Auto merge of #147371 - Zalathar:rollup-897uitw, r=Zalathar

Rollup of 5 pull requests

Successful merges:

 - rust-lang/rust#144908 (Fix doctest output json)
 - rust-lang/rust#147262 (Make #[link="dl"] an FCW rather than an error)
 - rust-lang/rust#147364 (update autodiff testcases)
 - rust-lang/rust#147367 (Trivial code cleanup in resolve)
 - rust-lang/rust#147369 (Fill out AVR target metadata)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2025-10-05 12:43:00 +00:00
12 changed files with 191 additions and 54 deletions
@@ -65,10 +65,22 @@ fn extend<'c>(
cx: &'c mut AcceptContext<'_, '_, S>,
args: &'c ArgParser<'_>,
) -> impl IntoIterator<Item = Self::Item> + 'c {
let mut result = None;
let Some(items) = args.list() else {
cx.expected_list(cx.attr_span);
return result;
let items = match args {
ArgParser::List(list) => list,
// This is an edgecase added because making this a hard error would break too many crates
// Specifically `#[link = "dl"]` is accepted with a FCW
// For more information, see https://github.com/rust-lang/rust/pull/143193
ArgParser::NameValue(nv) if nv.value_as_str().is_some_and(|v| v == sym::dl) => {
let suggestions = <Self as CombineAttributeParser<S>>::TEMPLATE
.suggestions(cx.attr_style, "link");
let span = cx.attr_span;
cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
return None;
}
_ => {
cx.expected_list(cx.attr_span);
return None;
}
};
let sess = cx.sess();
@@ -113,7 +125,7 @@ fn extend<'c>(
}
};
if !cont {
return result;
return None;
}
}
@@ -202,7 +214,7 @@ fn extend<'c>(
}
let Some((name, name_span)) = name else {
cx.emit_err(LinkRequiresName { span: cx.attr_span });
return result;
return None;
};
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
@@ -218,15 +230,14 @@ fn extend<'c>(
cx.emit_err(RawDylibNoNul { span: name_span });
}
result = Some(LinkEntry {
Some(LinkEntry {
span: cx.attr_span,
kind: kind.unwrap_or(NativeLibKind::Unspecified),
name,
cfg,
verbatim,
import_name_type,
});
result
})
}
}
+1 -5
View File
@@ -741,14 +741,10 @@ fn throw_unresolved_import_error(
errors.retain(|(_import, err)| match err.module {
// Skip `use` errors for `use foo::Bar;` if `foo.rs` has unrecovered parse errors.
Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false,
_ => true,
});
errors.retain(|(_import, err)| {
// If we've encountered something like `use _;`, we've already emitted an error stating
// that `_` is not a valid identifier, so we ignore that resolve error.
err.segment != Some(kw::Underscore)
_ => err.segment != Some(kw::Underscore),
});
if errors.is_empty() {
self.tcx.dcx().delayed_bug("expected a parse or \"`_` can't be an identifier\" error");
return;
+1
View File
@@ -874,6 +874,7 @@
div,
div_assign,
diverging_block_default,
dl,
do_not_recommend,
doc,
doc_alias,
@@ -5,9 +5,9 @@ pub(crate) fn target() -> Target {
arch: "avr".into(),
metadata: crate::spec::TargetMetadata {
description: None,
tier: None,
host_tools: None,
std: None,
tier: Some(3),
host_tools: Some(false),
std: Some(false),
},
data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8".into(),
llvm_target: "avr-unknown-unknown".into(),
+13 -17
View File
@@ -12,7 +12,7 @@
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use std::{fmt, panic, str};
use std::{panic, str};
pub(crate) use make::{BuildDocTestBuilder, DocTestBuilder};
pub(crate) use markdown::test as test_markdown;
@@ -60,24 +60,15 @@ fn add_compilation_time(&mut self, duration: Duration) {
self.added_compilation_times += 1;
}
fn display_times(&self) {
/// Returns `(total_time, compilation_time)`.
fn times_in_secs(&self) -> Option<(f64, f64)> {
// If no merged doctest was compiled, then there is nothing to display since the numbers
// displayed by `libtest` for standalone tests are already accurate (they include both
// compilation and runtime).
if self.added_compilation_times > 0 {
println!("{self}");
if self.added_compilation_times == 0 {
return None;
}
}
}
impl fmt::Display for MergedDoctestTimes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"all doctests ran in {:.2}s; merged doctests compilation took {:.2}s",
self.total_time.elapsed().as_secs_f64(),
self.compilation_time.as_secs_f64(),
)
Some((self.total_time.elapsed().as_secs_f64(), self.compilation_time.as_secs_f64()))
}
}
@@ -402,15 +393,20 @@ pub(crate) fn run_tests(
if ran_edition_tests == 0 || !standalone_tests.is_empty() {
standalone_tests.sort_by(|a, b| a.desc.name.as_slice().cmp(b.desc.name.as_slice()));
test::test_main_with_exit_callback(&test_args, standalone_tests, None, || {
let times = times.times_in_secs();
// We ensure temp dir destructor is called.
std::mem::drop(temp_dir.take());
times.display_times();
if let Some((total_time, compilation_time)) = times {
test::print_merged_doctests_times(&test_args, total_time, compilation_time);
}
});
} else {
// If the first condition branch exited successfully, `test_main_with_exit_callback` will
// not exit the process. So to prevent displaying the times twice, we put it behind an
// `else` condition.
times.display_times();
if let Some((total_time, compilation_time)) = times.times_in_secs() {
test::print_merged_doctests_times(&test_args, total_time, compilation_time);
}
}
// We ensure temp dir destructor is called.
std::mem::drop(temp_dir);
+13 -18
View File
@@ -18,11 +18,6 @@
// but each shadow argument is `width` times larger (thus 16 and 20 elements here).
// `d_square3` instead takes `width` (4) shadow arguments, which are all the same size as the
// original function arguments.
//
// FIXME(autodiff): We currently can't test `d_square1` and `d_square3` in the same file, since they
// generate the same dummy functions which get merged by LLVM, breaking pieces of our pipeline which
// try to rewrite the dummy functions later. We should consider to change to pure declarations both
// in our frontend and in the llvm backend to avoid these issues.
#![feature(autodiff)]
@@ -30,7 +25,7 @@
// CHECK: ;
#[no_mangle]
//#[autodiff(d_square1, Forward, Dual, Dual)]
#[autodiff_forward(d_square1, Dual, Dual)]
#[autodiff_forward(d_square2, 4, Dualv, Dualv)]
#[autodiff_forward(d_square3, 4, Dual, Dual)]
fn square(x: &[f32], y: &mut [f32]) {
@@ -79,25 +74,25 @@ fn main() {
let mut dy3_4 = std::hint::black_box(vec![0.0; 5]);
// scalar.
//d_square1(&x1, &z1, &mut y1, &mut dy1_1);
//d_square1(&x1, &z2, &mut y2, &mut dy1_2);
//d_square1(&x1, &z3, &mut y3, &mut dy1_3);
//d_square1(&x1, &z4, &mut y4, &mut dy1_4);
d_square1(&x1, &z1, &mut y1, &mut dy1_1);
d_square1(&x1, &z2, &mut y2, &mut dy1_2);
d_square1(&x1, &z3, &mut y3, &mut dy1_3);
d_square1(&x1, &z4, &mut y4, &mut dy1_4);
// assert y1 == y2 == y3 == y4
//for i in 0..5 {
// assert_eq!(y1[i], y2[i]);
// assert_eq!(y1[i], y3[i]);
// assert_eq!(y1[i], y4[i]);
//}
for i in 0..5 {
assert_eq!(y1[i], y2[i]);
assert_eq!(y1[i], y3[i]);
assert_eq!(y1[i], y4[i]);
}
// batch mode A)
d_square2(&x1, &z5, &mut y5, &mut dy2);
// assert y1 == y2 == y3 == y4 == y5
//for i in 0..5 {
// assert_eq!(y1[i], y5[i]);
//}
for i in 0..5 {
assert_eq!(y1[i], y5[i]);
}
// batch mode B)
d_square3(&x1, &z1, &z2, &z3, &z4, &mut y6, &mut dy3_1, &mut dy3_2, &mut dy3_3, &mut dy3_4);
+2 -2
View File
@@ -32,9 +32,9 @@ fn square2(x: &f64) -> f64 {
// CHECK-NOT:br
// CHECK-NOT:ret
// CHECK:; call identical_fnc::d_square
// CHECK-NEXT:call fastcc void @_ZN13identical_fnc8d_square17hcb5768e95528c35fE(double %x.val, ptr noalias noundef align 8 dereferenceable(8) %dx1)
// CHECK-NEXT:call fastcc void @_ZN13identical_fnc8d_square[[HASH:.+]](double %x.val, ptr noalias noundef align 8 dereferenceable(8) %dx1)
// CHECK:; call identical_fnc::d_square
// CHECK-NEXT:call fastcc void @_ZN13identical_fnc8d_square17hcb5768e95528c35fE(double %x.val, ptr noalias noundef align 8 dereferenceable(8) %dx2)
// CHECK-NEXT:call fastcc void @_ZN13identical_fnc8d_square[[HASH]](double %x.val, ptr noalias noundef align 8 dereferenceable(8) %dx2)
fn main() {
let x = std::hint::black_box(3.0);
@@ -0,0 +1,3 @@
//! ```
//! let x = 12;
//! ```
@@ -0,0 +1,83 @@
//! Regression test to ensure that the output format is respected for doctests.
//!
//! Regression test for <https://github.com/rust-lang/rust/issues/144798>.
//@ ignore-cross-compile
use run_make_support::{rustdoc, serde_json};
fn run_test(edition: &str, format: Option<&str>) -> String {
let mut r = rustdoc();
r.input("file.rs").edition(edition).arg("--test");
if let Some(format) = format {
r.args(&[
"--test-args",
"-Zunstable-options",
"--test-args",
"--format",
"--test-args",
format,
]);
}
r.run().stdout_utf8()
}
fn check_json_output(edition: &str, expected_reports: usize) {
let out = run_test(edition, Some("json"));
let mut found_report = 0;
for (line_nb, line) in out.lines().enumerate() {
match serde_json::from_str::<serde_json::Value>(&line) {
Ok(value) => {
if value.get("type") == Some(&serde_json::json!("report")) {
found_report += 1;
}
}
Err(error) => panic!(
"failed for {edition} edition (json format) at line {}: non-JSON value: {error}\n\
====== output ======\n{out}",
line_nb + 1,
),
}
}
if found_report != expected_reports {
panic!(
"failed for {edition} edition (json format): expected {expected_reports} doctest \
time `report`, found {found_report}\n====== output ======\n{out}",
);
}
}
fn check_non_json_output(edition: &str, expected_reports: usize) {
let out = run_test(edition, None);
let mut found_report = 0;
for (line_nb, line) in out.lines().enumerate() {
if line.starts_with('{') && serde_json::from_str::<serde_json::Value>(&line).is_ok() {
panic!(
"failed for {edition} edition: unexpected json at line {}: `{line}`\n\
====== output ======\n{out}",
line_nb + 1
);
}
if line.starts_with("all doctests ran in")
&& line.contains("; merged doctests compilation took ")
{
found_report += 1;
}
}
if found_report != expected_reports {
panic!(
"failed for {edition} edition: expected {expected_reports} doctest time `report`, \
found {found_report}\n====== output ======\n{out}",
);
}
}
fn main() {
// Only the merged doctests generate the "times report".
check_json_output("2021", 0);
check_json_output("2024", 1);
// Only the merged doctests generate the "times report".
check_non_json_output("2021", 0);
check_non_json_output("2024", 1);
}
@@ -0,0 +1,10 @@
Future incompatibility report: Future breakage diagnostic:
warning: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", wasm_import_module = "...")]`
--> $DIR/link-dl.rs:14:1
|
LL | #[link="dl"]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
@@ -0,0 +1,23 @@
error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", wasm_import_module = "...")]`
--> $DIR/link-dl.rs:14:1
|
LL | #[link="dl"]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
= note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
error: aborting due to 1 previous error
Future incompatibility report: Future breakage diagnostic:
error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", wasm_import_module = "...")]`
--> $DIR/link-dl.rs:14:1
|
LL | #[link="dl"]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
= note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
+19
View File
@@ -0,0 +1,19 @@
// Regression test for an issue discovered in https://github.com/rust-lang/rust/pull/143193/files and rediscovered in https://github.com/rust-lang/rust/issues/147254#event-20049906781
// Malformed #[link] attribute was supposed to be deny-by-default report-in-deps FCW,
// but accidentally was landed as a hard error.
//
// revision `default_fcw` tests that with `ill_formed_attribute_input` (the default) denied,
// the attribute produces an FCW
// revision `allowed` tests that with `ill_formed_attribute_input` allowed the test passes
//@ revisions: default_fcw allowed
//@[allowed] check-pass
#[cfg_attr(allowed, allow(ill_formed_attribute_input))]
#[link="dl"]
//[default_fcw]~^ ERROR valid forms for the attribute are
//[default_fcw]~| WARN previously accepted
extern "C" { }
fn main() {}