Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 4 pull requests #125628

Merged
merged 11 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 23 additions & 3 deletions compiler/rustc_mir_transform/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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."
),
);
}

Expand Down Expand Up @@ -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);
Expand Down
22 changes: 11 additions & 11 deletions src/ci/scripts/verify-line-endings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/tools/miri/tests/panic/mir-validation.stderr
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
5 changes: 4 additions & 1 deletion src/tools/run-make-support/src/diff/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
67 changes: 67 additions & 0 deletions src/tools/run-make-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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:
///
Expand Down
7 changes: 7 additions & 0 deletions src/tools/run-make-support/src/rustdoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 0 additions & 1 deletion src/tools/tidy/src/allowed_run_make_makefiles.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions src/tools/tidy/src/ui_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
32 changes: 0 additions & 32 deletions tests/run-make/rustdoc-verify-output-files/Makefile

This file was deleted.

49 changes: 49 additions & 0 deletions tests/run-make/rustdoc-verify-output-files/rmake.rs
Original file line number Diff line number Diff line change
@@ -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