From b485dd14956ea5d744be38cc5201b8a983be7582 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Fri, 28 Jun 2024 14:20:47 -0400 Subject: rewrite reproducible-build-2 to rmake --- src/tools/run-make-support/src/fs.rs | 22 ++++++++++++++++++++++ src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/run-make-support/src/fs.rs b/src/tools/run-make-support/src/fs.rs index 0a796161633..b896168b0a5 100644 --- a/src/tools/run-make-support/src/fs.rs +++ b/src/tools/run-make-support/src/fs.rs @@ -83,6 +83,28 @@ pub fn copy, Q: AsRef>(from: P, to: Q) { )); } +#[track_caller] +/// An extension of [`std::fs::copy`] which can copy a directory recursively. +pub fn copy_dir_all, Q: AsRef>(from: P, to: Q) { + create_dir_all(&to); + for entry in read_dir(from) { + let entry = entry.unwrap(); + let ty = entry.file_type().unwrap(); + if ty.is_dir() { + copy_dir_all(entry.path(), to.as_ref().join(entry.file_name())); + } else if ty.is_symlink() { + copy_symlink(entry.path(), to.as_ref().join(entry.file_name())); + } else { + copy(entry.path(), to.as_ref().join(entry.file_name())); + } + } +} + +fn copy_symlink, Q: AsRef>(from: P, to: Q) { + let target_path = fs::read_link(from).unwrap(); + std::os::unix::fs::symlink(target_path, to).unwrap(); +} + /// A wrapper around [`std::fs::File::create`] which includes the file path in the panic message. #[track_caller] pub fn create_file>(path: P) { diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 8747a6265c6..13230239796 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -41,7 +41,6 @@ run-make/raw-dylib-alt-calling-convention/Makefile run-make/raw-dylib-c/Makefile run-make/redundant-libs/Makefile run-make/remap-path-prefix-dwarf/Makefile -run-make/reproducible-build-2/Makefile run-make/reproducible-build/Makefile run-make/rlib-format-packed-bundled-libs/Makefile run-make/simd-ffi/Makefile -- cgit 1.4.1-3-g733a5 From 94da7b157a5ebcde7ee23f4bd2041307e579891f Mon Sep 17 00:00:00 2001 From: Oneirical Date: Fri, 28 Jun 2024 15:04:06 -0400 Subject: rewrite stable-symbol-names to rmake --- .../run-make-support/src/external_deps/llvm.rs | 3 +- src/tools/run-make-support/src/fs.rs | 48 +++++++-------- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/reproducible-build-2/rmake.rs | 26 +++++---- tests/run-make/stable-symbol-names/Makefile | 41 ------------- tests/run-make/stable-symbol-names/rmake.rs | 68 ++++++++++++++++++++++ 6 files changed, 105 insertions(+), 82 deletions(-) delete mode 100644 tests/run-make/stable-symbol-names/Makefile create mode 100644 tests/run-make/stable-symbol-names/rmake.rs (limited to 'src') diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 259bb615946..bd01275598b 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -137,7 +137,8 @@ impl LlvmReadobj { self } - /// Pass `--symbols` to display the symbol. + /// Pass `--symbols` to display the symbol table, including both local + /// and global symbols. pub fn symbols(&mut self) -> &mut Self { self.cmd.arg("--symbols"); self diff --git a/src/tools/run-make-support/src/fs.rs b/src/tools/run-make-support/src/fs.rs index b896168b0a5..2c35ba52a62 100644 --- a/src/tools/run-make-support/src/fs.rs +++ b/src/tools/run-make-support/src/fs.rs @@ -9,11 +9,19 @@ pub fn create_symlink, Q: AsRef>(original: P, link: Q) { if link.as_ref().exists() { std::fs::remove_dir(link.as_ref()).unwrap(); } - std::os::windows::fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!( - "failed to create symlink {:?} for {:?}", - link.as_ref().display(), - original.as_ref().display(), - )); + if original.as_ref().is_file() { + std::os::windows::fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!( + "failed to create symlink {:?} for {:?}", + link.as_ref().display(), + original.as_ref().display(), + )); + } else { + std::os::windows::fs::symlink_dir(original.as_ref(), link.as_ref()).expect(&format!( + "failed to create symlink {:?} for {:?}", + link.as_ref().display(), + original.as_ref().display(), + )); + } } /// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix. @@ -41,6 +49,8 @@ pub fn copy_dir_all(src: impl AsRef, dst: impl AsRef) { let ty = entry.file_type()?; if ty.is_dir() { copy_dir_all_inner(entry.path(), dst.join(entry.file_name()))?; + } else if ty.is_symlink() { + copy_symlink(entry.path(), dst.join(entry.file_name()))?; } else { std::fs::copy(entry.path(), dst.join(entry.file_name()))?; } @@ -59,6 +69,12 @@ pub fn copy_dir_all(src: impl AsRef, dst: impl AsRef) { } } +fn copy_symlink, Q: AsRef>(from: P, to: Q) -> io::Result<()> { + let target_path = std::fs::read_link(from).unwrap(); + create_symlink(target_path, to); + Ok(()) +} + /// Helper for reading entries in a given directory. pub fn read_dir_entries, F: FnMut(&Path)>(dir: P, mut callback: F) { for entry in read_dir(dir) { @@ -83,28 +99,6 @@ pub fn copy, Q: AsRef>(from: P, to: Q) { )); } -#[track_caller] -/// An extension of [`std::fs::copy`] which can copy a directory recursively. -pub fn copy_dir_all, Q: AsRef>(from: P, to: Q) { - create_dir_all(&to); - for entry in read_dir(from) { - let entry = entry.unwrap(); - let ty = entry.file_type().unwrap(); - if ty.is_dir() { - copy_dir_all(entry.path(), to.as_ref().join(entry.file_name())); - } else if ty.is_symlink() { - copy_symlink(entry.path(), to.as_ref().join(entry.file_name())); - } else { - copy(entry.path(), to.as_ref().join(entry.file_name())); - } - } -} - -fn copy_symlink, Q: AsRef>(from: P, to: Q) { - let target_path = fs::read_link(from).unwrap(); - std::os::unix::fs::symlink(target_path, to).unwrap(); -} - /// A wrapper around [`std::fs::File::create`] which includes the file path in the panic message. #[track_caller] pub fn create_file>(path: P) { diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 13230239796..ea50d05e1da 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -45,7 +45,6 @@ run-make/reproducible-build/Makefile run-make/rlib-format-packed-bundled-libs/Makefile run-make/simd-ffi/Makefile run-make/split-debuginfo/Makefile -run-make/stable-symbol-names/Makefile run-make/staticlib-dylib-linkage/Makefile run-make/symbol-mangling-hashed/Makefile run-make/sysroot-crates-are-unstable/Makefile diff --git a/tests/run-make/reproducible-build-2/rmake.rs b/tests/run-make/reproducible-build-2/rmake.rs index 6286b607605..c500c4238b0 100644 --- a/tests/run-make/reproducible-build-2/rmake.rs +++ b/tests/run-make/reproducible-build-2/rmake.rs @@ -6,17 +6,22 @@ // Outputs should be identical. // See https://github.com/rust-lang/rust/issues/34902 -//FIXME(Oneirical): excluded ignore-musl ignore-windows ignore-cross-compile +//@ ignore-windows +// Reasons: +// 1. The object files are reproducible, but their paths are not, which causes +// the first assertion in the test to fail. +// 2. When the sysroot gets copied, some symlinks must be re-created, +// which is a privileged action on Windows. -use run_make_support::{fs_wrapper, rust_lib_name, rustc}; +use run_make_support::{bin_name, rfs, rust_lib_name, rustc}; fn main() { // test 1: fat lto rustc().input("reproducible-build-aux.rs").run(); - rustc().input("reproducible-build.rs").arg("-Clto=fat").run(); - fs_wrapper::rename("reproducible-build", "reproducible-build-a"); - rustc().input("reproducible-build.rs").arg("-Clto=fat").run(); - assert_eq!(fs_wrapper::read("reproducible-build"), fs_wrapper::read("reproducible-build-a")); + rustc().input("reproducible-build.rs").arg("-Clto=fat").output("reproducible-build").run(); + rfs::rename("reproducible-build", "reproducible-build-a"); + rustc().input("reproducible-build.rs").arg("-Clto=fat").output("reproducible-build").run(); + assert_eq!(rfs::read("reproducible-build"), rfs::read("reproducible-build-a")); // test 2: sysroot let sysroot = rustc().print("sysroot").run().stdout_utf8(); @@ -29,8 +34,8 @@ fn main() { .sysroot(&sysroot) .arg(format!("--remap-path-prefix={sysroot}=/sysroot")) .run(); - fs_wrapper::copy_dir_all(&sysroot, "sysroot"); - fs_wrapper::rename(rust_lib_name("reproducible_build"), rust_lib_name("foo")); + rfs::copy_dir_all(&sysroot, "sysroot"); + rfs::rename(rust_lib_name("reproducible_build"), rust_lib_name("foo")); rustc() .input("reproducible-build.rs") .crate_type("rlib") @@ -38,8 +43,5 @@ fn main() { .arg("--remap-path-prefix=/sysroot=/sysroot") .run(); - assert_eq!( - fs_wrapper::read(rust_lib_name("reproducible_build")), - fs_wrapper::read(rust_lib_name("foo")) - ); + assert_eq!(rfs::read(rust_lib_name("reproducible_build")), rfs::read(rust_lib_name("foo"))); } diff --git a/tests/run-make/stable-symbol-names/Makefile b/tests/run-make/stable-symbol-names/Makefile deleted file mode 100644 index bbfb8e38881..00000000000 --- a/tests/run-make/stable-symbol-names/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -include ../tools.mk - -# The following command will: -# 1. dump the symbols of a library using `nm` -# 2. extract only those lines that we are interested in via `grep` -# 3. from those lines, extract just the symbol name via `sed`, which: -# * always starts with "_ZN" and ends with "E" (`legacy` mangling) -# * always starts with "_R" (`v0` mangling) -# 4. sort those symbol names for deterministic comparison -# 5. write the result into a file - -dump-symbols = nm "$(TMPDIR)/lib$(1).rlib" \ - | grep -E "$(2)" \ - | sed -E "s/.*(_ZN.*E|_R[a-zA-Z0-9_]*).*/\1/" \ - | sort \ - > "$(TMPDIR)/$(1)$(3).nm" - -# This test -# - compiles each of the two crates 2 times and makes sure each time we get -# exactly the same symbol names -# - makes sure that both crates agree on the same symbol names for monomorphic -# functions - -all: - $(RUSTC) stable-symbol-names1.rs - $(call dump-symbols,stable_symbol_names1,generic_|mono_,_v1) - rm $(TMPDIR)/libstable_symbol_names1.rlib - $(RUSTC) stable-symbol-names1.rs - $(call dump-symbols,stable_symbol_names1,generic_|mono_,_v2) - cmp "$(TMPDIR)/stable_symbol_names1_v1.nm" "$(TMPDIR)/stable_symbol_names1_v2.nm" - - $(RUSTC) stable-symbol-names2.rs - $(call dump-symbols,stable_symbol_names2,generic_|mono_,_v1) - rm $(TMPDIR)/libstable_symbol_names2.rlib - $(RUSTC) stable-symbol-names2.rs - $(call dump-symbols,stable_symbol_names2,generic_|mono_,_v2) - cmp "$(TMPDIR)/stable_symbol_names2_v1.nm" "$(TMPDIR)/stable_symbol_names2_v2.nm" - - $(call dump-symbols,stable_symbol_names1,mono_,_cross) - $(call dump-symbols,stable_symbol_names2,mono_,_cross) - cmp "$(TMPDIR)/stable_symbol_names1_cross.nm" "$(TMPDIR)/stable_symbol_names2_cross.nm" diff --git a/tests/run-make/stable-symbol-names/rmake.rs b/tests/run-make/stable-symbol-names/rmake.rs new file mode 100644 index 00000000000..402f411c7f5 --- /dev/null +++ b/tests/run-make/stable-symbol-names/rmake.rs @@ -0,0 +1,68 @@ +// A typo in rustc caused generic symbol names to be non-deterministic - +// that is, it was possible to compile the same file twice with no changes +// and get outputs with different symbol names. +// This test compiles each of the two crates twice, and checks that each output +// contains exactly the same symbol names. +// Additionally, both crates should agree on the same symbol names for monomorphic +// functions. +// See https://github.com/rust-lang/rust/issues/32554 + +use std::collections::HashSet; + +use run_make_support::{llvm_readobj, regex, rfs, rust_lib_name, rustc}; + +static LEGACY_PATTERN: std::sync::OnceLock = std::sync::OnceLock::new(); +static V0_PATTERN: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn main() { + LEGACY_PATTERN.set(regex::Regex::new(r"_ZN.*E").unwrap()).unwrap(); + V0_PATTERN.set(regex::Regex::new(r"_R[a-zA-Z0-9_]*").unwrap()).unwrap(); + // test 1: first file + rustc().input("stable-symbol-names1.rs").run(); + let sym1 = process_symbols("stable_symbol_names1", "generic_|mono_"); + rfs::remove_file(rust_lib_name("stable_symbol_names1")); + rustc().input("stable-symbol-names1.rs").run(); + let sym2 = process_symbols("stable_symbol_names1", "generic_|mono_"); + assert_eq!(sym1, sym2); + + // test 2: second file + rustc().input("stable-symbol-names2.rs").run(); + let sym1 = process_symbols("stable_symbol_names2", "generic_|mono_"); + rfs::remove_file(rust_lib_name("stable_symbol_names2")); + rustc().input("stable-symbol-names2.rs").run(); + let sym2 = process_symbols("stable_symbol_names2", "generic_|mono_"); + assert_eq!(sym1, sym2); + + // test 3: crossed files + let sym1 = process_symbols("stable_symbol_names1", "mono_"); + let sym2 = process_symbols("stable_symbol_names2", "mono_"); + assert_eq!(sym1, sym2); +} + +#[track_caller] +fn process_symbols(path: &str, symbol: &str) -> Vec { + // Dump all symbols. + let out = llvm_readobj().input(rust_lib_name(path)).symbols().run().stdout_utf8(); + // Extract only lines containing `symbol`. + let symbol_regex = regex::Regex::new(symbol).unwrap(); + let out = out.lines().filter(|&line| symbol_regex.find(line).is_some()); + + // HashSet - duplicates should be excluded! + let mut symbols: HashSet = HashSet::new(); + // From those lines, extract just the symbol name via `regex`, which: + // * always starts with "_ZN" and ends with "E" (`legacy` mangling) + // * always starts with "_R" (`v0` mangling) + for line in out { + if let Some(mat) = LEGACY_PATTERN.get().unwrap().find(line) { + symbols.insert(mat.as_str().to_string()); + } + if let Some(mat) = V0_PATTERN.get().unwrap().find(line) { + symbols.insert(mat.as_str().to_string()); + } + } + + let mut symbols: Vec = symbols.into_iter().collect(); + // Sort those symbol names for deterministic comparison. + symbols.sort(); + symbols +} -- cgit 1.4.1-3-g733a5 From de26ad1a2a30a65d74b9bf433fc805e261c6ed53 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 26 Feb 2024 13:13:43 +0000 Subject: Promote riscv64gc-unknown-linux-musl to tier 2 --- src/ci/docker/host-x86_64/dist-various-2/Dockerfile | 14 ++++++++++++-- src/tools/build-manifest/src/main.rs | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 2621e9a6031..1b98d541693 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -24,7 +24,8 @@ RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no # Needed for apt-key to work: dirmngr \ gpg-agent \ - g++-9-arm-linux-gnueabi + g++-9-arm-linux-gnueabi \ + g++-11-riscv64-linux-gnu RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486 RUN add-apt-repository -y 'deb https://apt.dilos.org/dilos dilos2 main' @@ -73,6 +74,10 @@ RUN env \ CC=arm-linux-gnueabi-gcc-9 CFLAGS="-march=armv7-a" \ CXX=arm-linux-gnueabi-g++-9 CXXFLAGS="-march=armv7-a" \ bash musl.sh armv7 && \ + env \ + CC=riscv64-linux-gnu-gcc-11 \ + CXX=riscv64-linux-gnu-g++-11 \ + bash musl.sh riscv64gc && \ rm -rf /build/* WORKDIR /tmp @@ -125,6 +130,7 @@ ENV TARGETS=$TARGETS,x86_64-unknown-none ENV TARGETS=$TARGETS,aarch64-unknown-uefi ENV TARGETS=$TARGETS,i686-unknown-uefi ENV TARGETS=$TARGETS,x86_64-unknown-uefi +ENV TARGETS=$TARGETS,riscv64gc-unknown-linux-musl # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 # we need asm in the search path for gcc-9 (for gnux32) but not in the search path of the @@ -132,7 +138,11 @@ ENV TARGETS=$TARGETS,x86_64-unknown-uefi # Luckily one of the folders is /usr/local/include so symlink /usr/include/x86_64-linux-gnu/asm there RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm +# musl-gcc can't find libgcc_s.so.1 since it doesn't use the standard search paths. +RUN ln -s /usr/riscv64-linux-gnu/lib/libgcc_s.so.1 /usr/lib/gcc-cross/riscv64-linux-gnu/11/ + ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-llvm-bitcode-linker --disable-docs \ - --musl-root-armv7=/musl-armv7 + --musl-root-armv7=/musl-armv7 \ + --musl-root-riscv64gc=/musl-riscv64gc ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index ff475b9571b..2b263f848e8 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -141,6 +141,7 @@ static TARGETS: &[&str] = &[ "riscv64gc-unknown-hermit", "riscv64gc-unknown-none-elf", "riscv64gc-unknown-linux-gnu", + "riscv64gc-unknown-linux-musl", "s390x-unknown-linux-gnu", "sparc64-unknown-linux-gnu", "sparcv9-sun-solaris", -- cgit 1.4.1-3-g733a5 From 9963a6c400f7c5aa762e0b5419df756432f2e83b Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 22 Jun 2024 17:04:00 +0200 Subject: Add platform support document for riscv64gc-unknown-linux-musl --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 2 +- .../riscv64gc-unknown-linux-musl.md | 47 ++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md (limited to 'src') diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index d5141591b97..467fd6f43e4 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -66,6 +66,7 @@ - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md) - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md) + - [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f3b49a65aad..7fd1808a1f0 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -98,6 +98,7 @@ target | notes `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17) `powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17) [`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29) +[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20, musl 1.2.3) `s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17) `x86_64-unknown-freebsd` | 64-bit FreeBSD `x86_64-unknown-illumos` | illumos @@ -354,7 +355,6 @@ target | std | host | notes [`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit `riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD `riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia -`riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.3) [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 [`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md new file mode 100644 index 00000000000..5b3dc683038 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md @@ -0,0 +1,47 @@ +# riscv64gc-unknown-linux-musl + +**Tier: 2** + +Target for RISC-V Linux programs using musl libc. + +## Target maintainers + +- [@Amanieu](https://github.com/Amanieu) +- [@kraj](https://github.com/kraj) + +## Requirements + +Building the target itself requires a RISC-V compiler that is supported by `cc-rs`. + +## Building the target + +The target can be built by enabling it for a `rustc` build. + +```toml +[build] +target = ["riscv64gc-unknown-linux-musl"] +``` + +Make sure your C compiler is included in `$PATH`, then add it to the `config.toml`: + +```toml +[target.riscv64gc-unknown-linux-musl] +cc = "riscv64-linux-gnu-gcc" +cxx = "riscv64-linux-gnu-g++" +ar = "riscv64-linux-gnu-ar" +linker = "riscv64-linux-gnu-gcc" +``` + +## Building Rust programs + +This target are distributed through `rustup`, and otherwise require no +special configuration. + +## Cross-compilation + +This target can be cross-compiled from any host. + +## Testing + +This target can be tested as normal with `x.py` on a RISC-V host or via QEMU +emulation. -- cgit 1.4.1-3-g733a5 From f9d7e4c0a96f17a25e8246a22195ad86d796fb5d Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 3 Aug 2024 16:59:29 +0000 Subject: Remove cygpath from run-make-support --- .../run-make-support/src/external_deps/c_build.rs | 4 +-- src/tools/run-make-support/src/external_deps/cc.rs | 10 +++---- .../run-make-support/src/external_deps/cygpath.rs | 35 ---------------------- .../run-make-support/src/external_deps/mod.rs | 3 -- 4 files changed, 5 insertions(+), 47 deletions(-) delete mode 100644 src/tools/run-make-support/src/external_deps/cygpath.rs (limited to 'src') diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs index 15e02d04393..fb22780eaa0 100644 --- a/src/tools/run-make-support/src/external_deps/c_build.rs +++ b/src/tools/run-make-support/src/external_deps/c_build.rs @@ -1,6 +1,5 @@ use std::path::PathBuf; -use super::cygpath::get_windows_path; use crate::artifact_names::{dynamic_lib_name, static_lib_name}; use crate::external_deps::cc::{cc, cxx}; use crate::external_deps::llvm::llvm_ar; @@ -44,8 +43,7 @@ pub fn build_native_dynamic_lib(lib_name: &str) -> PathBuf { }; let obj_file = if is_msvc() { format!("{lib_name}.obj") } else { format!("{lib_name}.o") }; if is_msvc() { - let mut out_arg = "-out:".to_owned(); - out_arg.push_str(&get_windows_path(&lib_path)); + let out_arg = format!("-out:{lib_path}"); cc().input(&obj_file).args(&["-link", "-dll", &out_arg]).run(); } else if is_darwin() { cc().out_exe(&lib_path).input(&obj_file).args(&["-dynamiclib", "-Wl,-dylib"]).run(); diff --git a/src/tools/run-make-support/src/external_deps/cc.rs b/src/tools/run-make-support/src/external_deps/cc.rs index 39ac3efef39..36cef15781f 100644 --- a/src/tools/run-make-support/src/external_deps/cc.rs +++ b/src/tools/run-make-support/src/external_deps/cc.rs @@ -1,7 +1,5 @@ use std::path::Path; -// FIXME(jieyouxu): can we get rid of the `cygpath` external dependency? -use super::cygpath::get_windows_path; use crate::command::Command; use crate::{env_var, is_msvc, is_windows, uname}; @@ -97,12 +95,12 @@ impl Cc { if is_msvc() { path.set_extension("exe"); - let fe_path = get_windows_path(&path); + let fe_path = path.clone(); path.set_extension(""); path.set_extension("obj"); - let fo_path = get_windows_path(path); - self.cmd.arg(format!("-Fe:{fe_path}")); - self.cmd.arg(format!("-Fo:{fo_path}")); + let fo_path = path; + self.cmd.arg(format!("-Fe:{}", fe_path.to_str().unwrap())); + self.cmd.arg(format!("-Fo:{}", fo_path.to_str().unwrap())); } else { self.cmd.arg("-o"); self.cmd.arg(name); diff --git a/src/tools/run-make-support/src/external_deps/cygpath.rs b/src/tools/run-make-support/src/external_deps/cygpath.rs deleted file mode 100644 index 07d8e840a63..00000000000 --- a/src/tools/run-make-support/src/external_deps/cygpath.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::panic; -use std::path::Path; - -use crate::command::Command; -use crate::util::handle_failed_output; - -/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is -/// available on the platform! -/// -/// # FIXME -/// -/// FIXME(jieyouxu): we should consider not depending on `cygpath`. -/// -/// > The cygpath program is a utility that converts Windows native filenames to Cygwin POSIX-style -/// > pathnames and vice versa. -/// > -/// > [irrelevant entries omitted...] -/// > -/// > `-w, --windows print Windows form of NAMEs (C:\WINNT)` -/// > -/// > -- *from [cygpath documentation](https://cygwin.com/cygwin-ug-net/cygpath.html)*. -#[track_caller] -#[must_use] -pub fn get_windows_path>(path: P) -> String { - let caller = panic::Location::caller(); - let mut cygpath = Command::new("cygpath"); - cygpath.arg("-w"); - cygpath.arg(path.as_ref()); - let output = cygpath.run(); - if !output.status().success() { - handle_failed_output(&cygpath, output, caller.line()); - } - // cygpath -w can attach a newline - output.stdout_utf8().trim().to_string() -} diff --git a/src/tools/run-make-support/src/external_deps/mod.rs b/src/tools/run-make-support/src/external_deps/mod.rs index a2dc426f3f2..f7c84724d0e 100644 --- a/src/tools/run-make-support/src/external_deps/mod.rs +++ b/src/tools/run-make-support/src/external_deps/mod.rs @@ -9,6 +9,3 @@ pub mod llvm; pub mod python; pub mod rustc; pub mod rustdoc; - -// Library-internal external dependency. -mod cygpath; -- cgit 1.4.1-3-g733a5 From 2ac09692e7a79fa49031994351c36d70aa0e752e Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 4 Aug 2024 10:59:28 +0300 Subject: handle crates when they are not specified for std docs This fixes a regression from https://github.com/rust-lang/rust/pull/128182. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/doc.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 1541396bfdd..2cd5db706c2 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -599,6 +599,16 @@ impl Step for Std { fn run(self, builder: &Builder<'_>) { let stage = self.stage; let target = self.target; + let crates = if self.crates.is_empty() { + builder + .in_tree_crates("sysroot", Some(target)) + .iter() + .map(|c| c.name.to_string()) + .collect() + } else { + self.crates + }; + let out = match self.format { DocumentationFormat::Html => builder.doc_out(target), DocumentationFormat::Json => builder.json_doc_out(target), @@ -627,7 +637,7 @@ impl Step for Std { extra_args.push("--disable-minification"); } - doc_std(builder, self.format, stage, target, &out, &extra_args, &self.crates); + doc_std(builder, self.format, stage, target, &out, &extra_args, &crates); // Don't open if the format is json if let DocumentationFormat::Json = self.format { @@ -639,7 +649,7 @@ impl Step for Std { let index = out.join("std").join("index.html"); builder.open_in_browser(index); } else { - for requested_crate in &*self.crates { + for requested_crate in crates { if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) { let index = out.join(requested_crate).join("index.html"); builder.open_in_browser(index); -- cgit 1.4.1-3-g733a5 From 249d686c7005ebb4d05234e9db6d29c2923296e2 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 15:25:13 -0700 Subject: rustdoc: Rename `SelfTy` to `ReceiverTy` `SelfTy` makes it sound like it is literally the `Self` type, whereas in fact it may be `&Self` or other types. Plus, I want to use the name `SelfTy` for a new variant of `clean::Type`. Having both causes resolution conflicts or at least confusion. --- src/librustdoc/clean/types.rs | 10 +++++----- src/librustdoc/html/format.rs | 2 +- src/librustdoc/html/render/mod.rs | 14 +++++++------- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7d5a16bc7e3..32e795e565e 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -34,7 +34,7 @@ use thin_vec::ThinVec; use {rustc_ast as ast, rustc_hir as hir}; pub(crate) use self::ItemKind::*; -pub(crate) use self::SelfTy::*; +pub(crate) use self::ReceiverTy::*; pub(crate) use self::Type::{ Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath, RawPointer, Slice, Tuple, @@ -1384,8 +1384,8 @@ pub(crate) struct FnDecl { } impl FnDecl { - pub(crate) fn self_type(&self) -> Option { - self.inputs.values.get(0).and_then(|v| v.to_self()) + pub(crate) fn receiver_type(&self) -> Option { + self.inputs.values.get(0).and_then(|v| v.to_receiver()) } } @@ -1404,14 +1404,14 @@ pub(crate) struct Argument { } #[derive(Clone, PartialEq, Debug)] -pub(crate) enum SelfTy { +pub(crate) enum ReceiverTy { SelfValue, SelfBorrowed(Option, Mutability), SelfExplicit(Type), } impl Argument { - pub(crate) fn to_self(&self) -> Option { + pub(crate) fn to_receiver(&self) -> Option { if self.name != kw::SelfLower { return None; } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index bb5ac303ffd..6476c8bd7c0 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1452,7 +1452,7 @@ impl clean::FnDecl { let last_input_index = self.inputs.values.len().checked_sub(1); for (i, input) in self.inputs.values.iter().enumerate() { - if let Some(selfty) = input.to_self() { + if let Some(selfty) = input.to_receiver() { match selfty { clean::SelfValue => { write!(f, "self")?; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 9617f0d9a1f..b7bcda2a604 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -58,7 +58,7 @@ use serde::{Serialize, Serializer}; pub(crate) use self::context::*; pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc}; -use crate::clean::{self, ItemId, RenderedLink, SelfTy}; +use crate::clean::{self, ItemId, ReceiverTy, RenderedLink}; use crate::error::Error; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; @@ -1372,21 +1372,21 @@ fn render_deref_methods( fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool { let self_type_opt = match *item.kind { - clean::MethodItem(ref method, _) => method.decl.self_type(), - clean::TyMethodItem(ref method) => method.decl.self_type(), + clean::MethodItem(ref method, _) => method.decl.receiver_type(), + clean::TyMethodItem(ref method) => method.decl.receiver_type(), _ => None, }; if let Some(self_ty) = self_type_opt { let (by_mut_ref, by_box, by_value) = match self_ty { - SelfTy::SelfBorrowed(_, mutability) - | SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => { + ReceiverTy::SelfBorrowed(_, mutability) + | ReceiverTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => { (mutability == Mutability::Mut, false, false) } - SelfTy::SelfExplicit(clean::Type::Path { path }) => { + ReceiverTy::SelfExplicit(clean::Type::Path { path }) => { (false, Some(path.def_id()) == tcx.lang_items().owned_box(), false) } - SelfTy::SelfValue => (false, false, true), + ReceiverTy::SelfValue => (false, false, true), _ => (false, false, false), }; -- cgit 1.4.1-3-g733a5 From 664b3ffbe932d93677ac7dff52252e02aee60ef9 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 16:45:05 -0700 Subject: rustdoc: Create `SelfTy` to replace `Generic(kw::SelfUpper)` Rustdoc often has to special-case `Self` because it is, well, a special type of generic parameter (although it also behaves as an alias in concrete impls). Instead of spreading this special-casing throughout the code base, create a new variant of the `clean::Type` enum that is for `Self` types. This is a refactoring that has almost no impact on rustdoc's behavior, except that `&Self`, `(Self,)`, `&[Self]`, and other similar occurrences of `Self` no longer link to the wrapping type (reference primitive, tuple primitive, etc.) as regular generics do. I felt this made more sense since users would expect `Self` to link to the containing trait or aliased type (though those are usually expanded), not the primitive that is wrapping it. For an example of the change, see the docs for `std::alloc::Allocator::by_ref`. --- src/librustdoc/clean/inline.rs | 16 +++++----------- src/librustdoc/clean/mod.rs | 11 ++++++----- src/librustdoc/clean/simplify.rs | 1 - src/librustdoc/clean/types.rs | 10 +++++++--- src/librustdoc/clean/utils.rs | 2 +- src/librustdoc/html/format.rs | 1 + src/librustdoc/html/render/search_index.rs | 15 ++++++++++++--- src/librustdoc/json/conversions.rs | 4 +++- 8 files changed, 35 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d92bc845664..f8953f0ebcf 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::hygiene::MacroKind; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{sym, Symbol}; use thin_vec::{thin_vec, ThinVec}; use {rustc_ast as ast, rustc_hir as hir}; @@ -792,11 +792,7 @@ fn build_macro( fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics { for pred in &mut g.where_predicates { match *pred { - clean::WherePredicate::BoundPredicate { - ty: clean::Generic(ref s), - ref mut bounds, - .. - } if *s == kw::SelfUpper => { + clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref mut bounds, .. } => { bounds.retain(|bound| match bound { clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => { trait_.def_id() != trait_did @@ -812,13 +808,13 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: clean::WherePredicate::BoundPredicate { ty: clean::QPath(box clean::QPathData { - self_type: clean::Generic(ref s), + self_type: clean::Generic(_), trait_: Some(trait_), .. }), bounds, .. - } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did), + } => !bounds.is_empty() && trait_.def_id() != trait_did, _ => true, }); g @@ -832,9 +828,7 @@ fn separate_supertrait_bounds( ) -> (clean::Generics, Vec) { let mut ty_bounds = Vec::new(); g.where_predicates.retain(|pred| match *pred { - clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds, .. } - if *s == kw::SelfUpper => - { + clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => { ty_bounds.extend(bounds.iter().cloned()); false } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 324b633e8ea..cffadc7c10a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1351,11 +1351,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( let self_arg_ty = tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder(); if self_arg_ty == self_ty { - item.decl.inputs.values[0].type_ = Generic(kw::SelfUpper); + item.decl.inputs.values[0].type_ = SelfTy; } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() { if ty == self_ty { match item.decl.inputs.values[0].type_ { - BorrowedRef { ref mut type_, .. } => **type_ = Generic(kw::SelfUpper), + BorrowedRef { ref mut type_, .. } => **type_ = SelfTy, _ => unreachable!(), } } @@ -1439,9 +1439,8 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( if trait_.def_id() != assoc_item.container_id(tcx) { return true; } - match *self_type { - Generic(ref s) if *s == kw::SelfUpper => {} - _ => return true, + if *self_type != SelfTy { + return true; } match &assoc.args { GenericArgs::AngleBracketed { args, constraints } => { @@ -2228,6 +2227,8 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Param(ref p) => { if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) { ImplTrait(bounds) + } else if p.name == kw::SelfUpper { + SelfTy } else { Generic(p.name) } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 739f6eb8cc8..1d81ae3eb8b 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -145,7 +145,6 @@ pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generi // should be handled when cleaning associated types. generics.where_predicates.retain(|pred| { if let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = pred - && *param != rustc_span::symbol::kw::SelfUpper && bounds.iter().any(|b| b.is_sized_bound(cx)) { sized_params.insert(*param); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 32e795e565e..82f1312364a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -37,7 +37,7 @@ pub(crate) use self::ItemKind::*; pub(crate) use self::ReceiverTy::*; pub(crate) use self::Type::{ Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath, - RawPointer, Slice, Tuple, + RawPointer, SelfTy, Slice, Tuple, }; use crate::clean::cfg::Cfg; use crate::clean::clean_middle_path; @@ -1477,6 +1477,8 @@ pub(crate) enum Type { DynTrait(Vec, Option), /// A type parameter. Generic(Symbol), + /// The `Self` type. + SelfTy, /// A primitive (aka, builtin) type. Primitive(PrimitiveType), /// A function pointer: `extern "ABI" fn(...) -> ...` @@ -1571,6 +1573,8 @@ impl Type { // If both sides are generic, this returns true. (_, Type::Generic(_)) => true, (Type::Generic(_), _) => false, + // `Self` only matches itself. + (Type::SelfTy, Type::SelfTy) => true, // Paths account for both the path itself and its generics. (Type::Path { path: a }, Type::Path { path: b }) => { a.def_id() == b.def_id() @@ -1642,7 +1646,7 @@ impl Type { pub(crate) fn is_self_type(&self) -> bool { match *self { - Generic(name) => name == kw::SelfUpper, + SelfTy => true, _ => false, } } @@ -1700,7 +1704,7 @@ impl Type { Type::Pat(..) => PrimitiveType::Pat, RawPointer(..) => PrimitiveType::RawPointer, QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache), - Generic(_) | Infer | ImplTrait(_) => return None, + Generic(_) | SelfTy | Infer | ImplTrait(_) => return None, }; Primitive(t).def_id(cache) } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 2dd3041ab4c..68266f3506a 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -468,7 +468,7 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type { match path.res { Res::PrimTy(p) => Primitive(PrimitiveType::from(p)), Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } if path.segments.len() == 1 => { - Generic(kw::SelfUpper) + Type::SelfTy } Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name), _ => { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6476c8bd7c0..0fe535ade9b 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1006,6 +1006,7 @@ fn fmt_type<'cx>( match *t { clean::Generic(name) => f.write_str(name.as_str()), + clean::SelfTy => f.write_str("Self"), clean::Type::Path { ref path } => { // Paths like `T::Output` and `Self::Output` should be rendered with all segments. let did = path.def_id(); diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index b3f4d82e054..fc3d6c99b80 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -797,7 +797,11 @@ fn get_index_type_id( } } // Not supported yet - clean::Type::Pat(..) | clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None, + clean::Type::Pat(..) + | clean::Generic(_) + | clean::SelfTy + | clean::ImplTrait(_) + | clean::Infer => None, } } @@ -848,13 +852,18 @@ fn simplify_fn_type<'tcx, 'a>( (false, arg) }; + let as_arg_s = |t: &Type| match *t { + Type::Generic(arg_s) => Some(arg_s), + Type::SelfTy => Some(kw::SelfUpper), + _ => None, + }; // If this argument is a type parameter and not a trait bound or a type, we need to look // for its bounds. - if let Type::Generic(arg_s) = *arg { + if let Some(arg_s) = as_arg_s(arg) { // First we check if the bounds are in a `where` predicate... let mut type_bounds = Vec::new(); for where_pred in generics.where_predicates.iter().filter(|g| match g { - WherePredicate::BoundPredicate { ty: Type::Generic(ty_s), .. } => *ty_s == arg_s, + WherePredicate::BoundPredicate { ty, .. } => *ty == *arg, _ => false, }) { let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index b56244f2d3b..b97d710c007 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -578,7 +578,7 @@ impl FromWithTcx for Type { fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { use clean::Type::{ Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath, - RawPointer, Slice, Tuple, + RawPointer, SelfTy, Slice, Tuple, }; match ty { @@ -588,6 +588,8 @@ impl FromWithTcx for Type { traits: bounds.into_tcx(tcx), }), Generic(s) => Type::Generic(s.to_string()), + // FIXME: add dedicated variant to json Type? + SelfTy => Type::Generic("Self".to_owned()), Primitive(p) => Type::Primitive(p.as_sym().to_string()), BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))), Tuple(t) => Type::Tuple(t.into_tcx(tcx)), -- cgit 1.4.1-3-g733a5 From 4e348fa803723a38553138d9795cb2c6b7fb964a Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 17:06:32 -0700 Subject: rustdoc: Stop treating `Self` as a generic in search index We already have special-cased code to handle inlining `Self` as the type or trait it refers to, and this was just causing glitches like the search `A -> B` yielding blanket `Into` impls. --- src/librustdoc/html/render/search_index.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index fc3d6c99b80..e4d948b8c9c 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -852,14 +852,9 @@ fn simplify_fn_type<'tcx, 'a>( (false, arg) }; - let as_arg_s = |t: &Type| match *t { - Type::Generic(arg_s) => Some(arg_s), - Type::SelfTy => Some(kw::SelfUpper), - _ => None, - }; // If this argument is a type parameter and not a trait bound or a type, we need to look // for its bounds. - if let Some(arg_s) = as_arg_s(arg) { + if let Type::Generic(arg_s) = *arg { // First we check if the bounds are in a `where` predicate... let mut type_bounds = Vec::new(); for where_pred in generics.where_predicates.iter().filter(|g| match g { -- cgit 1.4.1-3-g733a5 From e452e3def69deca6a671b6067b1faf14b4cf83f2 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 17:17:14 -0700 Subject: Use `match` instead of sequence of `if let`s This is much more readable and idiomatic, and also may help performance since `match`es usually use switches while `if`s may not. I also fixed an incorrect comment. --- src/librustdoc/html/render/search_index.rs | 477 +++++++++++++++-------------- 1 file changed, 243 insertions(+), 234 deletions(-) (limited to 'src') diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index e4d948b8c9c..8a2f31f7413 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -854,34 +854,70 @@ fn simplify_fn_type<'tcx, 'a>( // If this argument is a type parameter and not a trait bound or a type, we need to look // for its bounds. - if let Type::Generic(arg_s) = *arg { - // First we check if the bounds are in a `where` predicate... - let mut type_bounds = Vec::new(); - for where_pred in generics.where_predicates.iter().filter(|g| match g { - WherePredicate::BoundPredicate { ty, .. } => *ty == *arg, - _ => false, - }) { - let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); - for bound in bounds.iter() { - if let Some(path) = bound.get_trait_path() { - let ty = Type::Path { path }; - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut type_bounds, - rgen, - is_return, - cache, - ); + match *arg { + Type::Generic(arg_s) => { + // First we check if the bounds are in a `where` predicate... + let mut type_bounds = Vec::new(); + for where_pred in generics.where_predicates.iter().filter(|g| match g { + WherePredicate::BoundPredicate { ty, .. } => *ty == *arg, + _ => false, + }) { + let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); + for bound in bounds.iter() { + if let Some(path) = bound.get_trait_path() { + let ty = Type::Path { path }; + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut type_bounds, + rgen, + is_return, + cache, + ); + } + } + } + // Otherwise we check if the trait bounds are "inlined" like `T: Option`... + if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { + for bound in bound.get_bounds().unwrap_or(&[]) { + if let Some(path) = bound.get_trait_path() { + let ty = Type::Path { path }; + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut type_bounds, + rgen, + is_return, + cache, + ); + } } } + if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) { + res.push(RenderType { + id: Some(RenderTypeId::Index(*idx)), + generics: None, + bindings: None, + }); + } else { + let idx = -isize::try_from(rgen.len() + 1).unwrap(); + rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds)); + res.push(RenderType { + id: Some(RenderTypeId::Index(idx)), + generics: None, + bindings: None, + }); + } } - // Otherwise we check if the trait bounds are "inlined" like `T: Option`... - if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { - for bound in bound.get_bounds().unwrap_or(&[]) { + Type::ImplTrait(ref bounds) => { + let mut type_bounds = Vec::new(); + for bound in bounds { if let Some(path) = bound.get_trait_path() { let ty = Type::Path { path }; simplify_fn_type( @@ -897,84 +933,22 @@ fn simplify_fn_type<'tcx, 'a>( ); } } - } - if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) { - res.push(RenderType { - id: Some(RenderTypeId::Index(*idx)), - generics: None, - bindings: None, - }); - } else { - let idx = -isize::try_from(rgen.len() + 1).unwrap(); - rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds)); - res.push(RenderType { - id: Some(RenderTypeId::Index(idx)), - generics: None, - bindings: None, - }); - } - } else if let Type::ImplTrait(ref bounds) = *arg { - let mut type_bounds = Vec::new(); - for bound in bounds { - if let Some(path) = bound.get_trait_path() { - let ty = Type::Path { path }; - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut type_bounds, - rgen, - is_return, - cache, - ); + if is_return && !type_bounds.is_empty() { + // In return position, `impl Trait` is a unique thing. + res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None }); + } else { + // In parameter position, `impl Trait` is the same as an unnamed generic parameter. + let idx = -isize::try_from(rgen.len() + 1).unwrap(); + rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds)); + res.push(RenderType { + id: Some(RenderTypeId::Index(idx)), + generics: None, + bindings: None, + }); } } - if is_return && !type_bounds.is_empty() { - // In parameter position, `impl Trait` is a unique thing. - res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None }); - } else { - // In parameter position, `impl Trait` is the same as an unnamed generic parameter. - let idx = -isize::try_from(rgen.len() + 1).unwrap(); - rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds)); - res.push(RenderType { - id: Some(RenderTypeId::Index(idx)), - generics: None, - bindings: None, - }); - } - } else if let Type::Slice(ref ty) = *arg { - let mut ty_generics = Vec::new(); - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - res.push(get_index_type(arg, ty_generics, rgen)); - } else if let Type::Array(ref ty, _) = *arg { - let mut ty_generics = Vec::new(); - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - res.push(get_index_type(arg, ty_generics, rgen)); - } else if let Type::Tuple(ref tys) = *arg { - let mut ty_generics = Vec::new(); - for ty in tys { + Type::Slice(ref ty) => { + let mut ty_generics = Vec::new(); simplify_fn_type( self_, generics, @@ -986,15 +960,14 @@ fn simplify_fn_type<'tcx, 'a>( is_return, cache, ); + res.push(get_index_type(arg, ty_generics, rgen)); } - res.push(get_index_type(arg, ty_generics, rgen)); - } else if let Type::BareFunction(ref bf) = *arg { - let mut ty_generics = Vec::new(); - for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) { + Type::Array(ref ty, _) => { + let mut ty_generics = Vec::new(); simplify_fn_type( self_, generics, - ty, + &ty, tcx, recurse + 1, &mut ty_generics, @@ -1002,62 +975,11 @@ fn simplify_fn_type<'tcx, 'a>( is_return, cache, ); + res.push(get_index_type(arg, ty_generics, rgen)); } - // The search index, for simplicity's sake, represents fn pointers and closures - // the same way: as a tuple for the parameters, and an associated type for the - // return type. - let mut ty_output = Vec::new(); - simplify_fn_type( - self_, - generics, - &bf.decl.output, - tcx, - recurse + 1, - &mut ty_output, - rgen, - is_return, - cache, - ); - let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)]; - res.push(RenderType { - id: get_index_type_id(&arg, rgen), - bindings: Some(ty_bindings), - generics: Some(ty_generics), - }); - } else if let Type::BorrowedRef { lifetime: _, mutability, ref type_ } = *arg { - let mut ty_generics = Vec::new(); - if mutability.is_mut() { - ty_generics.push(RenderType { - id: Some(RenderTypeId::Mut), - generics: None, - bindings: None, - }); - } - simplify_fn_type( - self_, - generics, - &type_, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - res.push(get_index_type(arg, ty_generics, rgen)); - } else { - // This is not a type parameter. So for example if we have `T, U: Option`, and we're - // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't. - // - // So in here, we can add it directly and look for its own type parameters (so for `Option`, - // we will look for them but not for `T`). - let mut ty_generics = Vec::new(); - let mut ty_constraints = Vec::new(); - if let Some(arg_generics) = arg.generic_args() { - for ty in arg_generics.into_iter().filter_map(|param| match param { - clean::GenericArg::Type(ty) => Some(ty), - _ => None, - }) { + Type::Tuple(ref tys) => { + let mut ty_generics = Vec::new(); + for ty in tys { simplify_fn_type( self_, generics, @@ -1070,94 +992,181 @@ fn simplify_fn_type<'tcx, 'a>( cache, ); } - for constraint in arg_generics.constraints() { - simplify_fn_constraint( + res.push(get_index_type(arg, ty_generics, rgen)); + } + Type::BareFunction(ref bf) => { + let mut ty_generics = Vec::new(); + for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) { + simplify_fn_type( self_, generics, - &constraint, + ty, tcx, recurse + 1, - &mut ty_constraints, + &mut ty_generics, rgen, is_return, cache, ); } + // The search index, for simplicity's sake, represents fn pointers and closures + // the same way: as a tuple for the parameters, and an associated type for the + // return type. + let mut ty_output = Vec::new(); + simplify_fn_type( + self_, + generics, + &bf.decl.output, + tcx, + recurse + 1, + &mut ty_output, + rgen, + is_return, + cache, + ); + let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)]; + res.push(RenderType { + id: get_index_type_id(&arg, rgen), + bindings: Some(ty_bindings), + generics: Some(ty_generics), + }); } - // Every trait associated type on self gets assigned to a type parameter index - // this same one is used later for any appearances of these types - // - // for example, Iterator::next is: - // - // trait Iterator { - // fn next(&mut self) -> Option - // } - // - // Self is technically just Iterator, but we want to pretend it's more like this: - // - // fn next(self: Iterator) -> Option - if is_self - && let Type::Path { path } = arg - && let def_id = path.def_id() - && let Some(trait_) = cache.traits.get(&def_id) - && trait_.items.iter().any(|at| at.is_ty_associated_type()) - { - for assoc_ty in &trait_.items { - if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind - && let Some(name) = assoc_ty.name - { - let idx = -isize::try_from(rgen.len() + 1).unwrap(); - let (idx, stored_bounds) = rgen - .entry(SimplifiedParam::AssociatedType(def_id, name)) - .or_insert_with(|| (idx, Vec::new())); - let idx = *idx; - if stored_bounds.is_empty() { - // Can't just pass stored_bounds to simplify_fn_type, - // because it also accepts rgen as a parameter. - // Instead, have it fill in this local, then copy it into the map afterward. - let mut type_bounds = Vec::new(); - for bound in bounds { - if let Some(path) = bound.get_trait_path() { - let ty = Type::Path { path }; - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut type_bounds, - rgen, - is_return, - cache, - ); - } - } - let stored_bounds = &mut rgen - .get_mut(&SimplifiedParam::AssociatedType(def_id, name)) - .unwrap() - .1; + Type::BorrowedRef { lifetime: _, mutability, ref type_ } => { + let mut ty_generics = Vec::new(); + if mutability.is_mut() { + ty_generics.push(RenderType { + id: Some(RenderTypeId::Mut), + generics: None, + bindings: None, + }); + } + simplify_fn_type( + self_, + generics, + &type_, + tcx, + recurse + 1, + &mut ty_generics, + rgen, + is_return, + cache, + ); + res.push(get_index_type(arg, ty_generics, rgen)); + } + _ => { + // This is not a type parameter. So for example if we have `T, U: Option`, and we're + // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't. + // + // So in here, we can add it directly and look for its own type parameters (so for `Option`, + // we will look for them but not for `T`). + let mut ty_generics = Vec::new(); + let mut ty_constraints = Vec::new(); + if let Some(arg_generics) = arg.generic_args() { + for ty in arg_generics.into_iter().filter_map(|param| match param { + clean::GenericArg::Type(ty) => Some(ty), + _ => None, + }) { + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut ty_generics, + rgen, + is_return, + cache, + ); + } + for constraint in arg_generics.constraints() { + simplify_fn_constraint( + self_, + generics, + &constraint, + tcx, + recurse + 1, + &mut ty_constraints, + rgen, + is_return, + cache, + ); + } + } + // Every trait associated type on self gets assigned to a type parameter index + // this same one is used later for any appearances of these types + // + // for example, Iterator::next is: + // + // trait Iterator { + // fn next(&mut self) -> Option + // } + // + // Self is technically just Iterator, but we want to pretend it's more like this: + // + // fn next(self: Iterator) -> Option + if is_self + && let Type::Path { path } = arg + && let def_id = path.def_id() + && let Some(trait_) = cache.traits.get(&def_id) + && trait_.items.iter().any(|at| at.is_ty_associated_type()) + { + for assoc_ty in &trait_.items { + if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind + && let Some(name) = assoc_ty.name + { + let idx = -isize::try_from(rgen.len() + 1).unwrap(); + let (idx, stored_bounds) = rgen + .entry(SimplifiedParam::AssociatedType(def_id, name)) + .or_insert_with(|| (idx, Vec::new())); + let idx = *idx; if stored_bounds.is_empty() { - *stored_bounds = type_bounds; + // Can't just pass stored_bounds to simplify_fn_type, + // because it also accepts rgen as a parameter. + // Instead, have it fill in this local, then copy it into the map afterward. + let mut type_bounds = Vec::new(); + for bound in bounds { + if let Some(path) = bound.get_trait_path() { + let ty = Type::Path { path }; + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut type_bounds, + rgen, + is_return, + cache, + ); + } + } + let stored_bounds = &mut rgen + .get_mut(&SimplifiedParam::AssociatedType(def_id, name)) + .unwrap() + .1; + if stored_bounds.is_empty() { + *stored_bounds = type_bounds; + } } + ty_constraints.push(( + RenderTypeId::AssociatedType(name), + vec![RenderType { + id: Some(RenderTypeId::Index(idx)), + generics: None, + bindings: None, + }], + )) } - ty_constraints.push(( - RenderTypeId::AssociatedType(name), - vec![RenderType { - id: Some(RenderTypeId::Index(idx)), - generics: None, - bindings: None, - }], - )) } } - } - let id = get_index_type_id(&arg, rgen); - if id.is_some() || !ty_generics.is_empty() { - res.push(RenderType { - id, - bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) }, - generics: if ty_generics.is_empty() { None } else { Some(ty_generics) }, - }); + let id = get_index_type_id(&arg, rgen); + if id.is_some() || !ty_generics.is_empty() { + res.push(RenderType { + id, + bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) }, + generics: if ty_generics.is_empty() { None } else { Some(ty_generics) }, + }); + } } } } -- cgit 1.4.1-3-g733a5 From b4f77df9f8540f48744794c641e12ef66e0e57ba Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 17:33:13 -0700 Subject: rustdoc: Delete `ReceiverTy` (formerly known as `SelfTy`) It was barely used, and the places that used it are actually clearer without it since they were often undoing some of its work. This also avoids an unnecessary clone of the receiver type and removes a layer of logical indirection in the code. --- src/librustdoc/clean/types.rs | 25 +++---------------------- src/librustdoc/html/format.rs | 27 ++++++++++----------------- src/librustdoc/html/render/mod.rs | 11 +++++------ 3 files changed, 18 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 82f1312364a..4850500a1bf 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -34,7 +34,6 @@ use thin_vec::ThinVec; use {rustc_ast as ast, rustc_hir as hir}; pub(crate) use self::ItemKind::*; -pub(crate) use self::ReceiverTy::*; pub(crate) use self::Type::{ Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath, RawPointer, SelfTy, Slice, Tuple, @@ -1384,7 +1383,7 @@ pub(crate) struct FnDecl { } impl FnDecl { - pub(crate) fn receiver_type(&self) -> Option { + pub(crate) fn receiver_type(&self) -> Option<&Type> { self.inputs.values.get(0).and_then(|v| v.to_receiver()) } } @@ -1403,27 +1402,9 @@ pub(crate) struct Argument { pub(crate) is_const: bool, } -#[derive(Clone, PartialEq, Debug)] -pub(crate) enum ReceiverTy { - SelfValue, - SelfBorrowed(Option, Mutability), - SelfExplicit(Type), -} - impl Argument { - pub(crate) fn to_receiver(&self) -> Option { - if self.name != kw::SelfLower { - return None; - } - if self.type_.is_self_type() { - return Some(SelfValue); - } - match self.type_ { - BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => { - Some(SelfBorrowed(lifetime.clone(), mutability)) - } - _ => Some(SelfExplicit(self.type_.clone())), - } + pub(crate) fn to_receiver(&self) -> Option<&Type> { + if self.name == kw::SelfLower { Some(&self.type_) } else { None } } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 0fe535ade9b..b5ab6a35fdb 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1455,27 +1455,20 @@ impl clean::FnDecl { for (i, input) in self.inputs.values.iter().enumerate() { if let Some(selfty) = input.to_receiver() { match selfty { - clean::SelfValue => { + clean::SelfTy => { write!(f, "self")?; } - clean::SelfBorrowed(Some(ref lt), mutability) => { - write!( - f, - "{amp}{lifetime} {mutability}self", - lifetime = lt.print(), - mutability = mutability.print_with_space(), - )?; - } - clean::SelfBorrowed(None, mutability) => { - write!( - f, - "{amp}{mutability}self", - mutability = mutability.print_with_space(), - )?; + clean::BorrowedRef { lifetime, mutability, type_: box clean::SelfTy } => { + write!(f, "{amp}")?; + match lifetime { + Some(lt) => write!(f, "{lt} ", lt = lt.print())?, + None => {} + } + write!(f, "{mutability}self", mutability = mutability.print_with_space())?; } - clean::SelfExplicit(ref typ) => { + _ => { write!(f, "self: ")?; - typ.print(cx).fmt(f)?; + selfty.print(cx).fmt(f)?; } } } else { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index b7bcda2a604..9074e40a536 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -58,7 +58,7 @@ use serde::{Serialize, Serializer}; pub(crate) use self::context::*; pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc}; -use crate::clean::{self, ItemId, ReceiverTy, RenderedLink}; +use crate::clean::{self, ItemId, RenderedLink}; use crate::error::Error; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; @@ -1378,15 +1378,14 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> }; if let Some(self_ty) = self_type_opt { - let (by_mut_ref, by_box, by_value) = match self_ty { - ReceiverTy::SelfBorrowed(_, mutability) - | ReceiverTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => { + let (by_mut_ref, by_box, by_value) = match *self_ty { + clean::Type::BorrowedRef { mutability, .. } => { (mutability == Mutability::Mut, false, false) } - ReceiverTy::SelfExplicit(clean::Type::Path { path }) => { + clean::Type::Path { ref path } => { (false, Some(path.def_id()) == tcx.lang_items().owned_box(), false) } - ReceiverTy::SelfValue => (false, false, true), + clean::Type::SelfTy => (false, false, true), _ => (false, false, false), }; -- cgit 1.4.1-3-g733a5 From 7499e21a1ef918ed503fb8c4e5ab5c808d71bb44 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Tue, 30 Jul 2024 12:27:15 +0100 Subject: rustdoc-json: discard non-local inherent impls --- src/librustdoc/formats/cache.rs | 38 +++++++++++++++----------------------- src/librustdoc/json/mod.rs | 6 ------ tests/rustdoc-json/the_smallest.rs | 5 +++++ 3 files changed, 20 insertions(+), 29 deletions(-) create mode 100644 tests/rustdoc-json/the_smallest.rs (limited to 'src') diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 9f284486616..fab45e977b0 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -442,16 +442,16 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // `public_items` map, so we can skip inserting into the // paths map if there was already an entry present and we're // not a public item. - if !self.cache.paths.contains_key(&item.item_id.expect_def_id()) + let item_def_id = item.item_id.expect_def_id(); + if !self.cache.paths.contains_key(&item_def_id) || self .cache .effective_visibilities - .is_directly_public(self.tcx, item.item_id.expect_def_id()) + .is_directly_public(self.tcx, item_def_id) { - self.cache.paths.insert( - item.item_id.expect_def_id(), - (self.cache.stack.clone(), item.type_()), - ); + self.cache + .paths + .insert(item_def_id, (self.cache.stack.clone(), item.type_())); } } } @@ -514,9 +514,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { && adt.is_fundamental() { for ty in generics { - if let Some(did) = ty.def_id(self.cache) { - dids.insert(did); - } + dids.extend(ty.def_id(self.cache)); } } } @@ -529,32 +527,26 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { .primitive_type() .and_then(|t| self.cache.primitive_locations.get(&t).cloned()); - if let Some(did) = did { - dids.insert(did); - } + dids.extend(did); } } if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { for bound in generics { - if let Some(did) = bound.def_id(self.cache) { - dids.insert(did); - } + dids.extend(bound.def_id(self.cache)); } } let impl_item = Impl { impl_item: item }; - if impl_item.trait_did().map_or(true, |d| self.cache.traits.contains_key(&d)) { + let impl_did = impl_item.def_id(); + let trait_did = impl_item.trait_did(); + if trait_did.map_or(true, |d| self.cache.traits.contains_key(&d)) { for did in dids { - if self.impl_ids.entry(did).or_default().insert(impl_item.def_id()) { - self.cache - .impls - .entry(did) - .or_insert_with(Vec::new) - .push(impl_item.clone()); + if self.impl_ids.entry(did).or_default().insert(impl_did) { + self.cache.impls.entry(did).or_default().push(impl_item.clone()); } } } else { - let trait_did = impl_item.trait_did().expect("no trait did"); + let trait_did = trait_did.expect("no trait did"); self.cache.orphan_trait_impls.push((trait_did, dids, impl_item)); } None diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 033f01864f1..3c3c16a563c 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -217,13 +217,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { fn after_krate(&mut self) -> Result<(), Error> { debug!("Done with crate"); - debug!("Adding Primitive impls"); - for primitive in Rc::clone(&self.cache).primitive_locations.values() { - self.get_impls(*primitive); - } - let e = ExternalCrate { crate_num: LOCAL_CRATE }; - let index = (*self.index).clone().into_inner(); debug!("Constructing Output"); diff --git a/tests/rustdoc-json/the_smallest.rs b/tests/rustdoc-json/the_smallest.rs new file mode 100644 index 00000000000..2f6f91e6e27 --- /dev/null +++ b/tests/rustdoc-json/the_smallest.rs @@ -0,0 +1,5 @@ +// This test asserts that `index` is not polluted with unrelated items. +// See https://github.com/rust-lang/rust/issues/114039 + +//@ count "$.index[*]" 1 +fn main() {} -- cgit 1.4.1-3-g733a5 From ab690d31ceeff606cb7d0359717b50c173c7b21e Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 5 Aug 2024 17:55:42 +0300 Subject: fix the invalid argument type in `helpers::get_closest_merge_base_commit` Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/helpers.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 16959ce7e82..65e75f114bb 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -536,8 +536,7 @@ pub fn get_closest_merge_base_commit( let merge_base = get_git_merge_base(config, source_dir).unwrap_or_else(|_| "HEAD".into()); - git.arg(Path::new("rev-list")); - git.args([&format!("--author={author}"), "-n1", "--first-parent", &merge_base]); + git.args(["rev-list", &format!("--author={author}"), "-n1", "--first-parent", &merge_base]); if !target_paths.is_empty() { git.arg("--").args(target_paths); -- cgit 1.4.1-3-g733a5 From 46896d6f667bad2307efe22a75fc39f040302ae5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2024 20:35:52 +0200 Subject: interpret: move nullary-op evaluation into operator.rs --- .../rustc_const_eval/src/const_eval/machine.rs | 2 +- .../rustc_const_eval/src/interpret/intrinsics.rs | 4 +- .../rustc_const_eval/src/interpret/operator.rs | 37 ++++++++++++++++++- compiler/rustc_const_eval/src/interpret/step.rs | 43 ++++------------------ src/tools/miri/src/intrinsics/mod.rs | 2 +- .../generic_const_exprs/issue-80742.stderr | 2 +- 6 files changed, 49 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 901149825bf..79e8e212776 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -458,7 +458,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { _unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option>> { // Shared intrinsics. - if ecx.emulate_intrinsic(instance, args, dest, target)? { + if ecx.eval_intrinsic(instance, args, dest, target)? { return Ok(None); } let intrinsic_name = ecx.tcx.item_name(instance.def_id()); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 16a0a76a316..9210ec4e16f 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -97,7 +97,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Returns `true` if emulation happened. /// Here we implement the intrinsics that are common to all Miri instances; individual machines can add their own /// intrinsic handling. - pub fn emulate_intrinsic( + pub fn eval_intrinsic( &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, M::Provenance>], @@ -447,7 +447,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok(true) } - pub(super) fn emulate_nondiverging_intrinsic( + pub(super) fn eval_nondiverging_intrinsic( &mut self, intrinsic: &NonDivergingIntrinsic<'tcx>, ) -> InterpResult<'tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index fe5869ad7fa..2f860f9f942 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -1,8 +1,9 @@ use either::Either; use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir::interpret::{InterpResult, Scalar}; +use rustc_middle::mir::NullOp; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, FloatTy, ScalarInt}; +use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::symbol::sym; use tracing::trace; @@ -480,4 +481,38 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } } + + pub fn nullary_op( + &self, + null_op: NullOp<'tcx>, + arg_ty: Ty<'tcx>, + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { + use rustc_middle::mir::NullOp::*; + + let layout = self.layout_of(arg_ty)?; + let usize_layout = || self.layout_of(self.tcx.types.usize).unwrap(); + + Ok(match null_op { + SizeOf => { + if !layout.abi.is_sized() { + span_bug!(self.cur_span(), "unsized type for `NullaryOp::SizeOf`"); + } + let val = layout.size.bytes(); + ImmTy::from_uint(val, usize_layout()) + } + AlignOf => { + if !layout.abi.is_sized() { + span_bug!(self.cur_span(), "unsized type for `NullaryOp::AlignOf`"); + } + let val = layout.align.abi.bytes(); + ImmTy::from_uint(val, usize_layout()) + } + OffsetOf(fields) => { + let val = + self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes(); + ImmTy::from_uint(val, usize_layout()) + } + UbChecks => ImmTy::from_bool(self.tcx.sess.ub_checks(), *self.tcx), + }) + } } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 211a7b23002..28cf1068f40 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -4,8 +4,7 @@ use either::Either; use rustc_index::IndexSlice; -use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::{bug, mir, span_bug}; +use rustc_middle::{bug, mir}; use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; use tracing::{info, instrument, trace}; @@ -94,7 +93,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { M::retag_place_contents(self, *kind, &dest)?; } - Intrinsic(box intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?, + Intrinsic(box intrinsic) => self.eval_nondiverging_intrinsic(intrinsic)?, // Evaluate the place expression, without reading from it. PlaceMention(box place) => { @@ -179,6 +178,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_immediate(*result, &dest)?; } + NullaryOp(null_op, ty) => { + let ty = self.instantiate_from_current_frame_and_normalize_erasing_regions(ty)?; + let val = self.nullary_op(null_op, ty)?; + self.write_immediate(*val, &dest)?; + } + Aggregate(box ref kind, ref operands) => { self.write_aggregate(kind, operands, &dest)?; } @@ -230,38 +235,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_immediate(*val, &dest)?; } - NullaryOp(ref null_op, ty) => { - let ty = self.instantiate_from_current_frame_and_normalize_erasing_regions(ty)?; - let layout = self.layout_of(ty)?; - if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op - && layout.is_unsized() - { - span_bug!( - self.frame().current_span(), - "{null_op:?} MIR operator called for unsized type {ty}", - ); - } - let val = match null_op { - mir::NullOp::SizeOf => { - let val = layout.size.bytes(); - Scalar::from_target_usize(val, self) - } - mir::NullOp::AlignOf => { - let val = layout.align.abi.bytes(); - Scalar::from_target_usize(val, self) - } - mir::NullOp::OffsetOf(fields) => { - let val = self - .tcx - .offset_of_subfield(self.param_env, layout, fields.iter()) - .bytes(); - Scalar::from_target_usize(val, self) - } - mir::NullOp::UbChecks => Scalar::from_bool(self.tcx.sess.ub_checks()), - }; - self.write_scalar(val, &dest)?; - } - ShallowInitBox(ref operand, _) => { let src = self.eval_operand(operand, None)?; let v = self.read_immediate(&src)?; diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index d60119e75f1..18b22827bdb 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -33,7 +33,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); // See if the core engine can handle this intrinsic. - if this.emulate_intrinsic(instance, args, dest, ret)? { + if this.eval_intrinsic(instance, args, dest, ret)? { return Ok(None); } let intrinsic_name = this.tcx.item_name(instance.def_id()); diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr index 8d59235e2f4..01529599d37 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -1,4 +1,4 @@ -error: internal compiler error: compiler/rustc_const_eval/src/interpret/step.rs:LL:CC: SizeOf MIR operator called for unsized type dyn Debug +error: internal compiler error: compiler/rustc_const_eval/src/interpret/operator.rs:LL:CC: unsized type for `NullaryOp::SizeOf` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL Box -- cgit 1.4.1-3-g733a5 From 2431949e2a406c8b3243620d72dd3eaaceafb325 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 6 Aug 2024 04:57:39 +0000 Subject: Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index b74f9759ebe..f6fbc9844f8 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -29e924841f06bb181d87494eba2783761bc1ddec +c9687a95a602091777e28703aa5abf20f1ce1797 -- cgit 1.4.1-3-g733a5