about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-27 20:49:23 +0000
committerbors <bors@rust-lang.org>2024-05-27 20:49:23 +0000
commit84b40fc908c3adc7e0e470b3fbaa264df0e122b8 (patch)
treee629d46a9de99a1b20e97ab7d3e4eafa2206f784
parentf00b02e6bbe63707503f058fb87cc3e2b25991ac (diff)
parent4966e1ae35fdc5feb908aab7845ecea3c5947340 (diff)
downloadrust-84b40fc908c3adc7e0e470b3fbaa264df0e122b8.tar.gz
rust-84b40fc908c3adc7e0e470b3fbaa264df0e122b8.zip
Auto merge of #125628 - matthiaskrgr:rollup-3zk9v3w, r=matthiaskrgr
Rollup of 4 pull requests

Successful merges:

 - #125339 (The number of tests does not depend on the architecture's pointer width)
 - #125542 (Migrate rustdoc verify output files)
 - #125616 (MIR validation: ensure that downcast projection is followed by field projection)
 - #125625 (Use grep to implement verify-line-endings)

Failed merges:

 - #125573 (Migrate `run-make/allow-warnings-cmdline-stability` to `rmake.rs`)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs4
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs26
-rwxr-xr-xsrc/ci/scripts/verify-line-endings.sh22
-rw-r--r--src/tools/miri/tests/panic/mir-validation.stderr2
-rw-r--r--src/tools/run-make-support/src/diff/mod.rs5
-rw-r--r--src/tools/run-make-support/src/lib.rs67
-rw-r--r--src/tools/run-make-support/src/rustdoc.rs7
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt1
-rw-r--r--src/tools/tidy/src/ui_tests.rs8
-rw-r--r--tests/run-make/rustdoc-verify-output-files/Makefile32
-rw-r--r--tests/run-make/rustdoc-verify-output-files/rmake.rs49
11 files changed, 168 insertions, 55 deletions
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 2b28496faec..2d485211433 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1008,8 +1008,8 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
 /// element:
 ///
 ///  - [`Downcast`](ProjectionElem::Downcast): This projection sets the place's variant index to the
-///    given one, and makes no other changes. A `Downcast` projection on a place with its variant
-///    index already set is not well-formed.
+///    given one, and makes no other changes. A `Downcast` projection must always be followed
+///    immediately by a `Field` projection.
 ///  - [`Field`](ProjectionElem::Field): `Field` projections take their parent place and create a
 ///    place referring to one of the fields of the type. The resulting address is the parent
 ///    address, plus the offset of the field. The type becomes the type of the field. If the parent
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 66cc65de647..6df32169eec 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -689,8 +689,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         if Some(adt_def.did()) == self.tcx.lang_items().dyn_metadata() {
                             self.fail(
                                 location,
-                                format!("You can't project to field {f:?} of `DynMetadata` because \
-                                         layout is weird and thinks it doesn't have fields."),
+                                format!(
+                                    "You can't project to field {f:?} of `DynMetadata` because \
+                                         layout is weird and thinks it doesn't have fields."
+                                ),
                             );
                         }
 
@@ -839,7 +841,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             && cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo)
             && place.projection[1..].contains(&ProjectionElem::Deref)
         {
-            self.fail(location, format!("{place:?}, has deref at the wrong place"));
+            self.fail(
+                location,
+                format!("place {place:?} has deref as a later projection (it is only permitted as the first projection)"),
+            );
+        }
+
+        // Ensure all downcast projections are followed by field projections.
+        let mut projections_iter = place.projection.iter();
+        while let Some(proj) = projections_iter.next() {
+            if matches!(proj, ProjectionElem::Downcast(..)) {
+                if !matches!(projections_iter.next(), Some(ProjectionElem::Field(..))) {
+                    self.fail(
+                        location,
+                        format!(
+                            "place {place:?} has `Downcast` projection not followed by `Field`"
+                        ),
+                    );
+                }
+            }
         }
 
         self.super_place(place, cntxt, location);
