From 6f214c5bb3959dc8a646fac0dafdcaeaf7e025f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 13 Mar 2025 13:14:14 +0100 Subject: [PATCH 01/26] Fix pluralization of tests --- src/ci/citool/src/merge_report.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/citool/src/merge_report.rs b/src/ci/citool/src/merge_report.rs index 17e42d49286..2dbe383b912 100644 --- a/src/ci/citool/src/merge_report.rs +++ b/src/ci/citool/src/merge_report.rs @@ -242,7 +242,7 @@ fn report_test_changes(mut diffs: Vec) { println!(" - {}: {}", test.name, format_diff(&outcome_diff)); } if extra_tests > 0 { - println!(" - (and {extra_tests} additional {})", pluralize("tests", extra_tests)); + println!(" - (and {extra_tests} additional {})", pluralize("test", extra_tests)); } } From 208cef45fc963528a8959e3b153d3b238ca1e187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 13 Mar 2025 13:15:38 +0100 Subject: [PATCH 02/26] Add note about the experimental status --- .github/workflows/post-merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml index 31e075f45d6..da566a91b46 100644 --- a/.github/workflows/post-merge.yml +++ b/.github/workflows/post-merge.yml @@ -35,7 +35,7 @@ jobs: cd src/ci/citool - echo "Post-merge analysis result" > output.log + printf "*This is an experimental post-merge analysis result. You can ignore it.*\n\n" > output.log cargo run --release post-merge-report ${PARENT_COMMIT} ${{ github.sha }} >> output.log cat output.log From 2192d5c4e218aa137f7d38bc6c93e36af6149bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 13 Mar 2025 13:18:47 +0100 Subject: [PATCH 03/26] Print the compared SHAs --- src/ci/citool/src/merge_report.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ci/citool/src/merge_report.rs b/src/ci/citool/src/merge_report.rs index 2dbe383b912..21b77299cdb 100644 --- a/src/ci/citool/src/merge_report.rs +++ b/src/ci/citool/src/merge_report.rs @@ -14,6 +14,8 @@ type JobName = String; pub fn post_merge_report(job_db: JobDatabase, parent: Sha, current: Sha) -> anyhow::Result<()> { let jobs = download_all_metrics(&job_db, &parent, ¤t)?; let diffs = aggregate_test_diffs(&jobs)?; + + println!("Comparing {parent} (base) -> {current} (this PR)\n"); report_test_changes(diffs); Ok(()) From 7ed913be3196ac43f6938ba5beb01e72464cc1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 13 Mar 2025 13:26:45 +0100 Subject: [PATCH 04/26] Add cache for downloading job metrics To make it easier to experiment locally. --- src/ci/citool/src/merge_report.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/ci/citool/src/merge_report.rs b/src/ci/citool/src/merge_report.rs index 21b77299cdb..76b7d779abc 100644 --- a/src/ci/citool/src/merge_report.rs +++ b/src/ci/citool/src/merge_report.rs @@ -1,5 +1,6 @@ use std::cmp::Reverse; use std::collections::HashMap; +use std::path::PathBuf; use anyhow::Context; use build_helper::metrics::{JsonRoot, TestOutcome}; @@ -56,7 +57,16 @@ Maybe it was newly added?"#, Ok(jobs) } +/// Downloads job metrics of the given job for the given commit. +/// Caches the result on the local disk. fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result { + let cache_path = PathBuf::from(".citool-cache").join(sha).join(job_name).join("metrics.json"); + if let Some(cache_entry) = + std::fs::read_to_string(&cache_path).ok().and_then(|data| serde_json::from_str(&data).ok()) + { + return Ok(cache_entry); + } + let url = get_metrics_url(job_name, sha); let mut response = ureq::get(&url).call()?; if !response.status().is_success() { @@ -70,6 +80,13 @@ fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result { .body_mut() .read_json() .with_context(|| anyhow::anyhow!("cannot deserialize metrics from {url}"))?; + + // Ignore errors if cache cannot be created + if std::fs::create_dir_all(cache_path.parent().unwrap()).is_ok() { + if let Ok(serialized) = serde_json::to_string(&data) { + let _ = std::fs::write(&cache_path, &serialized); + } + } Ok(data) } From 5a7f227351dc12fe3217394c9ecb7e9643c6d67e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 13 Mar 2025 13:36:34 +0100 Subject: [PATCH 05/26] Collapse report in `
` --- .github/workflows/post-merge.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml index da566a91b46..de31c28cc90 100644 --- a/.github/workflows/post-merge.yml +++ b/.github/workflows/post-merge.yml @@ -35,8 +35,13 @@ jobs: cd src/ci/citool - printf "*This is an experimental post-merge analysis result. You can ignore it.*\n\n" > output.log + printf "*This is an experimental post-merge analysis report. You can ignore it.*\n\n" > output.log + printf "
\nPost-merge report\n\n" >> output.log + cargo run --release post-merge-report ${PARENT_COMMIT} ${{ github.sha }} >> output.log + + printf "
\n" >> output.log + cat output.log gh pr comment ${HEAD_PR} -F output.log From d5d633d2460e45df25c679933ea678367b4d94a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 13 Mar 2025 13:55:03 +0100 Subject: [PATCH 06/26] Group diffs by tests, rather than job groups --- src/ci/citool/src/merge_report.rs | 186 ++++++++++++++++-------------- 1 file changed, 98 insertions(+), 88 deletions(-) diff --git a/src/ci/citool/src/merge_report.rs b/src/ci/citool/src/merge_report.rs index 76b7d779abc..918e9b92f1e 100644 --- a/src/ci/citool/src/merge_report.rs +++ b/src/ci/citool/src/merge_report.rs @@ -1,5 +1,4 @@ -use std::cmp::Reverse; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use anyhow::Context; @@ -14,10 +13,10 @@ type JobName = String; /// Computes a post merge CI analysis report between the `parent` and `current` commits. pub fn post_merge_report(job_db: JobDatabase, parent: Sha, current: Sha) -> anyhow::Result<()> { let jobs = download_all_metrics(&job_db, &parent, ¤t)?; - let diffs = aggregate_test_diffs(&jobs)?; + let aggregated_test_diffs = aggregate_test_diffs(&jobs)?; println!("Comparing {parent} (base) -> {current} (this PR)\n"); - report_test_changes(diffs); + report_test_diffs(aggregated_test_diffs); Ok(()) } @@ -95,72 +94,30 @@ fn get_metrics_url(job_name: &str, sha: &str) -> String { format!("https://ci-artifacts.rust-lang.org/rustc-builds{suffix}/{sha}/metrics-{job_name}.json") } +/// Represents a difference in the outcome of tests between a base and a current commit. +/// Maps test diffs to jobs that contained them. +#[derive(Debug)] +struct AggregatedTestDiffs { + diffs: HashMap>, +} + fn aggregate_test_diffs( jobs: &HashMap, -) -> anyhow::Result> { - let mut job_diffs = vec![]; +) -> anyhow::Result { + let mut diffs: HashMap> = HashMap::new(); // Aggregate test suites for (name, metrics) in jobs { if let Some(parent) = &metrics.parent { let tests_parent = aggregate_tests(parent); let tests_current = aggregate_tests(&metrics.current); - let test_diffs = calculate_test_diffs(tests_parent, tests_current); - if !test_diffs.is_empty() { - job_diffs.push((name.clone(), test_diffs)); + for diff in calculate_test_diffs(tests_parent, tests_current) { + diffs.entry(diff).or_default().push(name.to_string()); } } } - // Aggregate jobs with the same diff, as often the same diff will appear in many jobs - let job_diffs: HashMap, Vec> = - job_diffs.into_iter().fold(HashMap::new(), |mut acc, (job, diffs)| { - acc.entry(diffs).or_default().push(job); - acc - }); - - Ok(job_diffs - .into_iter() - .map(|(test_diffs, jobs)| AggregatedTestDiffs { jobs, test_diffs }) - .collect()) -} - -fn calculate_test_diffs( - reference: TestSuiteData, - current: TestSuiteData, -) -> Vec<(Test, TestOutcomeDiff)> { - let mut diffs = vec![]; - for (test, outcome) in ¤t.tests { - match reference.tests.get(test) { - Some(before) => { - if before != outcome { - diffs.push(( - test.clone(), - TestOutcomeDiff::ChangeOutcome { - before: before.clone(), - after: outcome.clone(), - }, - )); - } - } - None => diffs.push((test.clone(), TestOutcomeDiff::Added(outcome.clone()))), - } - } - for (test, outcome) in &reference.tests { - if !current.tests.contains_key(test) { - diffs.push((test.clone(), TestOutcomeDiff::Missing { before: outcome.clone() })); - } - } - - diffs -} - -/// Represents a difference in the outcome of tests between a base and a current commit. -#[derive(Debug)] -struct AggregatedTestDiffs { - /// All jobs that had the exact same test diffs. - jobs: Vec, - test_diffs: Vec<(Test, TestOutcomeDiff)>, + Ok(AggregatedTestDiffs { diffs }) } #[derive(Eq, PartialEq, Hash, Debug)] @@ -170,6 +127,47 @@ enum TestOutcomeDiff { Added(TestOutcome), } +#[derive(Eq, PartialEq, Hash, Debug)] +struct TestDiff { + test: Test, + diff: TestOutcomeDiff, +} + +fn calculate_test_diffs(parent: TestSuiteData, current: TestSuiteData) -> HashSet { + let mut diffs = HashSet::new(); + for (test, outcome) in ¤t.tests { + match parent.tests.get(test) { + Some(before) => { + if before != outcome { + diffs.insert(TestDiff { + test: test.clone(), + diff: TestOutcomeDiff::ChangeOutcome { + before: before.clone(), + after: outcome.clone(), + }, + }); + } + } + None => { + diffs.insert(TestDiff { + test: test.clone(), + diff: TestOutcomeDiff::Added(outcome.clone()), + }); + } + } + } + for (test, outcome) in &parent.tests { + if !current.tests.contains_key(test) { + diffs.insert(TestDiff { + test: test.clone(), + diff: TestOutcomeDiff::Missing { before: outcome.clone() }, + }); + } + } + + diffs +} + /// Aggregates test suite executions from all bootstrap invocations in a given CI job. #[derive(Default)] struct TestSuiteData { @@ -200,16 +198,13 @@ fn normalize_test_name(name: &str) -> String { } /// Prints test changes in Markdown format to stdout. -fn report_test_changes(mut diffs: Vec) { +fn report_test_diffs(mut diff: AggregatedTestDiffs) { println!("## Test differences"); - if diffs.is_empty() { + if diff.diffs.is_empty() { println!("No test diffs found"); return; } - // Sort diffs in decreasing order by diff count - diffs.sort_by_key(|entry| Reverse(entry.test_diffs.len())); - fn format_outcome(outcome: &TestOutcome) -> String { match outcome { TestOutcome::Passed => "pass".to_string(), @@ -238,36 +233,51 @@ fn report_test_changes(mut diffs: Vec) { } } - let max_diff_count = 10; - let max_job_count = 5; - let max_test_count = 10; + // It would be quite noisy to repeat the jobs that contained the test changes after/next to + // every test diff. At the same time, grouping the test diffs by + // [unique set of jobs that contained them] also doesn't work well, because the test diffs + // would have to be duplicated several times. + // Instead, we create a set of unique job groups, and then print a job group after each test. + // We then print the job groups at the end, as a sort of index. + let mut grouped_diffs: Vec<(&TestDiff, u64)> = vec![]; + let mut job_list_to_group: HashMap<&[JobName], u64> = HashMap::new(); + let mut job_index: Vec<&[JobName]> = vec![]; - for diff in diffs.iter().take(max_diff_count) { - let mut jobs = diff.jobs.clone(); + for (_, jobs) in diff.diffs.iter_mut() { jobs.sort(); - - let jobs = jobs.iter().take(max_job_count).map(|j| format!("`{j}`")).collect::>(); - - let extra_jobs = diff.jobs.len().saturating_sub(max_job_count); - let suffix = if extra_jobs > 0 { - format!(" (and {extra_jobs} {})", pluralize("other", extra_jobs)) - } else { - String::new() - }; - println!("- {}{suffix}", jobs.join(",")); - - let extra_tests = diff.test_diffs.len().saturating_sub(max_test_count); - for (test, outcome_diff) in diff.test_diffs.iter().take(max_test_count) { - println!(" - {}: {}", test.name, format_diff(&outcome_diff)); - } - if extra_tests > 0 { - println!(" - (and {extra_tests} additional {})", pluralize("test", extra_tests)); - } } - let extra_diffs = diffs.len().saturating_sub(max_diff_count); + let max_diff_count = 100; + for (diff, jobs) in diff.diffs.iter().take(max_diff_count) { + let jobs = &*jobs; + let job_group = match job_list_to_group.get(jobs.as_slice()) { + Some(id) => *id, + None => { + let id = job_index.len() as u64; + job_index.push(jobs); + job_list_to_group.insert(jobs, id); + id + } + }; + grouped_diffs.push((diff, job_group)); + } + + // Sort diffs by job group and test name + grouped_diffs.sort_by(|(d1, g1), (d2, g2)| g1.cmp(&g2).then(d1.test.name.cmp(&d2.test.name))); + + for (diff, job_group) in grouped_diffs { + println!("- `{}`: {} (*J{job_group}*)", diff.test.name, format_diff(&diff.diff)); + } + + let extra_diffs = diff.diffs.len().saturating_sub(max_diff_count); if extra_diffs > 0 { - println!("\n(and {extra_diffs} additional {})", pluralize("diff", extra_diffs)); + println!("\n(and {extra_diffs} additional {})", pluralize("test diff", extra_diffs)); + } + + // Now print the job index + println!("\n**Job index**\n"); + for (group, jobs) in job_index.into_iter().enumerate() { + println!("- J{group}: `{}`", jobs.join(", ")); } } From f981a0a0cd266e88c4c504a7d3218d045cc8104e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 13 Mar 2025 14:31:23 +0100 Subject: [PATCH 07/26] Do not print doctest diffs in the report When they are moved around in code, their name changes, which produces too noisy diffs. --- src/ci/citool/src/merge_report.rs | 56 ++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/src/ci/citool/src/merge_report.rs b/src/ci/citool/src/merge_report.rs index 918e9b92f1e..be7246cfa5e 100644 --- a/src/ci/citool/src/merge_report.rs +++ b/src/ci/citool/src/merge_report.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use anyhow::Context; -use build_helper::metrics::{JsonRoot, TestOutcome}; +use build_helper::metrics::{JsonRoot, TestOutcome, TestSuiteMetadata}; use crate::jobs::JobDatabase; use crate::metrics::get_test_suites; @@ -177,6 +177,7 @@ struct TestSuiteData { #[derive(Hash, PartialEq, Eq, Debug, Clone)] struct Test { name: String, + is_doctest: bool, } /// Extracts all tests from the passed metrics and map them to their outcomes. @@ -185,7 +186,10 @@ fn aggregate_tests(metrics: &JsonRoot) -> TestSuiteData { let test_suites = get_test_suites(&metrics); for suite in test_suites { for test in &suite.tests { - let test_entry = Test { name: normalize_test_name(&test.name) }; + // Poor man's detection of doctests based on the "(line XYZ)" suffix + let is_doctest = matches!(suite.metadata, TestSuiteMetadata::CargoPackage { .. }) + && test.name.contains("(line"); + let test_entry = Test { name: normalize_test_name(&test.name), is_doctest }; tests.insert(test_entry, test.outcome.clone()); } } @@ -198,7 +202,7 @@ fn normalize_test_name(name: &str) -> String { } /// Prints test changes in Markdown format to stdout. -fn report_test_diffs(mut diff: AggregatedTestDiffs) { +fn report_test_diffs(diff: AggregatedTestDiffs) { println!("## Test differences"); if diff.diffs.is_empty() { println!("No test diffs found"); @@ -233,6 +237,10 @@ fn report_test_diffs(mut diff: AggregatedTestDiffs) { } } + fn format_job_group(group: u64) -> String { + format!("**J{group}**") + } + // It would be quite noisy to repeat the jobs that contained the test changes after/next to // every test diff. At the same time, grouping the test diffs by // [unique set of jobs that contained them] also doesn't work well, because the test diffs @@ -243,12 +251,20 @@ fn report_test_diffs(mut diff: AggregatedTestDiffs) { let mut job_list_to_group: HashMap<&[JobName], u64> = HashMap::new(); let mut job_index: Vec<&[JobName]> = vec![]; - for (_, jobs) in diff.diffs.iter_mut() { - jobs.sort(); - } + let original_diff_count = diff.diffs.len(); + let diffs = diff + .diffs + .into_iter() + .filter(|(diff, _)| !diff.test.is_doctest) + .map(|(diff, mut jobs)| { + jobs.sort(); + (diff, jobs) + }) + .collect::>(); + let doctest_count = original_diff_count.saturating_sub(diffs.len()); let max_diff_count = 100; - for (diff, jobs) in diff.diffs.iter().take(max_diff_count) { + for (diff, jobs) in diffs.iter().take(max_diff_count) { let jobs = &*jobs; let job_group = match job_list_to_group.get(jobs.as_slice()) { Some(id) => *id, @@ -266,18 +282,34 @@ fn report_test_diffs(mut diff: AggregatedTestDiffs) { grouped_diffs.sort_by(|(d1, g1), (d2, g2)| g1.cmp(&g2).then(d1.test.name.cmp(&d2.test.name))); for (diff, job_group) in grouped_diffs { - println!("- `{}`: {} (*J{job_group}*)", diff.test.name, format_diff(&diff.diff)); + println!( + "- `{}`: {} ({})", + diff.test.name, + format_diff(&diff.diff), + format_job_group(job_group) + ); } - let extra_diffs = diff.diffs.len().saturating_sub(max_diff_count); + let extra_diffs = diffs.len().saturating_sub(max_diff_count); if extra_diffs > 0 { println!("\n(and {extra_diffs} additional {})", pluralize("test diff", extra_diffs)); } - // Now print the job index - println!("\n**Job index**\n"); + if doctest_count > 0 { + println!( + "\nAdditionally, {doctest_count} doctest {} were found.", + pluralize("diff", doctest_count) + ); + } + + // Now print the job group index + println!("\n**Job group index**\n"); for (group, jobs) in job_index.into_iter().enumerate() { - println!("- J{group}: `{}`", jobs.join(", ")); + println!( + "- {}: {}", + format_job_group(group as u64), + jobs.iter().map(|j| format!("`{j}`")).collect::>().join(", ") + ); } } From e88512214729e7bde2ed91faf6e49b50c6d3677b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Mar 2025 16:48:52 +1100 Subject: [PATCH 08/26] Add a pretty printing test for fn params. Note that multiple parts of the output are incorrect. The following commits will fix this. --- tests/pretty/hir-fn-params.pp | 38 +++++++++++++++++++++++++++++++++++ tests/pretty/hir-fn-params.rs | 34 +++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 tests/pretty/hir-fn-params.pp create mode 100644 tests/pretty/hir-fn-params.rs diff --git a/tests/pretty/hir-fn-params.pp b/tests/pretty/hir-fn-params.pp new file mode 100644 index 00000000000..9749261175d --- /dev/null +++ b/tests/pretty/hir-fn-params.pp @@ -0,0 +1,38 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-fn-params.pp + +// This tests the pretty-printing of various kinds of function parameters. + +//--------------------------------------------------------------------------- +// Normal functions and methods. + +fn normal_fn(_: u32, a: u32) { } + +struct S; +impl S { + fn method(_: u32, a: u32) { } +} + +//--------------------------------------------------------------------------- +// More exotic forms, which get a different pretty-printing path. In the past, +// anonymous params and `_` params printed incorrectly, e.g. `fn(u32, _: u32)` +// was printed as `fn(: u32, : u32)`. +// +// Ideally we would also test invalid patterns, e.g. `fn(1: u32, &a: u32)`, +// because they had similar problems. But the pretty-printing tests currently +// can't contain compile errors. + +fn bare_fn(x: fn(: u32, : u32, a: u32)) { } + +extern "C" { + unsafe fn foreign_fn(: u32, a: u32); +} + +trait T { + fn trait_fn(: u32, : u32, a: u32); +} diff --git a/tests/pretty/hir-fn-params.rs b/tests/pretty/hir-fn-params.rs new file mode 100644 index 00000000000..5ace5289d08 --- /dev/null +++ b/tests/pretty/hir-fn-params.rs @@ -0,0 +1,34 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-fn-params.pp + +// This tests the pretty-printing of various kinds of function parameters. + +//--------------------------------------------------------------------------- +// Normal functions and methods. + +fn normal_fn(_: u32, a: u32) {} + +struct S; +impl S { + fn method(_: u32, a: u32) {} +} + +//--------------------------------------------------------------------------- +// More exotic forms, which get a different pretty-printing path. In the past, +// anonymous params and `_` params printed incorrectly, e.g. `fn(u32, _: u32)` +// was printed as `fn(: u32, : u32)`. +// +// Ideally we would also test invalid patterns, e.g. `fn(1: u32, &a: u32)`, +// because they had similar problems. But the pretty-printing tests currently +// can't contain compile errors. + +fn bare_fn(x: fn(u32, _: u32, a: u32)) {} + +extern "C" { + fn foreign_fn(_: u32, a: u32); +} + +trait T { + fn trait_fn(u32, _: u32, a: u32); +} From c4371786d623a56072d048b9dea64abccbf4a113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 12 Mar 2025 13:14:11 +0100 Subject: [PATCH 09/26] Create libgccjit.so.0 alias also for CI-downloaded GCC --- src/bootstrap/src/core/build_steps/gcc.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 5a4bc9bdbcb..ea5a312a716 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -63,11 +63,7 @@ impl Step for Gcc { } build_gcc(&metadata, builder, target); - - let lib_alias = metadata.install_dir.join("lib/libgccjit.so.0"); - if !lib_alias.exists() { - t!(builder.symlink_file(&libgccjit_path, lib_alias)); - } + create_lib_alias(builder, &libgccjit_path); t!(metadata.stamp.write()); @@ -75,6 +71,15 @@ impl Step for Gcc { } } +/// Creates a libgccjit.so.0 alias next to libgccjit.so if it does not +/// already exist +fn create_lib_alias(builder: &Builder<'_>, libgccjit: &PathBuf) { + let lib_alias = libgccjit.parent().unwrap().join("libgccjit.so.0"); + if !lib_alias.exists() { + t!(builder.symlink_file(libgccjit, lib_alias)); + } +} + pub struct Meta { stamp: BuildStamp, out_dir: PathBuf, @@ -109,8 +114,11 @@ fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option Date: Wed, 12 Mar 2025 17:24:51 +0100 Subject: [PATCH 10/26] Change GCC build flags --- src/bootstrap/src/core/build_steps/gcc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index ea5a312a716..0a3208b2363 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -218,7 +218,7 @@ fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) { .env("CXXFLAGS", "-Wno-everything -g -O2") .env("CFLAGS", "-Wno-everything -g -O2") .arg("--enable-host-shared") - .arg("--enable-languages=jit") + .arg("--enable-languages=c,jit,lto") .arg("--enable-checking=release") .arg("--disable-bootstrap") .arg("--disable-multilib") From 3fc7ca0fee9806983423dcd4aab06e42c856cd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 13 Mar 2025 11:31:08 +0100 Subject: [PATCH 11/26] Use GCC for building GCC --- src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index f54ecef1e30..ae5bf8946dd 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -101,7 +101,9 @@ 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 gcc + build-manifest bootstrap && \ + # Use GCC for building GCC, as it seems to behave badly when built with Clang + CC=/rustroot/bin/cc CXX=/rustroot/bin/c++ python3 ../x.py dist gcc ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang # This is the only builder which will create source tarballs From 34272a54689e1e9b9eac97e0f5e126cd4149ae39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 13 Mar 2025 16:27:41 +0100 Subject: [PATCH 12/26] Do not overwrite original `config.toml` in `opt-dist` So that follow-up CI commands can proceed normally. It will also avoid overwriting `config.toml` when running opt-dist tests locally. --- src/tools/opt-dist/src/tests.rs | 79 +++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index 8b3bd77141b..c8759bb6ff6 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -1,3 +1,5 @@ +use std::path::Path; + use anyhow::Context; use camino::{Utf8Path, Utf8PathBuf}; @@ -86,36 +88,57 @@ llvm-config = "{llvm_config}" log::info!("Using following `config.toml` for running tests:\n{config_content}"); // Simulate a stage 0 compiler with the extracted optimized dist artifacts. - std::fs::write("config.toml", config_content)?; + with_backed_up_file(Path::new("config.toml"), &config_content, || { + let x_py = env.checkout_path().join("x.py"); + let mut args = vec![ + env.python_binary(), + x_py.as_str(), + "test", + "--build", + env.host_tuple(), + "--stage", + "0", + "tests/assembly", + "tests/codegen", + "tests/codegen-units", + "tests/incremental", + "tests/mir-opt", + "tests/pretty", + "tests/run-make/glibc-symbols-x86_64-unknown-linux-gnu", + "tests/ui", + "tests/crashes", + ]; + for test_path in env.skipped_tests() { + args.extend(["--skip", test_path]); + } + cmd(&args) + .env("COMPILETEST_FORCE_STAGE0", "1") + // Also run dist-only tests + .env("COMPILETEST_ENABLE_DIST_TESTS", "1") + .run() + .context("Cannot execute tests") + }) +} - let x_py = env.checkout_path().join("x.py"); - let mut args = vec![ - env.python_binary(), - x_py.as_str(), - "test", - "--build", - env.host_tuple(), - "--stage", - "0", - "tests/assembly", - "tests/codegen", - "tests/codegen-units", - "tests/incremental", - "tests/mir-opt", - "tests/pretty", - "tests/run-make/glibc-symbols-x86_64-unknown-linux-gnu", - "tests/ui", - "tests/crashes", - ]; - for test_path in env.skipped_tests() { - args.extend(["--skip", test_path]); +/// Backup `path` (if it exists), then write `contents` into it, and then restore the original +/// contents of the file. +fn with_backed_up_file(path: &Path, contents: &str, func: F) -> anyhow::Result<()> +where + F: FnOnce() -> anyhow::Result<()>, +{ + let original_contents = + if path.is_file() { Some(std::fs::read_to_string(path)?) } else { None }; + + // Overwrite it with new contents + std::fs::write(path, contents)?; + + let ret = func(); + + if let Some(original_contents) = original_contents { + std::fs::write(path, original_contents)?; } - cmd(&args) - .env("COMPILETEST_FORCE_STAGE0", "1") - // Also run dist-only tests - .env("COMPILETEST_ENABLE_DIST_TESTS", "1") - .run() - .context("Cannot execute tests") + + ret } /// Tries to find the version of the dist artifacts (either nightly, beta, or 1.XY.Z). From 38fc11601ea95a4ba6b11f1aa0ad36fb9d8a53d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 13 Mar 2025 21:32:23 +0100 Subject: [PATCH 13/26] Store libgccjit.so in a lib directory in the GCC CI tarball --- src/bootstrap/src/core/build_steps/dist.rs | 2 +- src/bootstrap/src/core/build_steps/gcc.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index c393eb55c62..2354fe1ebaf 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2481,7 +2481,7 @@ impl Step for Gcc { fn run(self, builder: &Builder<'_>) -> Self::Output { let tarball = Tarball::new(builder, "gcc", &self.target.triple); let output = builder.ensure(super::gcc::Gcc { target: self.target }); - tarball.add_file(output.libgccjit, ".", 0o644); + tarball.add_file(output.libgccjit, "lib", 0o644); tarball.generate() } } diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 0a3208b2363..19525d4ebed 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -115,8 +115,7 @@ fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option Date: Fri, 14 Mar 2025 08:39:14 +1100 Subject: [PATCH 14/26] Inline and remove `FnParam::name`. It has a single call site. --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index b8517701667..8ab6e0c4159 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::Session; -use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; +use rustc_span::{DUMMY_SP, Ident, Span, kw, sym}; use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext}; @@ -2720,21 +2720,18 @@ impl FnParam<'_> { } } - fn name(&self) -> Option { - match self { - Self::Param(x) if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind => { - Some(ident.name) - } - Self::Name(x) if x.name != kw::Empty => Some(x.name), - _ => None, - } - } - fn display(&self, idx: usize) -> impl '_ + fmt::Display { struct D<'a>(FnParam<'a>, usize); impl fmt::Display for D<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(name) = self.0.name() { + let name = match self.0 { + FnParam::Param(x) if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind => { + Some(ident.name) + } + FnParam::Name(x) if x.name != kw::Empty => Some(x.name), + _ => None, + }; + if let Some(name) = name { write!(f, "`{name}`") } else { write!(f, "parameter #{}", self.1 + 1) From 958bc7b3655a0880361b11f9052fab84030cde26 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 14 Mar 2025 08:40:43 +1100 Subject: [PATCH 15/26] Handle `_` properly in a couple of places. Currently (PatKind::Wild` (i.e. `_`) gets turned by `lower_fn_params_to_names` into an empty identifier, which means it is printed incorrectly by HIR pretty printing. And likewise for `lower_fn_params_to_names`, which affects some error messages. This commit fixes them. This requires a slight tweak in a couple of places to continue using parameter numbers in some error messages. And it improves the output of `tests/ui/typeck/cyclic_type_ice.rs`: `/* _ */` is a better suggestion than `/* */`. --- compiler/rustc_ast_lowering/src/lib.rs | 9 +++++++- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 23 +++++++++++++------ compiler/rustc_middle/src/hir/map.rs | 3 ++- .../src/error_reporting/traits/suggestions.rs | 5 +++- tests/pretty/hir-fn-params.pp | 6 ++--- tests/ui/typeck/cyclic_type_ice.stderr | 2 +- 6 files changed, 34 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c7d37e2704d..df671cf4b86 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1516,7 +1516,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { PatKind::Ident(_, ident, _) => self.lower_ident(ident), - _ => Ident::new(kw::Empty, self.lower_span(param.pat.span)), + PatKind::Wild => Ident::new(kw::Underscore, self.lower_span(param.pat.span)), + _ => { + self.dcx().span_delayed_bug( + param.pat.span, + "non-ident/wild param pat must trigger an error", + ); + Ident::new(kw::Empty, self.lower_span(param.pat.span)) + } })) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 8ab6e0c4159..0a472c95221 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2712,11 +2712,12 @@ enum FnParam<'hir> { Param(&'hir hir::Param<'hir>), Name(&'hir Ident), } + impl FnParam<'_> { fn span(&self) -> Span { match self { - Self::Param(x) => x.span, - Self::Name(x) => x.span, + Self::Param(param) => param.span, + Self::Name(ident) => ident.span, } } @@ -2724,15 +2725,23 @@ impl FnParam<'_> { struct D<'a>(FnParam<'a>, usize); impl fmt::Display for D<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let name = match self.0 { - FnParam::Param(x) if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind => { + // A "unique" param name is one that (a) exists, and (b) is guaranteed to be unique + // among the parameters, i.e. `_` does not count. + let unique_name = match self.0 { + FnParam::Param(param) + if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind => + { + Some(ident.name) + } + FnParam::Name(ident) + if ident.name != kw::Empty && ident.name != kw::Underscore => + { Some(ident.name) } - FnParam::Name(x) if x.name != kw::Empty => Some(x.name), _ => None, }; - if let Some(name) = name { - write!(f, "`{name}`") + if let Some(unique_name) = unique_name { + write!(f, "`{unique_name}`") } else { write!(f, "parameter #{}", self.1 + 1) } diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index c85af81ee25..5c34dd6309e 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -281,8 +281,9 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator { - self.hir_body(id).params.iter().map(|arg| match arg.pat.kind { + self.hir_body(id).params.iter().map(|param| match param.pat.kind { PatKind::Binding(_, _, ident, _) => ident, + PatKind::Wild => Ident::new(kw::Underscore, param.pat.span), _ => Ident::empty(), }) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ad46a15a5ac..b56ed144377 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1998,7 +1998,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .iter() .enumerate() .map(|(i, ident)| { - if ident.name.is_empty() || ident.name == kw::SelfLower { + if ident.name.is_empty() + || ident.name == kw::Underscore + || ident.name == kw::SelfLower + { format!("arg{i}") } else { format!("{ident}") diff --git a/tests/pretty/hir-fn-params.pp b/tests/pretty/hir-fn-params.pp index 9749261175d..f33e26b7e8c 100644 --- a/tests/pretty/hir-fn-params.pp +++ b/tests/pretty/hir-fn-params.pp @@ -27,12 +27,12 @@ impl S { // because they had similar problems. But the pretty-printing tests currently // can't contain compile errors. -fn bare_fn(x: fn(: u32, : u32, a: u32)) { } +fn bare_fn(x: fn(: u32, _: u32, a: u32)) { } extern "C" { - unsafe fn foreign_fn(: u32, a: u32); + unsafe fn foreign_fn(_: u32, a: u32); } trait T { - fn trait_fn(: u32, : u32, a: u32); + fn trait_fn(: u32, _: u32, a: u32); } diff --git a/tests/ui/typeck/cyclic_type_ice.stderr b/tests/ui/typeck/cyclic_type_ice.stderr index 4dc02a53c02..645766becbf 100644 --- a/tests/ui/typeck/cyclic_type_ice.stderr +++ b/tests/ui/typeck/cyclic_type_ice.stderr @@ -23,7 +23,7 @@ LL | let f = |_, _| (); help: provide the argument | LL - f(f); -LL + f(/* */, /* */); +LL + f(/* _ */, /* _ */); | error: aborting due to 2 previous errors From bebd91feb32667b6a1bb7a11da91ab8a935b4c24 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 14 Mar 2025 07:29:19 +1100 Subject: [PATCH 16/26] Fix HIR param pretty printing some more. Anonymous params are currently represented with `kw::Empty`, so handle that properly. (Subsequent commits will get rid of the `kw::Empty`.) --- compiler/rustc_hir_pretty/src/lib.rs | 8 +++++--- tests/pretty/hir-fn-params.pp | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 3067766fb4d..1409310339a 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2148,9 +2148,11 @@ impl<'a> State<'a> { s.print_implicit_self(&decl.implicit_self); } else { if let Some(arg_name) = arg_names.get(i) { - s.word(arg_name.to_string()); - s.word(":"); - s.space(); + if arg_name.name != kw::Empty { + s.word(arg_name.to_string()); + s.word(":"); + s.space(); + } } else if let Some(body_id) = body_id { s.ann.nested(s, Nested::BodyParamPat(body_id, i)); s.word(":"); diff --git a/tests/pretty/hir-fn-params.pp b/tests/pretty/hir-fn-params.pp index f33e26b7e8c..3799c8a3c3b 100644 --- a/tests/pretty/hir-fn-params.pp +++ b/tests/pretty/hir-fn-params.pp @@ -27,12 +27,12 @@ impl S { // because they had similar problems. But the pretty-printing tests currently // can't contain compile errors. -fn bare_fn(x: fn(: u32, _: u32, a: u32)) { } +fn bare_fn(x: fn(u32, _: u32, a: u32)) { } extern "C" { unsafe fn foreign_fn(_: u32, a: u32); } trait T { - fn trait_fn(: u32, _: u32, a: u32); + fn trait_fn(u32, _: u32, a: u32); } From 79e4be1e9f1bd8032f3573a8f44f88814632a342 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 14 Mar 2025 09:02:45 +1100 Subject: [PATCH 17/26] Remove the ref from `FnParam::Ident`. --- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 0a472c95221..96d0a0fc6de 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2679,7 +2679,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?; debug_assert_eq!(params.len(), fn_inputs.len()); Some(( - fn_inputs.zip(params.iter().map(|param| FnParam::Name(param))).collect(), + fn_inputs.zip(params.iter().map(|¶m| FnParam::Name(param))).collect(), generics, )) } @@ -2710,7 +2710,7 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> { #[derive(Clone, Copy)] enum FnParam<'hir> { Param(&'hir hir::Param<'hir>), - Name(&'hir Ident), + Name(Ident), } impl FnParam<'_> { From b9f0ca11bc10b342633dadb0e8a8efc8b955bc6a Mon Sep 17 00:00:00 2001 From: Diane Ringo Date: Thu, 13 Mar 2025 20:31:59 -0500 Subject: [PATCH 18/26] Refactor is_snake_case. --- compiler/rustc_lint/src/nonstandard_style.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 722779d3268..9e4fdd2b3ce 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -274,18 +274,13 @@ impl NonSnakeCase { let ident = ident.trim_start_matches('\''); let ident = ident.trim_matches('_'); - let mut allow_underscore = true; - ident.chars().all(|c| { - allow_underscore = match c { - '_' if !allow_underscore => return false, - '_' => false, - // It would be more obvious to use `c.is_lowercase()`, - // but some characters do not have a lowercase form - c if !c.is_uppercase() => true, - _ => return false, - }; - true - }) + if ident.contains("__") { + return false; + } + + // This correctly handles letters in languages with and without + // cases, as well as numbers and underscores. + !ident.chars().any(char::is_uppercase) } let name = ident.name.as_str(); From d989bf5bbe511769d23fb43361f59d6a6ac76bc7 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Wed, 5 Mar 2025 16:08:14 +0800 Subject: [PATCH 19/26] rustc_target: Add target features for LoongArch v1.1 --- compiler/rustc_target/src/target_features.rs | 5 +++++ tests/ui/abi/compatibility.rs | 1 + .../bad-reg.loongarch64_lp64d.stderr | 12 +++++------ .../bad-reg.loongarch64_lp64s.stderr | 20 +++++++++---------- tests/ui/asm/loongarch/bad-reg.rs | 1 + tests/ui/check-cfg/target_feature.stderr | 5 +++++ 6 files changed, 28 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index d05466bb484..a725564132d 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -603,13 +603,18 @@ static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("d", Unstable(sym::loongarch_target_feature), &["f"]), + ("div32", Unstable(sym::loongarch_target_feature), &[]), ("f", Unstable(sym::loongarch_target_feature), &[]), ("frecipe", Unstable(sym::loongarch_target_feature), &[]), + ("lam-bh", Unstable(sym::loongarch_target_feature), &[]), + ("lamcas", Unstable(sym::loongarch_target_feature), &[]), ("lasx", Unstable(sym::loongarch_target_feature), &["lsx"]), ("lbt", Unstable(sym::loongarch_target_feature), &[]), + ("ld-seq-sa", Unstable(sym::loongarch_target_feature), &[]), ("lsx", Unstable(sym::loongarch_target_feature), &["d"]), ("lvz", Unstable(sym::loongarch_target_feature), &[]), ("relax", Unstable(sym::loongarch_target_feature), &[]), + ("scq", Unstable(sym::loongarch_target_feature), &[]), ("ual", Unstable(sym::loongarch_target_feature), &[]), // tidy-alphabetical-end ]; diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 01d90717107..64e65ece85d 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -40,6 +40,7 @@ //@ revisions: loongarch64 //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64] needs-llvm-components: loongarch +//@[loongarch64] min-llvm-version: 20 //FIXME: wasm is disabled due to . //FIXME @ revisions: wasm //FIXME @[wasm] compile-flags: --target wasm32-unknown-unknown diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr index 0e544119650..c88f3af7642 100644 --- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr +++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr @@ -1,35 +1,35 @@ error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:22:18 + --> $DIR/bad-reg.rs:23:18 | LL | asm!("", out("$r0") _); | ^^^^^^^^^^^^ error: invalid register `$tp`: reserved for TLS - --> $DIR/bad-reg.rs:24:18 + --> $DIR/bad-reg.rs:25:18 | LL | asm!("", out("$tp") _); | ^^^^^^^^^^^^ error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:27:18 | LL | asm!("", out("$sp") _); | ^^^^^^^^^^^^ error: invalid register `$r21`: reserved by the ABI - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:29:18 | LL | asm!("", out("$r21") _); | ^^^^^^^^^^^^^ error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("$fp") _); | ^^^^^^^^^^^^ error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("$r31") _); | ^^^^^^^^^^^^^ diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr index 6d0410dc6a1..cb8e55a9722 100644 --- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr +++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr @@ -1,59 +1,59 @@ error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:22:18 + --> $DIR/bad-reg.rs:23:18 | LL | asm!("", out("$r0") _); | ^^^^^^^^^^^^ error: invalid register `$tp`: reserved for TLS - --> $DIR/bad-reg.rs:24:18 + --> $DIR/bad-reg.rs:25:18 | LL | asm!("", out("$tp") _); | ^^^^^^^^^^^^ error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:27:18 | LL | asm!("", out("$sp") _); | ^^^^^^^^^^^^ error: invalid register `$r21`: reserved by the ABI - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:29:18 | LL | asm!("", out("$r21") _); | ^^^^^^^^^^^^^ error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("$fp") _); | ^^^^^^^^^^^^ error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("$r31") _); | ^^^^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:36:26 + --> $DIR/bad-reg.rs:37:26 | LL | asm!("/* {} */", in(freg) f); | ^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:38:26 + --> $DIR/bad-reg.rs:39:26 | LL | asm!("/* {} */", out(freg) _); | ^^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:40:26 + --> $DIR/bad-reg.rs:41:26 | LL | asm!("/* {} */", in(freg) d); | ^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:42:26 + --> $DIR/bad-reg.rs:43:26 | LL | asm!("/* {} */", out(freg) d); | ^^^^^^^^^^^ diff --git a/tests/ui/asm/loongarch/bad-reg.rs b/tests/ui/asm/loongarch/bad-reg.rs index 685b460bc92..db1c778e5a2 100644 --- a/tests/ui/asm/loongarch/bad-reg.rs +++ b/tests/ui/asm/loongarch/bad-reg.rs @@ -1,6 +1,7 @@ //@ add-core-stubs //@ needs-asm-support //@ revisions: loongarch64_lp64d loongarch64_lp64s +//@ min-llvm-version: 20 //@[loongarch64_lp64d] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64_lp64d] needs-llvm-components: loongarch //@[loongarch64_lp64s] compile-flags: --target loongarch64-unknown-none-softfloat diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 5b82d3f539f..a9d67481ba1 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -60,6 +60,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `d32` `deflate-conversion` `dit` +`div32` `doloop` `dotprod` `dpb` @@ -133,8 +134,11 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `jsconv` `kl` `lahfsahf` +`lam-bh` +`lamcas` `lasx` `lbt` +`ld-seq-sa` `leoncasa` `lor` `lse` @@ -190,6 +194,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `reserve-x18` `rtm` `sb` +`scq` `sha` `sha2` `sha3` From aad1db737347b93b51a7dc45dcb6bec9e367bc02 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Fri, 14 Mar 2025 00:39:18 +0800 Subject: [PATCH 20/26] Pass precise HirId when calling check_stability Signed-off-by: xizheyin --- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 4 +- ...truct-pat-fields-stability-issue-138319.rs | 12 ++++++ ...t-pat-fields-stability-issue-138319.stderr | 10 +++++ .../check-stability-issue-138319.rs | 39 +++++++++++++++++++ .../check-stability-issue-138319.stderr | 10 +++++ 6 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.rs create mode 100644 tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.stderr create mode 100644 tests/ui/stability-attribute/check-stability-issue-138319.rs create mode 100644 tests/ui/stability-attribute/check-stability-issue-138319.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7c6bb495be3..7e8e4e3a561 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2060,7 +2060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // struct-like enums (yet...), but it's definitely not // a bug to have constructed one. if adt_kind != AdtKind::Enum { - tcx.check_stability(v_field.did, Some(expr.hir_id), field.span, None); + tcx.check_stability(v_field.did, Some(field.hir_id), field.span, None); } self.field_ty(field.span, v_field, args) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 7e6973259fe..3d1c61a9c34 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1422,7 +1422,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.check_stability( variant.fields[FieldIdx::from_usize(i)].did, - Some(pat.hir_id), + Some(subpat.hir_id), subpat.span, None, ); @@ -1686,7 +1686,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .get(&ident) .map(|(i, f)| { self.write_field_index(field.hir_id, *i); - self.tcx.check_stability(f.did, Some(pat.hir_id), span, None); + self.tcx.check_stability(f.did, Some(field.hir_id), span, None); self.field_ty(span, f, args) }) .unwrap_or_else(|| { diff --git a/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.rs b/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.rs new file mode 100644 index 00000000000..b951c6d92ee --- /dev/null +++ b/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.rs @@ -0,0 +1,12 @@ +//@ check-pass +struct Point { + #[deprecated = "x is deprecated"] + _x: i32, + _y: i32, +} + +fn main() { + let p = Point { _x: 1, _y: 2 }; //~ WARNING use of deprecated field `Point::_x` + // Before fix, it report an warning + let Point { #[expect(deprecated)]_x, .. } = p; +} diff --git a/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.stderr b/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.stderr new file mode 100644 index 00000000000..707eb58e547 --- /dev/null +++ b/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.stderr @@ -0,0 +1,10 @@ +warning: use of deprecated field `Point::_x`: x is deprecated + --> $DIR/check-struct-pat-fields-stability-issue-138319.rs:9:21 + | +LL | let p = Point { _x: 1, _y: 2 }; + | ^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/stability-attribute/check-stability-issue-138319.rs b/tests/ui/stability-attribute/check-stability-issue-138319.rs new file mode 100644 index 00000000000..5440e0cad94 --- /dev/null +++ b/tests/ui/stability-attribute/check-stability-issue-138319.rs @@ -0,0 +1,39 @@ +//@ check-pass +fn _foo() { + _Bar { //~ WARNING use of deprecated struct `_Bar`: reason + #[expect(deprecated)] + foo: 0, + }; +} + +#[deprecated = "reason"] +struct _Bar { + foo: u32, +} + +fn _foo2() { + #[expect(deprecated)] + _Bar2 { + foo2: 0, + }; +} + +#[deprecated = "reason"] +struct _Bar2 { + foo2: u32, +} + +fn _foo3() { + _Bar3 { + #[expect(deprecated)] + foo3: 0, + }; +} + +struct _Bar3 { + #[deprecated = "reason"] + foo3: u32, +} + + +fn main() {} diff --git a/tests/ui/stability-attribute/check-stability-issue-138319.stderr b/tests/ui/stability-attribute/check-stability-issue-138319.stderr new file mode 100644 index 00000000000..4a2c3554a1e --- /dev/null +++ b/tests/ui/stability-attribute/check-stability-issue-138319.stderr @@ -0,0 +1,10 @@ +warning: use of deprecated struct `_Bar`: reason + --> $DIR/check-stability-issue-138319.rs:3:5 + | +LL | _Bar { + | ^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: 1 warning emitted + From 6ef465ba126013fa6add41813cd8299072507df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 09:09:26 +0100 Subject: [PATCH 21/26] Add clarification about doctests --- src/ci/citool/src/merge_report.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/citool/src/merge_report.rs b/src/ci/citool/src/merge_report.rs index be7246cfa5e..62daa2e6853 100644 --- a/src/ci/citool/src/merge_report.rs +++ b/src/ci/citool/src/merge_report.rs @@ -297,7 +297,7 @@ fn report_test_diffs(diff: AggregatedTestDiffs) { if doctest_count > 0 { println!( - "\nAdditionally, {doctest_count} doctest {} were found.", + "\nAdditionally, {doctest_count} doctest {} were found. These are ignored, as they are noisy.", pluralize("diff", doctest_count) ); } From bf095f6ecee956b3942625d9480e3a2f13666a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 09:16:06 +0100 Subject: [PATCH 22/26] Ensure that GCC is not built using Clang, as it misbehaves --- src/bootstrap/src/core/build_steps/gcc.rs | 15 +++++++++------ src/bootstrap/src/lib.rs | 11 +++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 19525d4ebed..0aa2a332531 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -184,6 +184,14 @@ fn libgccjit_built_path(install_dir: &Path) -> PathBuf { } fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) { + if builder.build.cc_tool(target).is_like_clang() + || builder.build.cxx_tool(target).is_like_clang() + { + panic!( + "Attempting to build GCC using Clang, which is known to misbehave. Please use GCC as the host C/C++ compiler. " + ); + } + let Meta { stamp: _, out_dir, install_dir, root } = metadata; t!(fs::create_dir_all(out_dir)); @@ -210,18 +218,13 @@ fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) { let mut configure_cmd = command(src_dir.join("configure")); configure_cmd .current_dir(out_dir) - // On CI, we compile GCC with Clang. - // The -Wno-everything flag is needed to make GCC compile with Clang 19. - // `-g -O2` are the default flags that are otherwise used by Make. - // FIXME(kobzol): change the flags once we have [gcc] configuration in config.toml. - .env("CXXFLAGS", "-Wno-everything -g -O2") - .env("CFLAGS", "-Wno-everything -g -O2") .arg("--enable-host-shared") .arg("--enable-languages=c,jit,lto") .arg("--enable-checking=release") .arg("--disable-bootstrap") .arg("--disable-multilib") .arg(format!("--prefix={}", install_dir.display())); + let cc = builder.build.cc(target).display().to_string(); let cc = builder .build diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index fc408437838..2693e85ca48 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -27,6 +27,7 @@ use std::{env, fs, io, str}; use build_helper::ci::gha; use build_helper::exit; +use cc::Tool; use termcolor::{ColorChoice, StandardStream, WriteColor}; use utils::build_stamp::BuildStamp; use utils::channel::GitInfo; @@ -1218,6 +1219,16 @@ Executed at: {executed_at}"#, self.cc.borrow()[&target].path().into() } + /// Returns the internal `cc::Tool` for the C compiler. + fn cc_tool(&self, target: TargetSelection) -> Tool { + self.cc.borrow()[&target].clone() + } + + /// Returns the internal `cc::Tool` for the C++ compiler. + fn cxx_tool(&self, target: TargetSelection) -> Tool { + self.cxx.borrow()[&target].clone() + } + /// Returns C flags that `cc-rs` thinks should be enabled for the /// specified target by default. fn cc_handled_clags(&self, target: TargetSelection, c: CLang) -> Vec { From 9e3805d6d3435e6f96e110ec3e7128099c082c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 17:22:46 +0100 Subject: [PATCH 23/26] Mirror NetBSD sources --- .../build-netbsd-toolchain.sh | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh index 4a42f5da29f..ad21836253b 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh @@ -41,8 +41,6 @@ cd netbsd mkdir -p /x-tools/x86_64-unknown-netbsd/sysroot -# URL=https://ci-mirrors.rust-lang.org/rustc - # Hashes come from https://cdn.netbsd.org/pub/NetBSD/security/hashes/NetBSD-9.0_hashes.asc SRC_SHA=2c791ae009a6929c6fc893ec5df7e62910ee8207e0b2159d6937309c03efe175b6ae1e445829a13d041b6851334ad35c521f2fa03c97675d4a05f1fafe58ede0 GNUSRC_SHA=3710085a73feecf6a843415271ec794c90146b03f6bbd30f07c9e0c79febf8995d557e40194f1e05db655e4f5ef2fae97563f8456fceaae65d4ea98857a83b1c @@ -51,22 +49,16 @@ SYSSRC_SHA=60b9ddf4cc6402256473e2e1eefeabd9001aa4e205208715ecc6d6fc3f5b400e46994 BASE_SHA=b5926b107cebf40c3c19b4f6cd039b610987dd7f819e7cdde3bd1e5230a856906e7930b15ab242d52ced9f0bda01d574be59488b8dbb95fa5df2987d0a70995f COMP_SHA=38ea54f30d5fc2afea87e5096f06873e00182789e8ad9cec0cb3e9f7c538c1aa4779e63fd401a36ba02676158e83fa5c95e8e87898db59c1914fb206aecd82d2 -# FIXME: the archive URL is being used temporarily while the CDN is down. -# We should serve this from our own CDN -# SOURCE_URL=https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/source/sets -SOURCE_URL=http://archive.netbsd.org/pub/NetBSD-archive/NetBSD-9.0/source/sets -download src.tgz "$SOURCE_URL/src.tgz" "$SRC_SHA" tar xzf src.tgz -download gnusrc.tgz "$SOURCE_URL/gnusrc.tgz" "$GNUSRC_SHA" tar xzf gnusrc.tgz -download sharesrc.tgz "$SOURCE_URL/sharesrc.tgz" "$SHARESRC_SHA" tar xzf sharesrc.tgz -download syssrc.tgz "$SOURCE_URL/syssrc.tgz" "$SYSSRC_SHA" tar xzf syssrc.tgz +SOURCE_URL=https://ci-mirrors.rust-lang.org/rustc/2025-03-14-netbsd-9.0-src +download src.tgz "$SOURCE_URL-src.tgz" "$SRC_SHA" tar xzf src.tgz +download gnusrc.tgz "$SOURCE_URL-gnusrc.tgz" "$GNUSRC_SHA" tar xzf gnusrc.tgz +download sharesrc.tgz "$SOURCE_URL-sharesrc.tgz" "$SHARESRC_SHA" tar xzf sharesrc.tgz +download syssrc.tgz "$SOURCE_URL-syssrc.tgz" "$SYSSRC_SHA" tar xzf syssrc.tgz -# FIXME: the archive URL is being used temporarily while the CDN is down. -# We should serve this from our own CDN -# BINARY_URL=https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/amd64/binary/sets -BINARY_URL=http://archive.netbsd.org/pub/NetBSD-archive/NetBSD-9.0/amd64/binary/sets -download base.tar.xz "$BINARY_URL/base.tar.xz" "$BASE_SHA" \ +BINARY_URL=https://ci-mirrors.rust-lang.org/rustc/2025-03-14-netbsd-9.0-amd64-binary +download base.tar.xz "$BINARY_URL-base.tar.xz" "$BASE_SHA" \ tar xJf base.tar.xz -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib ./lib -download comp.tar.xz "$BINARY_URL/comp.tar.xz" "$COMP_SHA" \ +download comp.tar.xz "$BINARY_URL-comp.tar.xz" "$COMP_SHA" \ tar xJf comp.tar.xz -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib cd usr/src From 66c49c73ee16c02e7b01c4c22070b92410318a5f Mon Sep 17 00:00:00 2001 From: Moritz Hedtke Date: Fri, 14 Mar 2025 18:50:41 +0100 Subject: [PATCH 24/26] Make `Parser::parse_expr_cond` public. This allows usage in rustfmt and rustfmt forks. --- compiler/rustc_parse/src/parser/expr.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9b2d562a69e..0774324eae7 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2588,7 +2588,8 @@ impl<'a> Parser<'a> { } /// Parses the condition of a `if` or `while` expression. - fn parse_expr_cond(&mut self) -> PResult<'a, P> { + // Public because it is used in rustfmt forks such as https://github.com/tucant/rustfmt/blob/30c83df9e1db10007bdd16dafce8a86b404329b2/src/parse/macros/html.rs#L57 for custom if expressions. + pub fn parse_expr_cond(&mut self) -> PResult<'a, P> { let attrs = self.parse_outer_attributes()?; let (mut cond, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?; From 5da1ba41b3ba8573b8b16a7207b7b29f895f3dfa Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 14 Mar 2025 20:19:38 +0000 Subject: [PATCH 25/26] Fix typo in hir lowering lint diag --- compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs | 4 +++- .../ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr | 2 +- .../ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr | 4 ++-- tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr | 4 ++-- tests/ui/rust-2021/ice-return-unsized-can-impl.stderr | 2 +- tests/ui/rust-2021/ice-unsized-fn-params-2.stderr | 2 +- tests/ui/rust-2021/ice-unsized-fn-params.stderr | 4 ++-- ...compatible-trait-should-use-self-2021-without-dyn.stderr | 6 +++--- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index e78801dd601..6ed29e04948 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -411,7 +411,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Applicability::MachineApplicable, ); if !is_dyn_compatible { - diag.note(format!("`{trait_name}` it is dyn-incompatible, so it can't be `dyn`")); + diag.note(format!( + "`{trait_name}` is dyn-incompatible, otherwise a trait object could be used" + )); } else { // No ampersand in suggestion if it's borrowed already let (dyn_str, paren_dyn_str) = diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr index 87207d607e2..4c4cb45293f 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn id(f: Copy) -> usize { | ^^^^ | - = note: `Copy` it is dyn-incompatible, so it can't be `dyn` + = note: `Copy` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `Copy` | LL - fn id(f: Copy) -> usize { diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr index 6075e313f4e..d3208d07e91 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | trait A { fn g(b: B) -> B; } | ^ | - = note: `B` it is dyn-incompatible, so it can't be `dyn` + = note: `B` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `B` | LL - trait A { fn g(b: B) -> B; } @@ -32,7 +32,7 @@ error[E0782]: expected a type, found a trait LL | trait B { fn f(a: A) -> A; } | ^ | - = note: `A` it is dyn-incompatible, so it can't be `dyn` + = note: `A` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `A` | LL - trait B { fn f(a: A) -> A; } diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr index f2942820e28..75718c94b19 100644 --- a/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn concrete(b: B) -> B; | ^ | - = note: `B` it is dyn-incompatible, so it can't be `dyn` + = note: `B` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `B` | LL - fn concrete(b: B) -> B; @@ -32,7 +32,7 @@ error[E0782]: expected a type, found a trait LL | fn f(a: A) -> A; | ^ | - = note: `A` it is dyn-incompatible, so it can't be `dyn` + = note: `A` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `A` | LL - fn f(a: A) -> A; diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr b/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr index cfee506e29b..284232cf4f4 100644 --- a/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn g(new: B) -> B; | ^ | - = note: `B` it is dyn-incompatible, so it can't be `dyn` + = note: `B` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `B` | LL - fn g(new: B) -> B; diff --git a/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr b/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr index 7f837bbe50f..630bbc2b905 100644 --- a/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr +++ b/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn guard(_s: Copy) -> bool { | ^^^^ | - = note: `Copy` it is dyn-incompatible, so it can't be `dyn` + = note: `Copy` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `Copy` | LL - fn guard(_s: Copy) -> bool { diff --git a/tests/ui/rust-2021/ice-unsized-fn-params.stderr b/tests/ui/rust-2021/ice-unsized-fn-params.stderr index 4d900711ed6..57708031d6b 100644 --- a/tests/ui/rust-2021/ice-unsized-fn-params.stderr +++ b/tests/ui/rust-2021/ice-unsized-fn-params.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn g(b: B) -> B; | ^ | - = note: `B` it is dyn-incompatible, so it can't be `dyn` + = note: `B` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `B` | LL - fn g(b: B) -> B; @@ -32,7 +32,7 @@ error[E0782]: expected a type, found a trait LL | fn f(a: A) -> A; | ^ | - = note: `A` it is dyn-incompatible, so it can't be `dyn` + = note: `A` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `A` | LL - fn f(a: A) -> A; diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr index 20aa227d10f..7b0fd979991 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn f(a: A) -> A; | ^ | - = note: `A` it is dyn-incompatible, so it can't be `dyn` + = note: `A` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `A` | LL - fn f(a: A) -> A; @@ -32,7 +32,7 @@ error[E0782]: expected a type, found a trait LL | fn f(b: B) -> B; | ^ | - = note: `B` it is dyn-incompatible, so it can't be `dyn` + = note: `B` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `B` | LL - fn f(b: B) -> B; @@ -60,7 +60,7 @@ error[E0782]: expected a type, found a trait LL | fn f(&self, c: C) -> C; | ^ | - = note: `C` it is dyn-incompatible, so it can't be `dyn` + = note: `C` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `C` | LL - fn f(&self, c: C) -> C; From e6f7ab50c00eb754dff01fac27023a291c2ef0f4 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 14 Mar 2025 20:51:28 +0000 Subject: [PATCH 26/26] Small grammar fix in comment --- compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 6ed29e04948..be726c042da 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -420,7 +420,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") }; let sugg = if let hir::TyKind::TraitObject([_, _, ..], _) = self_ty.kind { - // There are more than one trait bound, we need surrounding parentheses. + // There is more than one trait bound, we need surrounding parentheses. vec![ (self_ty.span.shrink_to_lo(), paren_dyn_str.to_string()), (self_ty.span.shrink_to_hi(), ")".to_string()),