Skip to content

Commit

Permalink
Auto merge of rust-lang#134025 - workingjubilee:rollup-xb4212q, r=<try>
Browse files Browse the repository at this point in the history
[TEST] Rollup of 5 pull requests

Successful merges:

 - rust-lang#133733 ( compiletest: show the difference between the normalized output and the actual output for lines which didn't match)
 - rust-lang#133861 (Add allocate_bytes and refactor allocate_str in InterpCx for raw byte…)
 - rust-lang#133967 ([AIX] Pass -bnoipath when adding rust upstream dynamic crates)
 - rust-lang#133976 (Removed Unnecessary Spaces From RELEASES.md)
 - rust-lang#133980 ([AIX] Remove option "-n" from AIX "ln" command)

r? `@ghost`
`@rustbot` modify labels: rollup

try-job: i686-mingw
  • Loading branch information
bors committed Dec 8, 2024
2 parents 728f2da + 7e81657 commit 4bf8448
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 53 deletions.
8 changes: 4 additions & 4 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ Compatibility Notes
* We have renamed `std::panic::PanicInfo` to `std::panic::PanicHookInfo`. The old name will continue to work as an alias, but will result in a deprecation warning starting in Rust 1.82.0.

`core::panic::PanicInfo` will remain unchanged, however, as this is now a *different type*.