diff --git a/src/ci/scripts/verify-line-endings.sh b/src/ci/scripts/verify-line-endings.sh
index f3cac13ea48..5f4b4aeb0e4 100755
--- a/src/ci/scripts/verify-line-endings.sh
+++ b/src/ci/scripts/verify-line-endings.sh
@@ -4,21 +4,21 @@
 # We check both in rust-lang/rust and in a submodule to make sure both are
 # accurate. Submodules are checked out significantly later than the main
 # repository in this script, so settings can (and do!) change between then.
-#
-# Linux (and maybe macOS) builders don't currently have dos2unix so just only
-# run this step on Windows.
 
 set -euo pipefail
 IFS=$'\n\t'
 
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
-if isWindows; then
-    # print out the git configuration so we can better investigate failures in
-    # the following
-    git config --list --show-origin
-    dos2unix -ih Cargo.lock src/tools/rust-installer/install-template.sh
-    endings=$(dos2unix -ic Cargo.lock src/tools/rust-installer/install-template.sh)
-    # if endings has non-zero length, error out
-    if [ -n "$endings" ]; then exit 1 ; fi
+# print out the git configuration so we can better investigate failures in
+# the following
+git config --list --show-origin
+# -U is necessary on Windows to stop grep automatically converting the line ending
+endings=$(grep -Ul $(printf '\r$') Cargo.lock src/tools/cargo/Cargo.lock) || true
+# if endings has non-zero length, error out
+if [[ -n $endings ]]; then
+    echo "Error: found DOS line endings"
+    # Print the files with DOS line endings
+    echo "$endings"
+    exit 1
 fi
diff --git a/src/tools/miri/tests/panic/mir-validation.stderr b/src/tools/miri/tests/panic/mir-validation.stderr
index d5dd53d7b4e..534e2d5881f 100644
--- a/src/tools/miri/tests/panic/mir-validation.stderr
+++ b/src/tools/miri/tests/panic/mir-validation.stderr
@@ -1,6 +1,6 @@
 thread 'rustc' panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC:
 broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]:
-(*(_2.0: *mut i32)), has deref at the wrong place
+place (*(_2.0: *mut i32)) has deref as a later projection (it is only permitted as the first projection)
 stack backtrace:
 
 error: the compiler unexpectedly panicked. this is a bug.
diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs
index 332126939c0..d864ddf4eb1 100644
--- a/src/tools/run-make-support/src/diff/mod.rs
+++ b/src/tools/run-make-support/src/diff/mod.rs
@@ -51,7 +51,10 @@ impl Diff {
     /// Specify the actual output for the diff from a file.
     pub fn actual_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         let path = path.as_ref();
-        let content = std::fs::read_to_string(path).expect("failed to read file");
+        let content = match std::fs::read_to_string(path) {
+            Ok(c) => c,
+            Err(e) => panic!("failed to read `{}`: {:?}", path.display(), e),
+        };
         let name = path.to_string_lossy().to_string();
 
         self.actual = Some(content);
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 9854d91e19e..d96c8b89127 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -12,6 +12,8 @@ pub mod rustc;
 pub mod rustdoc;
 
 use std::env;
+use std::fs;
+use std::io;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Output};
 
@@ -201,6 +203,71 @@ pub fn set_host_rpath(cmd: &mut Command) {
     });
 }
 
