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
This commit is contained in:
commit
84b40fc908
@ -1008,8 +1008,8 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
|
|||||||
/// element:
|
/// element:
|
||||||
///
|
///
|
||||||
/// - [`Downcast`](ProjectionElem::Downcast): This projection sets the place's variant index to the
|
/// - [`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
|
/// given one, and makes no other changes. A `Downcast` projection must always be followed
|
||||||
/// index already set is not well-formed.
|
/// immediately by a `Field` projection.
|
||||||
/// - [`Field`](ProjectionElem::Field): `Field` projections take their parent place and create a
|
/// - [`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
|
/// 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
|
/// address, plus the offset of the field. The type becomes the type of the field. If the parent
|
||||||
|
@ -689,8 +689,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
if Some(adt_def.did()) == self.tcx.lang_items().dyn_metadata() {
|
if Some(adt_def.did()) == self.tcx.lang_items().dyn_metadata() {
|
||||||
self.fail(
|
self.fail(
|
||||||
location,
|
location,
|
||||||
format!("You can't project to field {f:?} of `DynMetadata` because \
|
format!(
|
||||||
layout is weird and thinks it doesn't have fields."),
|
"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)
|
&& cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo)
|
||||||
&& place.projection[1..].contains(&ProjectionElem::Deref)
|
&& 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);
|
self.super_place(place, cntxt, location);
|
||||||
|
@ -4,21 +4,21 @@
|
|||||||
# We check both in rust-lang/rust and in a submodule to make sure both are
|
# 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
|
# accurate. Submodules are checked out significantly later than the main
|
||||||
# repository in this script, so settings can (and do!) change between then.
|
# 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
|
set -euo pipefail
|
||||||
IFS=$'\n\t'
|
IFS=$'\n\t'
|
||||||
|
|
||||||
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
|
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
|
||||||
|
|
||||||
if isWindows; then
|
# print out the git configuration so we can better investigate failures in
|
||||||
# print out the git configuration so we can better investigate failures in
|
# the following
|
||||||
# the following
|
git config --list --show-origin
|
||||||
git config --list --show-origin
|
# -U is necessary on Windows to stop grep automatically converting the line ending
|
||||||
dos2unix -ih Cargo.lock src/tools/rust-installer/install-template.sh
|
endings=$(grep -Ul $(printf '\r$') Cargo.lock src/tools/cargo/Cargo.lock) || true
|
||||||
endings=$(dos2unix -ic Cargo.lock src/tools/rust-installer/install-template.sh)
|
# if endings has non-zero length, error out
|
||||||
# if endings has non-zero length, error out
|
if [[ -n $endings ]]; then
|
||||||
if [ -n "$endings" ]; then exit 1 ; fi
|
echo "Error: found DOS line endings"
|
||||||
|
# Print the files with DOS line endings
|
||||||
|
echo "$endings"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
thread 'rustc' panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC:
|
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]:
|
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:
|
stack backtrace:
|
||||||
|
|
||||||
error: the compiler unexpectedly panicked. this is a bug.
|
error: the compiler unexpectedly panicked. this is a bug.
|
||||||
|
@ -51,7 +51,10 @@ impl Diff {
|
|||||||
/// Specify the actual output for the diff from a file.
|
/// Specify the actual output for the diff from a file.
|
||||||
pub fn actual_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
|
pub fn actual_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
|
||||||
let path = path.as_ref();
|
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();
|
let name = path.to_string_lossy().to_string();
|
||||||
|
|
||||||
self.actual = Some(content);
|
self.actual = Some(content);
|
||||||
|
@ -12,6 +12,8 @@ pub mod rustc;
|
|||||||
pub mod rustdoc;
|
pub mod rustdoc;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Output};
|
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
|
/// 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:
|
/// containing a `cmd: Command` field and a `output` function. The provided helpers are:
|
||||||
///
|
///
|
||||||
|
@ -151,6 +151,13 @@ impl Rustdoc {
|
|||||||
self
|
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]
|
#[track_caller]
|
||||||
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
|
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
|
||||||
let caller_location = std::panic::Location::caller();
|
let caller_location = std::panic::Location::caller();
|
||||||
|
@ -226,7 +226,6 @@ run-make/rlib-format-packed-bundled-libs/Makefile
|
|||||||
run-make/rmeta-preferred/Makefile
|
run-make/rmeta-preferred/Makefile
|
||||||
run-make/rustc-macro-dep-files/Makefile
|
run-make/rustc-macro-dep-files/Makefile
|
||||||
run-make/rustdoc-io-error/Makefile
|
run-make/rustdoc-io-error/Makefile
|
||||||
run-make/rustdoc-verify-output-files/Makefile
|
|
||||||
run-make/sanitizer-cdylib-link/Makefile
|
run-make/sanitizer-cdylib-link/Makefile
|
||||||
run-make/sanitizer-dylib-link/Makefile
|
run-make/sanitizer-dylib-link/Makefile
|
||||||
run-make/sanitizer-staticlib-link/Makefile
|
run-make/sanitizer-staticlib-link/Makefile
|
||||||
|
@ -12,10 +12,10 @@ use std::path::{Path, PathBuf};
|
|||||||
// should all be 1000 or lower. Limits significantly smaller than 1000 are also
|
// 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
|
// desirable, because large numbers of files are unwieldy in general. See issue
|
||||||
// #73494.
|
// #73494.
|
||||||
const ENTRY_LIMIT: usize = 900;
|
const ENTRY_LIMIT: u32 = 900;
|
||||||
// FIXME: The following limits should be reduced eventually.
|
// 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] = &[
|
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||||
"rs", // test source files
|
"rs", // test source files
|
||||||
@ -53,7 +53,7 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
|
|||||||
];
|
];
|
||||||
|
|
||||||
fn check_entries(tests_path: &Path, bad: &mut bool) {
|
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")) {
|
for dir in Walk::new(&tests_path.join("ui")) {
|
||||||
if let Ok(entry) = dir {
|
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 {
|
for (dir_path, count) in directories {
|
||||||
let is_issues_dir = tests_path.join("ui/issues") == dir_path;
|
let is_issues_dir = tests_path.join("ui/issues") == dir_path;
|
||||||
let (limit, maxcnt) = if is_issues_dir {
|
let (limit, maxcnt) = if is_issues_dir {
|
||||||
|
@ -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)
|
|
49
tests/run-make/rustdoc-verify-output-files/rmake.rs
Normal file
49
tests/run-make/rustdoc-verify-output-files/rmake.rs
Normal file
@ -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);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user