Auto merge of #135525 - jhpratt:rollup-4gu2wpm, r=jhpratt

Rollup of 7 pull requests

Successful merges:

 - #132397 (Make missing_abi lint warn-by-default.)
 - #133807 (ci: Enable opt-dist for dist-aarch64-linux builds)
 - #134143 (Convert `struct FromBytesWithNulError` into enum)
 - #134338 (Use a C-safe return type for `__rust_[ui]128_*` overflowing intrinsics)
 - #134678 (Update `ReadDir::next` in `std::sys::pal::unix::fs` to use `&raw const (*p).field` instead of `p.byte_offset().cast()`)
 - #135424 (Detect unstable lint docs that dont enable their feature)
 - #135520 (Make sure we actually use the right trivial lifetime substs when eagerly monomorphizing drop for ADTs)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-01-15 09:20:25 +00:00
commit 2776bdfe42
81 changed files with 429 additions and 315 deletions

View file

@ -91,9 +91,12 @@ ENV RUST_CONFIGURE_ARGS \
--set rust.debug-assertions=false \
--set rust.jemalloc \
--set rust.use-lld=true \
--set rust.lto=thin \
--set rust.codegen-units=1
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \
./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \
--host $HOSTS --target $HOSTS --include-default-paths build-manifest bootstrap
ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=clang
ENV LIBCURL_NO_PKG_CONFIG 1

View file