+/// Copy a directory into another.
+pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
+    fn copy_dir_all_inner(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
+        let dst = dst.as_ref();
+        if !dst.is_dir() {
+            fs::create_dir_all(&dst)?;
+        }
+        for entry in fs::read_dir(src)? {
+            let entry = entry?;
+            let ty = entry.file_type()?;
+            if ty.is_dir() {
+                copy_dir_all_inner(entry.path(), dst.join(entry.file_name()))?;
+            } else {
+                fs::copy(entry.path(), dst.join(entry.file_name()))?;
+            }
+        }
+        Ok(())
+    }
+
+    if let Err(e) = copy_dir_all_inner(&src, &dst) {
+        // Trying to give more context about what exactly caused the failure
+        panic!(
+            "failed to copy `{}` to `{}`: {:?}",
+            src.as_ref().display(),
+            dst.as_ref().display(),
+            e
+        );
+    }
+}
+
+/// Check that all files in `dir1` exist and have the same content in `dir2`. Panic otherwise.
+pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
+    fn read_file(path: &Path) -> Vec<u8> {
+        match fs::read(path) {
+            Ok(c) => c,
+            Err(e) => panic!("Failed to read `{}`: {:?}", path.display(), e),
+        }
+    }
+
+    let dir2 = dir2.as_ref();
+    for entry in fs::read_dir(dir1).unwrap() {
+        let entry = entry.unwrap();
+        let entry_name = entry.file_name();
+        let path = entry.path();
+
+        if path.is_dir() {
+            recursive_diff(&path, &dir2.join(entry_name));
+        } else {
+            let path2 = dir2.join(entry_name);
+            let file1 = read_file(&path);
+            let file2 = read_file(&path2);
+
+            // We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
+            // Why not using String? Because there might be minified files or even potentially
+            // binary ones, so that would display useless output.
+            assert!(
+                file1 == file2,
+                "`{}` and `{}` have different content",
+                path.display(),
+                path2.display(),
+            );
+        }
+    }
+}
+
 /// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
 /// containing a `cmd: Command` field and a `output` function. The provided helpers are:
 ///
diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
index c4f4e9f9bd2..9c77f1ca462 100644
--- a/src/tools/run-make-support/src/rustdoc.rs
+++ b/src/tools/run-make-support/src/rustdoc.rs
@@ -151,6 +151,13 @@ impl Rustdoc {
         self
     }
 
+    /// Specify the output format.
+    pub fn output_format(&mut self, format: &str) -> &mut Self {
+        self.cmd.arg("--output-format");
+        self.cmd.arg(format);
+        self
+    }
+
     #[track_caller]
     pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
         let caller_location = std::panic::Location::caller();
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 55d65fe8987..2329b8b44de 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -226,7 +226,6 @@ run-make/rlib-format-packed-bundled-libs/Makefile
 run-make/rmeta-preferred/Makefile
 run-make/rustc-macro-dep-files/Makefile
 run-make/rustdoc-io-error/Makefile
-run-make/rustdoc-verify-output-files/Makefile
 run-make/sanitizer-cdylib-link/Makefile
 run-make/sanitizer-dylib-link/Makefile
 run-make/sanitizer-staticlib-link/Makefile
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 37324639edf..055d620361f 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -12,10 +12,10 @@ use std::path::{Path, PathBuf};
 // should all be 1000 or lower. Limits significantly smaller than 1000 are also
 // desirable, because large numbers of files are unwieldy in general. See issue
 // #73494.
-const ENTRY_LIMIT: usize = 900;
+const ENTRY_LIMIT: u32 = 900;
 // FIXME: The following limits should be reduced eventually.
 