The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`.

* The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data.
Expand Down Expand Up @@ -584,7 +584,7 @@ Stabilized APIs
- [`impl Default for Arc<CStr>`](https://doc.rust-lang.org/beta/alloc/sync/struct.Arc.html#impl-Default-for-Arc%3CCStr%3E)
- [`impl Default for Arc<[T]>`](https://doc.rust-lang.org/beta/alloc/sync/struct.Arc.html#impl-Default-for-Arc%3C%5BT%5D%3E)
- [`impl IntoIterator for Box<[T]>`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-IntoIterator-for-Box%3C%5BI%5D,+A%3E)
- [`impl FromIterator<String> for Box<str>`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-FromIterator%3CString%3E-for-Box%3Cstr%3E)
- [`impl FromIterator<String> for Box<str>`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-FromIterator%3CString%3E-for-Box%3Cstr%3E)
- [`impl FromIterator<char> for Box<str>`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-FromIterator%3Cchar%3E-for-Box%3Cstr%3E)
- [`LazyCell`](https://doc.rust-lang.org/beta/core/cell/struct.LazyCell.html)
- [`LazyLock`](https://doc.rust-lang.org/beta/std/sync/struct.LazyLock.html)
Expand Down Expand Up @@ -1816,7 +1816,7 @@ Compiler
- [Detect uninhabited types early in const eval](https://github.com/rust-lang/rust/pull/109435/)
- [Switch to LLD as default linker for {arm,thumb}v4t-none-eabi](https://github.com/rust-lang/rust/pull/109721/)
- [Add tier 3 target `loongarch64-unknown-linux-gnu`](https://github.com/rust-lang/rust/pull/96971)
- [Add tier 3 target for `i586-pc-nto-qnx700` (QNX Neutrino RTOS, version 7.0)](https://github.com/rust-lang/rust/pull/109173/),
- [Add tier 3 target for `i586-pc-nto-qnx700` (QNX Neutrino RTOS, version 7.0)](https://github.com/rust-lang/rust/pull/109173/),
- [Insert alignment checks for pointer dereferences as debug assertions](https://github.com/rust-lang/rust/pull/98112)
This catches undefined behavior at runtime, and may cause existing code to fail.

Expand Down Expand Up @@ -2023,7 +2023,7 @@ Compatibility Notes
If `tools = [...]` is set in config.toml, we will respect a missing rustdoc in that list. By
default rustdoc remains included. To retain the prior behavior explicitly add `"rustdoc"` to the
list.

<a id="1.69.0-Internal-Changes"></a>

Internal Changes
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2753,6 +2753,15 @@ fn add_upstream_rust_crates(
.find(|(ty, _)| *ty == crate_type)
.expect("failed to find crate type in dependency format list");

if sess.target.is_like_aix {
// Unlike ELF linkers, AIX doesn't feature `DT_SONAME` to override
// the dependency name when outputing a shared library. Thus, `ld` will
// use the full path to shared libraries as the dependency if passed it
// by default unless `noipath` is passed.
// https://www.ibm.com/docs/en/aix/7.3?topic=l-ld-command.
cmd.link_or_cc_arg("-bnoipath");
}

for &cnum in &codegen_results.crate_info.used_crates {
// We may not pass all crates through to the linker. Some crates may appear statically in
// an existing dylib, meaning we'll pick up all the symbols from the dylib.
Expand Down
45 changes: 32 additions & 13 deletions compiler/rustc_const_eval/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1018,29 +1018,48 @@ where
self.allocate_dyn(layout, kind, MemPlaceMeta::None)
}

/// Returns a wide MPlace of type `str` to a new 1-aligned allocation.
/// Immutable strings are deduplicated and stored in global memory.
pub fn allocate_str(
/// Allocates a sequence of bytes in the interpreter's memory.
/// For immutable allocations, uses deduplication to reuse existing memory.
/// For mutable allocations, creates a new unique allocation.
pub fn allocate_bytes(
&mut self,
str: &str,
bytes: &[u8],
align: Align,
kind: MemoryKind<M::MemoryKind>,
mutbl: Mutability,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
let tcx = self.tcx.tcx;

) -> InterpResult<'tcx, Pointer<M::Provenance>> {
// Use cache for immutable strings.
let ptr = if mutbl.is_not() {
if mutbl.is_not() {
// Use dedup'd allocation function.
let salt = M::get_global_alloc_salt(self, None);
let id = tcx.allocate_bytes_dedup(str.as_bytes(), salt);
let id = self.tcx.allocate_bytes_dedup(bytes, salt);

// Turn untagged "global" pointers (obtained via `tcx`) into the machine pointer to the allocation.
M::adjust_alloc_root_pointer(&self, Pointer::from(id), Some(kind))?
M::adjust_alloc_root_pointer(&self, Pointer::from(id), Some(kind))
} else {
self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl)?
};
let meta = Scalar::from_target_usize(u64::try_from(str.len()).unwrap(), self);
// Allocate new memory for mutable data.
self.allocate_bytes_ptr(bytes, align, kind, mutbl)
}
}

/// Allocates a string in the interpreter's memory with metadata for length.
/// Uses `allocate_bytes` internally but adds string-specific metadata handling.
pub fn allocate_str(
&mut self,
str: &str,
kind: MemoryKind<M::MemoryKind>,
mutbl: Mutability,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
let bytes = str.as_bytes();
let ptr = self.allocate_bytes(bytes, Align::ONE, kind, mutbl)?;

// Create length metadata for the string.
let meta = Scalar::from_target_usize(u64::try_from(bytes.len()).unwrap(), self);

// Get layout for Rust's str type.
let layout = self.layout_of(self.tcx.types.str_).unwrap();

// Combine pointer and metadata into a wide pointer.
interp_ok(self.ptr_with_meta_to_mplace(
ptr.into(),
MemPlaceMeta::Meta(meta),
Expand Down
136 changes: 106 additions & 30 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::common::{
UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG, Ui, expected_output_path, incremental_dir,
output_base_dir, output_base_name, output_testname_unique,
};
use crate::compute_diff::{write_diff, write_filtered_diff};
use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
use crate::errors::{self, Error, ErrorKind};
use crate::header::TestProps;
use crate::read2::{Truncated, read2_abbreviated};
Expand Down Expand Up @@ -2295,17 +2295,31 @@ impl<'test> TestCx<'test> {
match output_kind {
TestOutput::Compile => {
if !self.props.dont_check_compiler_stdout {
errors +=
self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
errors += self.compare_output(
stdout_kind,
&normalized_stdout,
&proc_res.stdout,
&expected_stdout,
);
}
if !self.props.dont_check_compiler_stderr {
errors +=
self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
errors += self.compare_output(
stderr_kind,
&normalized_stderr,
&stderr,
&expected_stderr,
);
}
}
TestOutput::Run => {
errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
errors += self.compare_output(
stdout_kind,
&normalized_stdout,
&proc_res.stdout,
&expected_stdout,
);
errors +=
self.compare_output(stderr_kind, &normalized_stderr, &stderr, &expected_stderr);
}
}
errors
Expand Down Expand Up @@ -2533,7 +2547,13 @@ impl<'test> TestCx<'test> {
}
}

fn compare_output(&self, stream: &str, actual: &str, expected: &str) -> usize {
fn compare_output(
&self,
stream: &str,
actual: &str,
actual_unnormalized: &str,
expected: &str,
) -> usize {
let are_different = match (self.force_color_svg(), expected.find('\n'), actual.find('\n')) {
// FIXME: We ignore the first line of SVG files
// because the width parameter is non-deterministic.
Expand Down Expand Up @@ -2590,28 +2610,14 @@ impl<'test> TestCx<'test> {
if expected.is_empty() {
println!("normalized {}:\n{}\n", stream, actual);
} else {
println!("diff of {stream}:\n");
if let Some(diff_command) = self.config.diff_command.as_deref() {
let mut args = diff_command.split_whitespace();
let name = args.next().unwrap();
match Command::new(name)
.args(args)
.args([&expected_path, &actual_path])
.output()
{
Err(err) => {
self.fatal(&format!(
"failed to call custom diff command `{diff_command}`: {err}"
));
}
Ok(output) => {
let output = String::from_utf8_lossy(&output.stdout);
print!("{output}");
}
}
} else {
print!("{}", write_diff(expected, actual, 3));
}
self.show_diff(
stream,
&expected_path,
&actual_path,
expected,
actual,
actual_unnormalized,
);
}
} else {
// Delete non-revision .stderr/.stdout file if revisions are used.
Expand All @@ -2633,6 +2639,76 @@ impl<'test> TestCx<'test> {
if self.config.bless { 0 } else { 1 }
}

/// Returns whether to show the full stderr/stdout.
fn show_diff(
&self,
stream: &str,
expected_path: &Path,
actual_path: &Path,
expected: &str,
actual: &str,
actual_unnormalized: &str,
) {
eprintln!("diff of {stream}:\n");
if let Some(diff_command) = self.config.diff_command.as_deref() {
let mut args = diff_command.split_whitespace();
let name = args.next().unwrap();
match Command::new(name).args(args).args([expected_path, actual_path]).output() {
Err(err) => {
self.fatal(&format!(
"failed to call custom diff command `{diff_command}`: {err}"
));
}
Ok(output) => {
let output = String::from_utf8_lossy(&output.stdout);
eprint!("{output}");
}
}
} else {
eprint!("{}", write_diff(expected, actual, 3));
}

// NOTE: argument order is important, we need `actual` to be on the left so the line number match up when we compare it to `actual_unnormalized` below.
let diff_results = make_diff(actual, expected, 0);

let (mut mismatches_normalized, mut mismatch_line_nos) = (String::new(), vec![]);
for hunk in diff_results {
let mut line_no = hunk.line_number;
for line in hunk.lines {
// NOTE: `Expected` is actually correct here, the argument order is reversed so our line numbers match up
if let DiffLine::Expected(normalized) = line {
mismatches_normalized += &normalized;
mismatches_normalized += "\n";
mismatch_line_nos.push(line_no);
line_no += 1;
}
}
}
let mut mismatches_unnormalized = String::new();
let diff_normalized = make_diff(actual, actual_unnormalized, 0);
for hunk in diff_normalized {
if mismatch_line_nos.contains(&hunk.line_number) {
for line in hunk.lines {
if let DiffLine::Resulting(unnormalized) = line {
mismatches_unnormalized += &unnormalized;
mismatches_unnormalized += "\n";
}
}
}
}

let normalized_diff = make_diff(&mismatches_normalized, &mismatches_unnormalized, 0);
// HACK: instead of checking if each hunk is empty, this only checks if the whole input is empty. we should be smarter about this so we don't treat added or removed output as normalized.
if !normalized_diff.is_empty()
&& !mismatches_unnormalized.is_empty()
&& !mismatches_normalized.is_empty()
{
eprintln!("Note: some mismatched output was normalized before being compared");
// FIXME: respect diff_command
eprint!("{}", write_diff(&mismatches_unnormalized, &mismatches_normalized, 0));
}
}

fn check_and_prune_duplicate_outputs(
&self,
proc_res: &ProcRes,
Expand Down
16 changes: 12 additions & 4 deletions src/tools/compiletest/src/runtest/coverage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ impl<'test> TestCx<'test> {
let expected_coverage_dump = self.load_expected_output(kind);
let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]);

let coverage_dump_errors =
self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump);
let coverage_dump_errors = self.compare_output(
kind,
&actual_coverage_dump,
&proc_res.stdout,
&expected_coverage_dump,
);

if coverage_dump_errors > 0 {
self.fatal_proc_rec(
Expand Down Expand Up @@ -135,8 +139,12 @@ impl<'test> TestCx<'test> {
self.fatal_proc_rec(&err, &proc_res);
});

let coverage_errors =
self.compare_output(kind, &normalized_actual_coverage, &expected_coverage);
let coverage_errors = self.compare_output(
kind,
&normalized_actual_coverage,
&proc_res.stdout,
&expected_coverage,
);

if coverage_errors > 0 {
self.fatal_proc_rec(
Expand Down
2 changes: 1 addition & 1 deletion src/tools/compiletest/src/runtest/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl TestCx<'_> {
)
});

errors += self.compare_output("fixed", &fixed_code, &expected_fixed);
errors += self.compare_output("fixed", &fixed_code, &fixed_code, &expected_fixed);
} else if !expected_fixed.is_empty() {
panic!(
"the `//@ run-rustfix` directive wasn't found but a `*.fixed` \
Expand Down
12 changes: 11 additions & 1 deletion tests/run-make/libs-through-symlinks/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,20 @@ include ../tools.mk

# ignore-windows

# The option -n for the AIX ln command has a different purpose than it does
# on Linux. On Linux, the -n option is used to treat the destination path as
# normal file if it is a symbolic link to a directory, which is the default
# behavior of the AIX ln command.
ifeq ($(UNAME),AIX)
LN_FLAGS := -sf
else
LN_FLAGS := -nsf
endif

NAME := $(shell $(RUSTC) --print file-names foo.rs)

all:
mkdir -p $(TMPDIR)/outdir
$(RUSTC) foo.rs -o $(TMPDIR)/outdir/$(NAME)
ln -nsf outdir/$(NAME) $(TMPDIR)
ln $(LN_FLAGS) outdir/$(NAME) $(TMPDIR)
RUSTC_LOG=rustc_metadata::loader $(RUSTC) bar.rs

0 comments on commit 4bf8448

Please sign in to comment.