@ -173,6 +173,7 @@ mod issue_3739 {
/// This shouldn't warn for `boxed_local` as it is intended to called from non-Rust code.
pub extern "C" fn do_not_warn_me(_c_pointer: Box<String>) -> () {}
#[allow(missing_abi)]
#[rustfmt::skip] // Forces rustfmt to not add ABI
pub extern fn do_not_warn_me_no_abi(_c_pointer: Box<String>) -> () {}

View file

@ -14,13 +14,13 @@ LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {}
| ^^^^^^^^^^^
error: local variable doesn't need to be boxed here
--> tests/ui/boxed_local.rs:188:44
--> tests/ui/boxed_local.rs:189:44
|
LL | fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 {
| ^
error: local variable doesn't need to be boxed here
--> tests/ui/boxed_local.rs:196:16
--> tests/ui/boxed_local.rs:197:16
|
LL | fn foo(x: Box<u32>) {}
| ^

View file

@ -240,7 +240,7 @@ fn parenthesized_word() {}
/// UXes
fn plural_acronym_test() {}
extern {
extern "C" {
/// `foo()`
fn in_extern();
}

View file

@ -240,7 +240,7 @@ fn parenthesized_word() {}
/// UXes
fn plural_acronym_test() {}
extern {
extern "C" {
/// foo()
fn in_extern();
}

View file

@ -149,6 +149,7 @@ mod msrv {
//~^ ERROR: this could be a `const fn`
#[rustfmt::skip]
#[allow(missing_abi)]
const extern fn implicit_c() {}
//~^ ERROR: this could be a `const fn`

View file

@ -149,6 +149,7 @@ mod msrv {
//~^ ERROR: this could be a `const fn`
#[rustfmt::skip]
#[allow(missing_abi)]
extern fn implicit_c() {}
//~^ ERROR: this could be a `const fn`

View file

@ -222,7 +222,7 @@ LL | const extern "C" fn c() {}
| +++++
error: this could be a `const fn`
--> tests/ui/missing_const_for_fn/could_be_const.rs:152:9
--> tests/ui/missing_const_for_fn/could_be_const.rs:153:9
|
LL | extern fn implicit_c() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -233,7 +233,7 @@ LL | const extern fn implicit_c() {}
| +++++
error: this could be a `const fn`
--> tests/ui/missing_const_for_fn/could_be_const.rs:169:9
--> tests/ui/missing_const_for_fn/could_be_const.rs:170:9
|
LL | / pub fn new(strings: Vec<String>) -> Self {
LL | | Self { strings }
@ -246,7 +246,7 @@ LL | pub const fn new(strings: Vec<String>) -> Self {
| +++++
error: this could be a `const fn`
--> tests/ui/missing_const_for_fn/could_be_const.rs:174:9
--> tests/ui/missing_const_for_fn/could_be_const.rs:175:9
|
LL | / pub fn empty() -> Self {
LL | | Self { strings: Vec::new() }
@ -259,7 +259,7 @@ LL | pub const fn empty() -> Self {
| +++++
error: this could be a `const fn`
--> tests/ui/missing_const_for_fn/could_be_const.rs:185:9
--> tests/ui/missing_const_for_fn/could_be_const.rs:186:9
|
LL | / pub fn new(text: String) -> Self {
LL | | let vec = Vec::new();
@ -273,7 +273,7 @@ LL | pub const fn new(text: String) -> Self {
| +++++
error: this could be a `const fn`
--> tests/ui/missing_const_for_fn/could_be_const.rs:204:5
--> tests/ui/missing_const_for_fn/could_be_const.rs:205:5
|
LL | fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -284,7 +284,7 @@ LL | const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
| +++++
error: this could be a `const fn`
--> tests/ui/missing_const_for_fn/could_be_const.rs:208:5
--> tests/ui/missing_const_for_fn/could_be_const.rs:209:5
|
LL | extern "C-unwind" fn c_unwind() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -295,7 +295,7 @@ LL | const extern "C-unwind" fn c_unwind() {}
| +++++
error: this could be a `const fn`
--> tests/ui/missing_const_for_fn/could_be_const.rs:210:5
--> tests/ui/missing_const_for_fn/could_be_const.rs:211:5
|
LL | extern "system" fn system() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -306,7 +306,7 @@ LL | const extern "system" fn system() {}
| +++++
error: this could be a `const fn`
--> tests/ui/missing_const_for_fn/could_be_const.rs:212:5
--> tests/ui/missing_const_for_fn/could_be_const.rs:213:5
|
LL | extern "system-unwind" fn system_unwind() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -473,37 +473,64 @@ impl<'a> LintExtractor<'a> {
.filter(|line| line.starts_with('{'))
.map(serde_json::from_str)
.collect::<Result<Vec<serde_json::Value>, _>>()?;
// First try to find the messages with the `code` field set to our lint.
let matches: Vec<_> = msgs
.iter()
.filter(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s==name))
.map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string())
.collect();
if matches.is_empty() {
// Some lints override their code to something else (E0566).
// Try to find something that looks like it could be our lint.
let matches: Vec<_> = msgs.iter().filter(|msg|
matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)))
.map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string())
.collect();
if matches.is_empty() {
let rendered: Vec<&str> =
msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
let non_json: Vec<&str> =
stderr.lines().filter(|line| !line.starts_with('{')).collect();
Err(format!(
"did not find lint `{}` in output of example, got:\n{}\n{}",
name,
non_json.join("\n"),
rendered.join("\n")
)
.into())
} else {
Ok(matches.join("\n"))
}
} else {
Ok(matches.join("\n"))
if !matches.is_empty() {
return Ok(matches.join("\n"));
}
// Try to detect if an unstable lint forgot to enable a `#![feature(..)]`.
// Specifically exclude `test_unstable_lint` which exercises this on purpose.
if name != "test_unstable_lint"
&& msgs.iter().any(|msg| {
matches!(&msg["code"]["code"], serde_json::Value::String(s) if s=="unknown_lints")
&& matches!(&msg["message"], serde_json::Value::String(s) if s.contains(name))
})
{
let rendered: Vec<&str> =
msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
let non_json: Vec<&str> =
stderr.lines().filter(|line| !line.starts_with('{')).collect();
return Err(format!(
"did not find lint `{}` in output of example (got unknown_lints)\n\
Is the lint possibly misspelled, or does it need a `#![feature(...)]`?\n\
Output was:\n\
{}\n{}",
name,
rendered.join("\n"),
non_json.join("\n"),
)
.into());
}
// Some lints override their code to something else (E0566).
// Try to find something that looks like it could be our lint.
let matches: Vec<_> = msgs
.iter()
.filter(
|msg| matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)),
)
.map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string())
.collect();
if !matches.is_empty() {
return Ok(matches.join("\n"));
}
// Otherwise, give a descriptive error.
let rendered: Vec<&str> = msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
let non_json: Vec<&str> = stderr.lines().filter(|line| !line.starts_with('{')).collect();
Err(format!(
"did not find lint `{}` in output of example, got:\n{}\n{}",
name,
non_json.join("\n"),
rendered.join("\n")
)
.into())
}
/// Saves the mdbook lint chapters at the given path.

View file

@ -1,6 +1,7 @@
use anyhow::Context;
use camino::{Utf8Path, Utf8PathBuf};
use crate::environment::Environment;
use crate::exec::cmd;
use crate::training::BoltProfile;
use crate::utils::io::copy_file;
@ -45,13 +46,21 @@ pub fn with_bolt_instrumented<F: FnOnce(&Utf8Path) -> anyhow::Result<R>, R>(
}
/// Optimizes the file at `path` with BOLT in-place using the given `profile`.
pub fn bolt_optimize(path: &Utf8Path, profile: &BoltProfile) -> anyhow::Result<()> {
pub fn bolt_optimize(
path: &Utf8Path,
profile: &BoltProfile,
env: &Environment,
) -> anyhow::Result<()> {
// Copy the artifact to a new location, so that we do not use the same input and output file.
// BOLT cannot handle optimizing when the input and output is the same file, because it performs
// in-place patching.
let temp_path = tempfile::NamedTempFile::new()?.into_temp_path();
copy_file(path, &temp_path)?;
// FIXME: cdsplit in llvm-bolt is currently broken on AArch64, drop this once it's fixed upstream
let split_strategy =
if env.host_tuple().starts_with("aarch64") { "profile2" } else { "cdsplit" };
cmd(&["llvm-bolt"])
.arg(temp_path.display())
.arg("-data")
@ -65,7 +74,7 @@ pub fn bolt_optimize(path: &Utf8Path, profile: &BoltProfile) -> anyhow::Result<(
// Split function code into hot and code regions
.arg("-split-functions")
// Split using best available strategy (three-way splitting, Cache-Directed Sort)
.arg("-split-strategy=cdsplit")
.arg(format!("-split-strategy={split_strategy}"))
// Split as many basic blocks as possible
.arg("-split-all-cold")
// Move jump tables to a separate section

View file

@ -146,6 +146,21 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
let target_triple =
std::env::var("PGO_HOST").expect("PGO_HOST environment variable missing");
let is_aarch64 = target_triple.starts_with("aarch64");
let mut skip_tests = vec![
// Fails because of linker errors, as of June 2023.
"tests/ui/process/nofile-limit.rs".to_string(),
];
if is_aarch64 {
skip_tests.extend([
// Those tests fail only inside of Docker on aarch64, as of December 2024
"tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs".to_string(),
"tests/ui/consts/large_const_alloc.rs".to_string(),
]);
}
let checkout_dir = Utf8PathBuf::from("/checkout");
let env = EnvironmentBuilder::default()
.host_tuple(target_triple)
@ -155,11 +170,9 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
.artifact_dir(Utf8PathBuf::from("/tmp/tmp-multistage/opt-artifacts"))
.build_dir(checkout_dir.join("obj"))
.shared_llvm(true)
.use_bolt(true)
.skipped_tests(vec![
// Fails because of linker errors, as of June 2023.
"tests/ui/process/nofile-limit.rs".to_string(),
])
// FIXME: Enable bolt for aarch64 once it's fixed upstream. Broken as of December 2024.
.use_bolt(!is_aarch64)
.skipped_tests(skip_tests)
.build()?;
(env, shared.build_args)
@ -304,7 +317,8 @@ fn execute_pipeline(
// the final dist build. However, when BOLT optimizes an artifact, it does so *in-place*,
// therefore it will actually optimize all the hard links, which means that the final
// packaged `libLLVM.so` file *will* be BOLT optimized.
bolt_optimize(&llvm_lib, &llvm_profile).context("Could not optimize LLVM with BOLT")?;
bolt_optimize(&llvm_lib, &llvm_profile, env)
.context("Could not optimize LLVM with BOLT")?;
let rustc_lib = io::find_file_in_dir(&libdir, "librustc_driver", ".so")?;
@ -319,7 +333,7 @@ fn execute_pipeline(
print_free_disk_space()?;
// Now optimize the library with BOLT.
bolt_optimize(&rustc_lib, &rustc_profile)
bolt_optimize(&rustc_lib, &rustc_profile, env)
.context("Could not optimize rustc with BOLT")?;
// LLVM is not being cleared here, we want to use the BOLT-optimized LLVM