-const ISSUES_ENTRY_LIMIT: usize = 1676;
+const ISSUES_ENTRY_LIMIT: u32 = 1676;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
@@ -53,7 +53,7 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
 ];
 
 fn check_entries(tests_path: &Path, bad: &mut bool) {
-    let mut directories: HashMap<PathBuf, usize> = HashMap::new();
+    let mut directories: HashMap<PathBuf, u32> = HashMap::new();
 
     for dir in Walk::new(&tests_path.join("ui")) {
         if let Ok(entry) = dir {
@@ -62,7 +62,7 @@ fn check_entries(tests_path: &Path, bad: &mut bool) {
         }
     }
 
-    let (mut max, mut max_issues) = (0usize, 0usize);
+    let (mut max, mut max_issues) = (0, 0);
     for (dir_path, count) in directories {
         let is_issues_dir = tests_path.join("ui/issues") == dir_path;
         let (limit, maxcnt) = if is_issues_dir {
diff --git a/tests/run-make/rustdoc-verify-output-files/Makefile b/tests/run-make/rustdoc-verify-output-files/Makefile
deleted file mode 100644
index 76f233ab445..00000000000
--- a/tests/run-make/rustdoc-verify-output-files/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-include ../tools.mk
-
-OUTPUT_DIR := "$(TMPDIR)/rustdoc"
-TMP_OUTPUT_DIR := "$(TMPDIR)/tmp-rustdoc"
-
-all:
-	# Generate html docs
-	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR)
-
-	# Copy first output for to check if it's exactly same after second compilation
-	cp -R $(OUTPUT_DIR) $(TMP_OUTPUT_DIR)
-
-	# Generate html docs once again on same output
-	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR)
-
-	# Check if everything exactly same
-	$(DIFF) -r $(OUTPUT_DIR) $(TMP_OUTPUT_DIR)
-
-	# Generate json doc on the same output
-	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) -Z unstable-options --output-format json
-
-	# Check if expected json file is generated
-	[ -e $(OUTPUT_DIR)/foobar.json ]
-
-	# Copy first json output to check if it's exactly same after second compilation
-	cp -R $(OUTPUT_DIR)/foobar.json $(TMP_OUTPUT_DIR)/foobar.json
-
-	# Generate json doc on the same output
-	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) -Z unstable-options --output-format json
-
-	# Check if all docs(including both json and html formats) are still the same after multiple compilations
-	$(DIFF) -r $(OUTPUT_DIR) $(TMP_OUTPUT_DIR)
diff --git a/tests/run-make/rustdoc-verify-output-files/rmake.rs b/tests/run-make/rustdoc-verify-output-files/rmake.rs
new file mode 100644
index 00000000000..212e7eaba2d
--- /dev/null
+++ b/tests/run-make/rustdoc-verify-output-files/rmake.rs
@@ -0,0 +1,49 @@
+use std::fs::copy;
+use std::path::{Path, PathBuf};
+
+use run_make_support::{copy_dir_all, recursive_diff, rustdoc, tmp_dir};
+
+#[derive(PartialEq)]
+enum JsonOutput {
+    Yes,
+    No,
+}
+
+fn generate_docs(out_dir: &Path, json_output: JsonOutput) {
+    let mut rustdoc = rustdoc();
+    rustdoc.input("src/lib.rs").crate_name("foobar").crate_type("lib").out_dir(&out_dir);
+    if json_output == JsonOutput::Yes {
+        rustdoc.arg("-Zunstable-options").output_format("json");
+    }
+    rustdoc.run();
+}
+
+fn main() {
+    let out_dir = tmp_dir().join("rustdoc");
+    let tmp_out_dir = tmp_dir().join("tmp-rustdoc");
+
+    // Generate HTML docs.
+    generate_docs(&out_dir, JsonOutput::No);
+
+    // Copy first output for to check if it's exactly same after second compilation.
+    copy_dir_all(&out_dir, &tmp_out_dir);
+
+    // Generate html docs once again on same output.
+    generate_docs(&out_dir, JsonOutput::No);
+
+    // Generate json doc on the same output.
+    generate_docs(&out_dir, JsonOutput::Yes);
+
+    // Check if expected json file is generated.
+    assert!(out_dir.join("foobar.json").is_file());
+
+    // Copy first json output to check if it's exactly same after second compilation.
+    copy(out_dir.join("foobar.json"), tmp_out_dir.join("foobar.json")).unwrap();
+
+    // Generate json doc on the same output.
+    generate_docs(&out_dir, JsonOutput::Yes);
+
+    // Check if all docs(including both json and html formats) are still the same after multiple
+    // compilations.
+    recursive_diff(&out_dir, &tmp_out_dir);
+}