From 50c659fcba19f6d51d465815cadcea00d8abb02b Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Fri, 14 Mar 2025 17:30:47 +0100 Subject: [PATCH 01/21] Clarify "owned data" in E0515.md This clarifies the explanation of why this is not allowed and also what to do instead. Fixes 62071 PS There was suggestion of adding a link to the book. I did not yet do that, but if desired that could be added. --- compiler/rustc_error_codes/src/error_codes/E0515.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0515.md b/compiler/rustc_error_codes/src/error_codes/E0515.md index 0f4fbf672239c..87bbe4aea705f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0515.md +++ b/compiler/rustc_error_codes/src/error_codes/E0515.md @@ -17,10 +17,13 @@ fn get_dangling_iterator<'a>() -> Iter<'a, i32> { } ``` -Local variables, function parameters and temporaries are all dropped before the -end of the function body. So a reference to them cannot be returned. +Local variables, function parameters and temporaries are all dropped before +the end of the function body. A returned reference (or struct containing a +reference) to such a dropped value would immediately be invalid. Therefore +it is not allowed to return such a reference. -Consider returning an owned value instead: +Consider returning a value that takes ownership of local data instead of +referencing it: ``` use std::vec::IntoIter; From 899eed15adfbcda55e0eb300c037fe8d444f188d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 22:18:04 +0100 Subject: [PATCH 02/21] Refactor metrics generation step --- .github/workflows/ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96c0955e871b8..47ee02ab00ed5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -241,13 +241,17 @@ jobs: - name: postprocess metrics into the summary run: | if [ -f build/metrics.json ]; then - ./build/citool/debug/citool postprocess-metrics build/metrics.json ${GITHUB_STEP_SUMMARY} + METRICS=build/metrics.json elif [ -f obj/build/metrics.json ]; then - ./build/citool/debug/citool postprocess-metrics obj/build/metrics.json ${GITHUB_STEP_SUMMARY} + METRICS=obj/build/metrics.json else echo "No metrics.json found" + exit 0 fi + ./build/citool/debug/citool postprocess-metrics \ + ${METRICS} ${GITHUB_STEP_SUMMARY} + - name: upload job metrics to DataDog if: needs.calculate_matrix.outputs.run_type != 'pr' env: From 301c384262522d0c4b5577ffbd10642ee9bee24f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 22:18:41 +0100 Subject: [PATCH 03/21] Do not fail the build if metrics postprocessing or DataDog upload fails --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47ee02ab00ed5..01008d70b65b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -239,6 +239,9 @@ jobs: if: github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1' - name: postprocess metrics into the summary + # This step is not critical, and if some I/O problem happens, we don't want + # to cancel the build. + continue-on-error: true run: | if [ -f build/metrics.json ]; then METRICS=build/metrics.json @@ -253,6 +256,9 @@ jobs: ${METRICS} ${GITHUB_STEP_SUMMARY} - name: upload job metrics to DataDog + # This step is not critical, and if some I/O problem happens, we don't want + # to cancel the build. + continue-on-error: true if: needs.calculate_matrix.outputs.run_type != 'pr' env: DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }} From 09d44a48b29fcf4c618ba38e592a1c4f365fc4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 22:21:41 +0100 Subject: [PATCH 04/21] Print metrics postprocessing to stdout This allows the code to be simplified a little bit. --- .github/workflows/ci.yml | 2 +- src/ci/citool/src/main.rs | 7 ++----- src/ci/citool/src/metrics.rs | 33 ++++++++++----------------------- 3 files changed, 13 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01008d70b65b6..ffcdc40de3a70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -253,7 +253,7 @@ jobs: fi ./build/citool/debug/citool postprocess-metrics \ - ${METRICS} ${GITHUB_STEP_SUMMARY} + ${METRICS} >> ${GITHUB_STEP_SUMMARY} - name: upload job metrics to DataDog # This step is not critical, and if some I/O problem happens, we don't want diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index cd690ebeb0625..53fe75900750d 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -158,9 +158,6 @@ enum Args { PostprocessMetrics { /// Path to the metrics.json file metrics_path: PathBuf, - /// Path to a file where the postprocessed metrics summary will be stored. - /// Usually, this will be GITHUB_STEP_SUMMARY on CI. - summary_path: PathBuf, }, /// Upload CI metrics to Datadog. UploadBuildMetrics { @@ -211,8 +208,8 @@ fn main() -> anyhow::Result<()> { Args::UploadBuildMetrics { cpu_usage_csv } => { upload_ci_metrics(&cpu_usage_csv)?; } - Args::PostprocessMetrics { metrics_path, summary_path } => { - postprocess_metrics(&metrics_path, &summary_path)?; + Args::PostprocessMetrics { metrics_path } => { + postprocess_metrics(&metrics_path)?; } Args::PostMergeReport { current: commit, parent } => { post_merge_report(load_db(default_jobs_file)?, parent, commit)?; diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 83b3d5ceed05a..8da4d4e53e64e 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -1,6 +1,4 @@ use std::collections::BTreeMap; -use std::fs::File; -use std::io::Write; use std::path::Path; use anyhow::Context; @@ -8,57 +6,46 @@ use build_helper::metrics::{ BuildStep, JsonNode, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, }; -pub fn postprocess_metrics(metrics_path: &Path, summary_path: &Path) -> anyhow::Result<()> { +pub fn postprocess_metrics(metrics_path: &Path) -> anyhow::Result<()> { let metrics = load_metrics(metrics_path)?; - let mut file = File::options() - .append(true) - .create(true) - .open(summary_path) - .with_context(|| format!("Cannot open summary file at {summary_path:?}"))?; - if !metrics.invocations.is_empty() { - writeln!(file, "# Bootstrap steps")?; - record_bootstrap_step_durations(&metrics, &mut file)?; - record_test_suites(&metrics, &mut file)?; + println!("# Bootstrap steps"); + record_bootstrap_step_durations(&metrics); + record_test_suites(&metrics); } Ok(()) } -fn record_bootstrap_step_durations(metrics: &JsonRoot, file: &mut File) -> anyhow::Result<()> { +fn record_bootstrap_step_durations(metrics: &JsonRoot) { for invocation in &metrics.invocations { let step = BuildStep::from_invocation(invocation); let table = format_build_steps(&step); eprintln!("Step `{}`\n{table}\n", invocation.cmdline); - writeln!( - file, + println!( r"
{}
{table}
", invocation.cmdline - )?; + ); } eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); - - Ok(()) } -fn record_test_suites(metrics: &JsonRoot, file: &mut File) -> anyhow::Result<()> { +fn record_test_suites(metrics: &JsonRoot) { let suites = get_test_suites(&metrics); if !suites.is_empty() { let aggregated = aggregate_test_suites(&suites); let table = render_table(aggregated); - writeln!(file, "\n# Test results\n")?; - writeln!(file, "{table}")?; + println!("\n# Test results\n"); + println!("{table}"); } else { eprintln!("No test suites found in metrics"); } - - Ok(()) } fn render_table(suites: BTreeMap) -> String { From e757deab233aea31612c593773f242b6b9c6e386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 11:16:09 +0100 Subject: [PATCH 05/21] Refactor metrics and analysis in citool to distinguish them better --- .../src/{merge_report.rs => analysis.rs} | 204 ++++++++++-------- src/ci/citool/src/main.rs | 17 +- src/ci/citool/src/metrics.rs | 190 ++++++---------- src/ci/citool/src/utils.rs | 4 + 4 files changed, 196 insertions(+), 219 deletions(-) rename src/ci/citool/src/{merge_report.rs => analysis.rs} (62%) diff --git a/src/ci/citool/src/merge_report.rs b/src/ci/citool/src/analysis.rs similarity index 62% rename from src/ci/citool/src/merge_report.rs rename to src/ci/citool/src/analysis.rs index 62daa2e68530a..87c5708fa602b 100644 --- a/src/ci/citool/src/merge_report.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,97 +1,135 @@ -use std::collections::{HashMap, HashSet}; -use std::path::PathBuf; +use crate::metrics; +use crate::metrics::{JobMetrics, JobName, get_test_suites}; +use crate::utils::pluralize; +use build_helper::metrics::{ + BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, +}; +use std::collections::{BTreeMap, HashMap, HashSet}; + +pub fn output_bootstrap_stats(metrics: &JsonRoot) { + if !metrics.invocations.is_empty() { + println!("# Bootstrap steps"); + record_bootstrap_step_durations(&metrics); + record_test_suites(&metrics); + } +} -use anyhow::Context; -use build_helper::metrics::{JsonRoot, TestOutcome, TestSuiteMetadata}; +fn record_bootstrap_step_durations(metrics: &JsonRoot) { + for invocation in &metrics.invocations { + let step = BuildStep::from_invocation(invocation); + let table = format_build_steps(&step); + eprintln!("Step `{}`\n{table}\n", invocation.cmdline); + println!( + r"
+{} +
{table}
+
+", + invocation.cmdline + ); + } + eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); +} -use crate::jobs::JobDatabase; -use crate::metrics::get_test_suites; +fn record_test_suites(metrics: &JsonRoot) { + let suites = metrics::get_test_suites(&metrics); -type Sha = String; -type JobName = String; + if !suites.is_empty() { + let aggregated = aggregate_test_suites(&suites); + let table = render_table(aggregated); + println!("\n# Test results\n"); + println!("{table}"); + } else { + eprintln!("No test suites found in metrics"); + } +} -/// 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 aggregated_test_diffs = aggregate_test_diffs(&jobs)?; +fn render_table(suites: BTreeMap) -> String { + use std::fmt::Write; - println!("Comparing {parent} (base) -> {current} (this PR)\n"); - report_test_diffs(aggregated_test_diffs); + let mut table = "| Test suite | Passed ✅ | Ignored 🚫 | Failed ❌ |\n".to_string(); + writeln!(table, "|:------|------:|------:|------:|").unwrap(); - Ok(()) -} + fn compute_pct(value: f64, total: f64) -> f64 { + if total == 0.0 { 0.0 } else { value / total } + } -struct JobMetrics { - parent: Option, - current: JsonRoot, -} + fn write_row( + buffer: &mut String, + name: &str, + record: &TestSuiteRecord, + surround: &str, + ) -> std::fmt::Result { + let TestSuiteRecord { passed, ignored, failed } = record; + let total = (record.passed + record.ignored + record.failed) as f64; + let passed_pct = compute_pct(*passed as f64, total) * 100.0; + let ignored_pct = compute_pct(*ignored as f64, total) * 100.0; + let failed_pct = compute_pct(*failed as f64, total) * 100.0; + + write!(buffer, "| {surround}{name}{surround} |")?; + write!(buffer, " {surround}{passed} ({passed_pct:.0}%){surround} |")?; + write!(buffer, " {surround}{ignored} ({ignored_pct:.0}%){surround} |")?; + writeln!(buffer, " {surround}{failed} ({failed_pct:.0}%){surround} |")?; + + Ok(()) + } -/// Download before/after metrics for all auto jobs in the job database. -fn download_all_metrics( - job_db: &JobDatabase, - parent: &str, - current: &str, -) -> anyhow::Result> { - let mut jobs = HashMap::default(); - - for job in &job_db.auto_jobs { - eprintln!("Downloading metrics of job {}", job.name); - let metrics_parent = match download_job_metrics(&job.name, parent) { - Ok(metrics) => Some(metrics), - Err(error) => { - eprintln!( - r#"Did not find metrics for job `{}` at `{}`: {error:?}. -Maybe it was newly added?"#, - job.name, parent - ); - None - } - }; - let metrics_current = download_job_metrics(&job.name, current)?; - jobs.insert( - job.name.clone(), - JobMetrics { parent: metrics_parent, current: metrics_current }, - ); + let mut total = TestSuiteRecord::default(); + for (name, record) in suites { + write_row(&mut table, &name, &record, "").unwrap(); + total.passed += record.passed; + total.ignored += record.ignored; + total.failed += record.failed; } - Ok(jobs) + write_row(&mut table, "Total", &total, "**").unwrap(); + table } -/// 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); - } +/// Computes a post merge CI analysis report of test differences +/// between the `parent` and `current` commits. +pub fn output_test_diffs(job_metrics: HashMap) { + let aggregated_test_diffs = aggregate_test_diffs(&job_metrics); + report_test_diffs(aggregated_test_diffs); +} - let url = get_metrics_url(job_name, sha); - let mut response = ureq::get(&url).call()?; - if !response.status().is_success() { - return Err(anyhow::anyhow!( - "Cannot fetch metrics from {url}: {}\n{}", - response.status(), - response.body_mut().read_to_string()? - )); - } - let data: JsonRoot = response - .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); +#[derive(Default)] +struct TestSuiteRecord { + passed: u64, + ignored: u64, + failed: u64, +} + +fn test_metadata_name(metadata: &TestSuiteMetadata) -> String { + match metadata { + TestSuiteMetadata::CargoPackage { crates, stage, .. } => { + format!("{} (stage {stage})", crates.join(", ")) + } + TestSuiteMetadata::Compiletest { suite, stage, .. } => { + format!("{suite} (stage {stage})") } } - Ok(data) } -fn get_metrics_url(job_name: &str, sha: &str) -> String { - let suffix = if job_name.ends_with("-alt") { "-alt" } else { "" }; - format!("https://ci-artifacts.rust-lang.org/rustc-builds{suffix}/{sha}/metrics-{job_name}.json") +fn aggregate_test_suites(suites: &[&TestSuite]) -> BTreeMap { + let mut records: BTreeMap = BTreeMap::new(); + for suite in suites { + let name = test_metadata_name(&suite.metadata); + let record = records.entry(name).or_default(); + for test in &suite.tests { + match test.outcome { + TestOutcome::Passed => { + record.passed += 1; + } + TestOutcome::Failed => { + record.failed += 1; + } + TestOutcome::Ignored { .. } => { + record.ignored += 1; + } + } + } + } + records } /// Represents a difference in the outcome of tests between a base and a current commit. @@ -101,9 +139,7 @@ struct AggregatedTestDiffs { diffs: HashMap>, } -fn aggregate_test_diffs( - jobs: &HashMap, -) -> anyhow::Result { +fn aggregate_test_diffs(jobs: &HashMap) -> AggregatedTestDiffs { let mut diffs: HashMap> = HashMap::new(); // Aggregate test suites @@ -117,7 +153,7 @@ fn aggregate_test_diffs( } } - Ok(AggregatedTestDiffs { diffs }) + AggregatedTestDiffs { diffs } } #[derive(Eq, PartialEq, Hash, Debug)] @@ -312,7 +348,3 @@ fn report_test_diffs(diff: AggregatedTestDiffs) { ); } } - -fn pluralize(text: &str, count: usize) -> String { - if count == 1 { text.to_string() } else { format!("{text}s") } -} diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 53fe75900750d..5f1932854b5a0 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -1,7 +1,7 @@ +mod analysis; mod cpu_usage; mod datadog; mod jobs; -mod merge_report; mod metrics; mod utils; @@ -14,12 +14,13 @@ use clap::Parser; use jobs::JobDatabase; use serde_yaml::Value; +use crate::analysis::output_test_diffs; use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; -use crate::merge_report::post_merge_report; -use crate::metrics::postprocess_metrics; +use crate::metrics::{download_auto_job_metrics, load_metrics}; use crate::utils::load_env_var; +use analysis::output_bootstrap_stats; const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/.."); const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker"); @@ -209,10 +210,14 @@ fn main() -> anyhow::Result<()> { upload_ci_metrics(&cpu_usage_csv)?; } Args::PostprocessMetrics { metrics_path } => { - postprocess_metrics(&metrics_path)?; + let metrics = load_metrics(&metrics_path)?; + output_bootstrap_stats(&metrics); } - Args::PostMergeReport { current: commit, parent } => { - post_merge_report(load_db(default_jobs_file)?, parent, commit)?; + Args::PostMergeReport { current, parent } => { + let db = load_db(default_jobs_file)?; + let metrics = download_auto_job_metrics(&db, &parent, ¤t)?; + println!("Comparing {parent} (base) -> {current} (this PR)\n"); + output_test_diffs(metrics); } } diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 8da4d4e53e64e..117a4f372c4c2 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -1,133 +1,11 @@ -use std::collections::BTreeMap; use std::path::Path; +use crate::jobs::JobDatabase; use anyhow::Context; -use build_helper::metrics::{ - BuildStep, JsonNode, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, -}; +use build_helper::metrics::{JsonNode, JsonRoot, TestSuite}; +use std::collections::HashMap; -pub fn postprocess_metrics(metrics_path: &Path) -> anyhow::Result<()> { - let metrics = load_metrics(metrics_path)?; - - if !metrics.invocations.is_empty() { - println!("# Bootstrap steps"); - record_bootstrap_step_durations(&metrics); - record_test_suites(&metrics); - } - - Ok(()) -} - -fn record_bootstrap_step_durations(metrics: &JsonRoot) { - for invocation in &metrics.invocations { - let step = BuildStep::from_invocation(invocation); - let table = format_build_steps(&step); - eprintln!("Step `{}`\n{table}\n", invocation.cmdline); - println!( - r"
-{} -
{table}
-
-", - invocation.cmdline - ); - } - eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); -} - -fn record_test_suites(metrics: &JsonRoot) { - let suites = get_test_suites(&metrics); - - if !suites.is_empty() { - let aggregated = aggregate_test_suites(&suites); - let table = render_table(aggregated); - println!("\n# Test results\n"); - println!("{table}"); - } else { - eprintln!("No test suites found in metrics"); - } -} - -fn render_table(suites: BTreeMap) -> String { - use std::fmt::Write; - - let mut table = "| Test suite | Passed ✅ | Ignored 🚫 | Failed ❌ |\n".to_string(); - writeln!(table, "|:------|------:|------:|------:|").unwrap(); - - fn compute_pct(value: f64, total: f64) -> f64 { - if total == 0.0 { 0.0 } else { value / total } - } - - fn write_row( - buffer: &mut String, - name: &str, - record: &TestSuiteRecord, - surround: &str, - ) -> std::fmt::Result { - let TestSuiteRecord { passed, ignored, failed } = record; - let total = (record.passed + record.ignored + record.failed) as f64; - let passed_pct = compute_pct(*passed as f64, total) * 100.0; - let ignored_pct = compute_pct(*ignored as f64, total) * 100.0; - let failed_pct = compute_pct(*failed as f64, total) * 100.0; - - write!(buffer, "| {surround}{name}{surround} |")?; - write!(buffer, " {surround}{passed} ({passed_pct:.0}%){surround} |")?; - write!(buffer, " {surround}{ignored} ({ignored_pct:.0}%){surround} |")?; - writeln!(buffer, " {surround}{failed} ({failed_pct:.0}%){surround} |")?; - - Ok(()) - } - - let mut total = TestSuiteRecord::default(); - for (name, record) in suites { - write_row(&mut table, &name, &record, "").unwrap(); - total.passed += record.passed; - total.ignored += record.ignored; - total.failed += record.failed; - } - write_row(&mut table, "Total", &total, "**").unwrap(); - table -} - -#[derive(Default)] -struct TestSuiteRecord { - passed: u64, - ignored: u64, - failed: u64, -} - -fn test_metadata_name(metadata: &TestSuiteMetadata) -> String { - match metadata { - TestSuiteMetadata::CargoPackage { crates, stage, .. } => { - format!("{} (stage {stage})", crates.join(", ")) - } - TestSuiteMetadata::Compiletest { suite, stage, .. } => { - format!("{suite} (stage {stage})") - } - } -} - -fn aggregate_test_suites(suites: &[&TestSuite]) -> BTreeMap { - let mut records: BTreeMap = BTreeMap::new(); - for suite in suites { - let name = test_metadata_name(&suite.metadata); - let record = records.entry(name).or_default(); - for test in &suite.tests { - match test.outcome { - TestOutcome::Passed => { - record.passed += 1; - } - TestOutcome::Failed => { - record.failed += 1; - } - TestOutcome::Ignored { .. } => { - record.ignored += 1; - } - } - } - } - records -} +pub type JobName = String; pub fn get_test_suites(metrics: &JsonRoot) -> Vec<&TestSuite> { fn visit_test_suites<'a>(nodes: &'a [JsonNode], suites: &mut Vec<&'a TestSuite>) { @@ -150,10 +28,68 @@ pub fn get_test_suites(metrics: &JsonRoot) -> Vec<&TestSuite> { suites } -fn load_metrics(path: &Path) -> anyhow::Result { +pub fn load_metrics(path: &Path) -> anyhow::Result { let metrics = std::fs::read_to_string(path) .with_context(|| format!("Cannot read JSON metrics from {path:?}"))?; let metrics: JsonRoot = serde_json::from_str(&metrics) .with_context(|| format!("Cannot deserialize JSON metrics from {path:?}"))?; Ok(metrics) } + +pub struct JobMetrics { + pub parent: Option, + pub current: JsonRoot, +} + +/// Download before/after metrics for all auto jobs in the job database. +/// `parent` and `current` should be commit SHAs. +pub fn download_auto_job_metrics( + job_db: &JobDatabase, + parent: &str, + current: &str, +) -> anyhow::Result> { + let mut jobs = HashMap::default(); + + for job in &job_db.auto_jobs { + eprintln!("Downloading metrics of job {}", job.name); + let metrics_parent = match download_job_metrics(&job.name, parent) { + Ok(metrics) => Some(metrics), + Err(error) => { + eprintln!( + r#"Did not find metrics for job `{}` at `{}`: {error:?}. +Maybe it was newly added?"#, + job.name, parent + ); + None + } + }; + let metrics_current = download_job_metrics(&job.name, current)?; + jobs.insert( + job.name.clone(), + JobMetrics { parent: metrics_parent, current: metrics_current }, + ); + } + Ok(jobs) +} + +pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result { + let url = get_metrics_url(job_name, sha); + let mut response = ureq::get(&url).call()?; + if !response.status().is_success() { + return Err(anyhow::anyhow!( + "Cannot fetch metrics from {url}: {}\n{}", + response.status(), + response.body_mut().read_to_string()? + )); + } + let data: JsonRoot = response + .body_mut() + .read_json() + .with_context(|| anyhow::anyhow!("cannot deserialize metrics from {url}"))?; + Ok(data) +} + +fn get_metrics_url(job_name: &str, sha: &str) -> String { + let suffix = if job_name.ends_with("-alt") { "-alt" } else { "" }; + format!("https://ci-artifacts.rust-lang.org/rustc-builds{suffix}/{sha}/metrics-{job_name}.json") +} diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs index 9cc220987bdfd..a18af96bf3de6 100644 --- a/src/ci/citool/src/utils.rs +++ b/src/ci/citool/src/utils.rs @@ -9,3 +9,7 @@ pub fn load_env_var(name: &str) -> anyhow::Result { pub fn read_to_string>(path: P) -> anyhow::Result { std::fs::read_to_string(&path).with_context(|| format!("Cannot read file {:?}", path.as_ref())) } + +pub fn pluralize(text: &str, count: usize) -> String { + if count == 1 { text.to_string() } else { format!("{text}s") } +} From 413fd52ea98a1cd986afa3201a259304a3b58599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 09:32:57 +0100 Subject: [PATCH 06/21] Print number of found test diffs --- src/ci/citool/src/analysis.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 87c5708fa602b..8e4ab03f3b3a9 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -244,6 +244,7 @@ fn report_test_diffs(diff: AggregatedTestDiffs) { println!("No test diffs found"); return; } + println!("\n{} test {} found\n", diff.diffs.len(), pluralize("difference", diff.diffs.len())); fn format_outcome(outcome: &TestOutcome) -> String { match outcome { From 6c24c9c088a0eb858976781090a5b1fbb57981bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 09:34:35 +0100 Subject: [PATCH 07/21] Use first-level heading for test differences header --- src/ci/citool/src/analysis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 8e4ab03f3b3a9..02199636fc798 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -239,7 +239,7 @@ fn normalize_test_name(name: &str) -> String { /// Prints test changes in Markdown format to stdout. fn report_test_diffs(diff: AggregatedTestDiffs) { - println!("## Test differences"); + println!("# Test differences"); if diff.diffs.is_empty() { println!("No test diffs found"); return; From 30d57576b9040a438adc2414540da3778addf34b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 09:35:29 +0100 Subject: [PATCH 08/21] Print test diffs into GitHub summary So that we can also observe them for try builds, before merging a PR. --- .github/workflows/ci.yml | 5 +++++ src/ci/citool/src/main.rs | 41 +++++++++++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ffcdc40de3a70..aaae67c28bc70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -252,7 +252,12 @@ jobs: exit 0 fi + # Get closest bors merge commit + PARENT_COMMIT=`git rev-list --author='bors ' -n1 --first-parent HEAD^1` + ./build/citool/debug/citool postprocess-metrics \ + --job-name ${CI_JOB_NAME} \ + --parent ${PARENT_COMMIT} \ ${METRICS} >> ${GITHUB_STEP_SUMMARY} - name: upload job metrics to DataDog diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 5f1932854b5a0..fb0639367bd0e 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -5,7 +5,7 @@ mod jobs; mod metrics; mod utils; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use std::path::{Path, PathBuf}; use std::process::Command; @@ -18,7 +18,7 @@ use crate::analysis::output_test_diffs; use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; -use crate::metrics::{download_auto_job_metrics, load_metrics}; +use crate::metrics::{JobMetrics, download_auto_job_metrics, download_job_metrics, load_metrics}; use crate::utils::load_env_var; use analysis::output_bootstrap_stats; @@ -138,6 +138,27 @@ fn upload_ci_metrics(cpu_usage_csv: &Path) -> anyhow::Result<()> { Ok(()) } +fn postprocess_metrics( + metrics_path: PathBuf, + parent: Option, + job_name: Option, +) -> anyhow::Result<()> { + let metrics = load_metrics(&metrics_path)?; + output_bootstrap_stats(&metrics); + + let (Some(parent), Some(job_name)) = (parent, job_name) else { + return Ok(()); + }; + + let parent_metrics = + download_job_metrics(&job_name, &parent).context("cannot download parent metrics")?; + let job_metrics = + HashMap::from([(job_name, JobMetrics { parent: Some(parent_metrics), current: metrics })]); + output_test_diffs(job_metrics); + + Ok(()) +} + #[derive(clap::Parser)] enum Args { /// Calculate a list of jobs that should be executed on CI. @@ -155,10 +176,19 @@ enum Args { #[clap(long = "type", default_value = "auto")] job_type: JobType, }, - /// Postprocess the metrics.json file generated by bootstrap. + /// Postprocess the metrics.json file generated by bootstrap and output + /// various statistics. + /// If `--parent` and `--job-name` are provided, also display a diff + /// against previous metrics that are downloaded from CI. PostprocessMetrics { /// Path to the metrics.json file metrics_path: PathBuf, + /// A parent SHA against which to compare. + #[clap(long, requires("job_name"))] + parent: Option, + /// The name of the current job. + #[clap(long, requires("parent"))] + job_name: Option, }, /// Upload CI metrics to Datadog. UploadBuildMetrics { @@ -209,9 +239,8 @@ fn main() -> anyhow::Result<()> { Args::UploadBuildMetrics { cpu_usage_csv } => { upload_ci_metrics(&cpu_usage_csv)?; } - Args::PostprocessMetrics { metrics_path } => { - let metrics = load_metrics(&metrics_path)?; - output_bootstrap_stats(&metrics); + Args::PostprocessMetrics { metrics_path, parent, job_name } => { + postprocess_metrics(metrics_path, parent, job_name)?; } Args::PostMergeReport { current, parent } => { let db = load_db(default_jobs_file)?; From 634a11ef4864eb3cdaefa34d320f4be4f679b542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 09:37:19 +0100 Subject: [PATCH 09/21] Add bootstrap stage to test names --- src/ci/citool/src/analysis.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 02199636fc798..566b8e603fbb6 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -225,16 +225,23 @@ fn aggregate_tests(metrics: &JsonRoot) -> TestSuiteData { // 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 }; + let test_entry = Test { name: generate_test_name(&test.name, &suite), is_doctest }; tests.insert(test_entry, test.outcome.clone()); } } TestSuiteData { tests } } -/// Normalizes Windows-style path delimiters to Unix-style paths. -fn normalize_test_name(name: &str) -> String { - name.replace('\\', "/") +/// Normalizes Windows-style path delimiters to Unix-style paths +/// and adds suite metadata to the test name. +fn generate_test_name(name: &str, suite: &TestSuite) -> String { + let name = name.replace('\\', "/"); + let stage = match suite.metadata { + TestSuiteMetadata::CargoPackage { stage, .. } => stage, + TestSuiteMetadata::Compiletest { stage, .. } => stage, + }; + + format!("{name} (stage {stage})") } /// Prints test changes in Markdown format to stdout. From 232be8614d8bc396f3c0917916c96ef0ee939ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 09:41:00 +0100 Subject: [PATCH 10/21] Add a helper function for outputting details --- src/ci/citool/src/analysis.rs | 13 ++++--------- src/ci/citool/src/utils.rs | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 566b8e603fbb6..8a37544357700 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,6 +1,6 @@ use crate::metrics; use crate::metrics::{JobMetrics, JobName, get_test_suites}; -use crate::utils::pluralize; +use crate::utils::{output_details, pluralize}; use build_helper::metrics::{ BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, }; @@ -19,14 +19,9 @@ fn record_bootstrap_step_durations(metrics: &JsonRoot) { let step = BuildStep::from_invocation(invocation); let table = format_build_steps(&step); eprintln!("Step `{}`\n{table}\n", invocation.cmdline); - println!( - r"
-{} -
{table}
-
-", - invocation.cmdline - ); + output_details(&invocation.cmdline, || { + println!("
{table}
"); + }); } eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); } diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs index a18af96bf3de6..bbe24c3633bc0 100644 --- a/src/ci/citool/src/utils.rs +++ b/src/ci/citool/src/utils.rs @@ -13,3 +13,17 @@ pub fn read_to_string>(path: P) -> anyhow::Result { pub fn pluralize(text: &str, count: usize) -> String { if count == 1 { text.to_string() } else { format!("{text}s") } } + +/// Outputs a HTML
section with the provided summary. +/// Output printed by `func` will be contained within the section. +pub fn output_details(summary: &str, func: F) +where + F: FnOnce(), +{ + println!( + r"
+{summary}" + ); + func(); + println!("
\n"); +} From b4cccf01587ac672dee7a92df7e3e21728f5b7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 10:00:11 +0100 Subject: [PATCH 11/21] Put test differences into a `
` section and add better explanation of the post merge report --- src/ci/citool/src/analysis.rs | 63 +++++++++++++++++++---------------- src/ci/citool/src/main.rs | 23 ++++++++++--- src/ci/citool/src/utils.rs | 4 ++- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 8a37544357700..6469bc251be66 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -246,7 +246,6 @@ fn report_test_diffs(diff: AggregatedTestDiffs) { println!("No test diffs found"); return; } - println!("\n{} test {} found\n", diff.diffs.len(), pluralize("difference", diff.diffs.len())); fn format_outcome(outcome: &TestOutcome) -> String { match outcome { @@ -320,34 +319,42 @@ fn report_test_diffs(diff: AggregatedTestDiffs) { // 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!( - "- `{}`: {} ({})", - diff.test.name, - format_diff(&diff.diff), - format_job_group(job_group) - ); - } + output_details( + &format!("Show {} test {}\n", original_diff_count, pluralize("diff", original_diff_count)), + || { + for (diff, job_group) in grouped_diffs { + println!( + "- `{}`: {} ({})", + diff.test.name, + format_diff(&diff.diff), + format_job_group(job_group) + ); + } - 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)); - } + 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) + ); + } - if doctest_count > 0 { - println!( - "\nAdditionally, {doctest_count} doctest {} were found. These are ignored, as they are noisy.", - pluralize("diff", doctest_count) - ); - } + if doctest_count > 0 { + println!( + "\nAdditionally, {doctest_count} doctest {} were found. These are ignored, as they are noisy.", + 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!( - "- {}: {}", - format_job_group(group as u64), - jobs.iter().map(|j| format!("`{j}`")).collect::>().join(", ") - ); - } + // Now print the job group index + println!("\n**Job group index**\n"); + for (group, jobs) in job_index.into_iter().enumerate() { + println!( + "- {}: {}", + format_job_group(group as u64), + jobs.iter().map(|j| format!("`{j}`")).collect::>().join(", ") + ); + } + }, + ); } diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index fb0639367bd0e..01483a2633d0a 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -19,7 +19,7 @@ use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; use crate::metrics::{JobMetrics, download_auto_job_metrics, download_job_metrics, load_metrics}; -use crate::utils::load_env_var; +use crate::utils::{load_env_var, output_details}; use analysis::output_bootstrap_stats; const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/.."); @@ -159,6 +159,22 @@ fn postprocess_metrics( Ok(()) } +fn post_merge_report(db: JobDatabase, current: String, parent: String) -> anyhow::Result<()> { + let metrics = download_auto_job_metrics(&db, &parent, ¤t)?; + + output_details("What is this?", || { + println!( + r#"This is an experimental post-merge analysis report that shows differences in +test outcomes between the merged PR and its parent PR."# + ); + }); + + println!("\nComparing {parent} (parent) -> {current} (this PR)\n"); + output_test_diffs(metrics); + + Ok(()) +} + #[derive(clap::Parser)] enum Args { /// Calculate a list of jobs that should be executed on CI. @@ -243,10 +259,7 @@ fn main() -> anyhow::Result<()> { postprocess_metrics(metrics_path, parent, job_name)?; } Args::PostMergeReport { current, parent } => { - let db = load_db(default_jobs_file)?; - let metrics = download_auto_job_metrics(&db, &parent, ¤t)?; - println!("Comparing {parent} (base) -> {current} (this PR)\n"); - output_test_diffs(metrics); + post_merge_report(load_db(default_jobs_file)?, current, parent)?; } } diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs index bbe24c3633bc0..b9b1bf4d45502 100644 --- a/src/ci/citool/src/utils.rs +++ b/src/ci/citool/src/utils.rs @@ -22,7 +22,9 @@ where { println!( r"
-{summary}" +{summary} + +" ); func(); println!("
\n"); From e84531811160308fbdd0a8ec3e9b697bb17ccd02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 11:11:56 +0100 Subject: [PATCH 12/21] Do not error out on missing parent metrics --- src/ci/citool/src/main.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 01483a2633d0a..29f94e2be5dbd 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -150,11 +150,24 @@ fn postprocess_metrics( return Ok(()); }; - let parent_metrics = - download_job_metrics(&job_name, &parent).context("cannot download parent metrics")?; - let job_metrics = - HashMap::from([(job_name, JobMetrics { parent: Some(parent_metrics), current: metrics })]); - output_test_diffs(job_metrics); + // This command is executed also on PR builds, which might not have parent metrics + // available, because some PR jobs don't run on auto builds, and PR jobs do not upload metrics + // due to missing permissions. + // To avoid having to detect if this is a PR job, and to avoid having failed steps in PR jobs, + // we simply print an error if the parent metrics were not found, but otherwise exit + // successfully. + match download_job_metrics(&job_name, &parent).context("cannot download parent metrics") { + Ok(parent_metrics) => { + let job_metrics = HashMap::from([( + job_name, + JobMetrics { parent: Some(parent_metrics), current: metrics }, + )]); + output_test_diffs(job_metrics); + } + Err(error) => { + eprintln!("Metrics for job `{job_name}` and commit `{parent}` not found: {error:?}"); + } + } Ok(()) } From 4801dba9af6e6c1b3bb06959893f68ed031f6325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 11:34:55 +0100 Subject: [PATCH 13/21] Reformat code --- src/ci/citool/src/analysis.rs | 10 ++++++---- src/ci/citool/src/main.rs | 2 +- src/ci/citool/src/metrics.rs | 5 +++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 6469bc251be66..2088ce2962097 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,10 +1,12 @@ -use crate::metrics; -use crate::metrics::{JobMetrics, JobName, get_test_suites}; -use crate::utils::{output_details, pluralize}; +use std::collections::{BTreeMap, HashMap, HashSet}; + use build_helper::metrics::{ BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, }; -use std::collections::{BTreeMap, HashMap, HashSet}; + +use crate::metrics; +use crate::metrics::{JobMetrics, JobName, get_test_suites}; +use crate::utils::{output_details, pluralize}; pub fn output_bootstrap_stats(metrics: &JsonRoot) { if !metrics.invocations.is_empty() { diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 29f94e2be5dbd..9e4b558d77aa0 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -9,6 +9,7 @@ use std::collections::{BTreeMap, HashMap}; use std::path::{Path, PathBuf}; use std::process::Command; +use analysis::output_bootstrap_stats; use anyhow::Context; use clap::Parser; use jobs::JobDatabase; @@ -20,7 +21,6 @@ use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; use crate::metrics::{JobMetrics, download_auto_job_metrics, download_job_metrics, load_metrics}; use crate::utils::{load_env_var, output_details}; -use analysis::output_bootstrap_stats; const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/.."); const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker"); diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 117a4f372c4c2..263011a337089 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -1,9 +1,10 @@ +use std::collections::HashMap; use std::path::Path; -use crate::jobs::JobDatabase; use anyhow::Context; use build_helper::metrics::{JsonNode, JsonRoot, TestSuite}; -use std::collections::HashMap; + +use crate::jobs::JobDatabase; pub type JobName = String; From 7c792e29d71f83407318e730015caa0003bbb9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 13:10:49 +0100 Subject: [PATCH 14/21] Only use `DIST_TRY_BUILD` for try jobs that were not selected explicitly --- src/ci/citool/src/jobs.rs | 14 ++++++++++++++ src/ci/citool/tests/jobs.rs | 10 +++++----- src/ci/citool/tests/test-jobs.yml | 7 ------- src/ci/github-actions/jobs.yml | 12 +++++------- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs index 0de8b740227d7..13880ad466a6b 100644 --- a/src/ci/citool/src/jobs.rs +++ b/src/ci/citool/src/jobs.rs @@ -185,6 +185,20 @@ fn calculate_jobs( env.extend(crate::yaml_map_to_json(&job.env)); let full_name = format!("{prefix} - {}", job.name); + // When the default `@bors try` job is executed (which is usually done + // for benchmarking performance, running crater or for downloading the + // built toolchain using `rustup-toolchain-install-master`), + // we inject the `DIST_TRY_BUILD` environment variable to the jobs + // to tell `opt-dist` to make the build faster by skipping certain steps. + if let RunType::TryJob { job_patterns } = run_type { + if job_patterns.is_none() { + env.insert( + "DIST_TRY_BUILD".to_string(), + serde_json::value::Value::Number(1.into()), + ); + } + } + GithubActionsJob { name: job.name, full_name, diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs index 788f5e7e4f661..c644f885be30c 100644 --- a/src/ci/citool/tests/jobs.rs +++ b/src/ci/citool/tests/jobs.rs @@ -14,10 +14,10 @@ fn auto_jobs() { #[test] fn try_jobs() { let stdout = get_matrix("push", "commit", "refs/heads/try"); - insta::assert_snapshot!(stdout, @r#" + insta::assert_snapshot!(stdout, @r###" jobs=[{"name":"dist-x86_64-linux","full_name":"try - dist-x86_64-linux","os":"ubuntu-22.04-16core-64gb","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1}}] run_type=try - "#); + "###); } #[test] @@ -30,10 +30,10 @@ try-job: aarch64-gnu try-job: dist-i686-msvc"#, "refs/heads/try", ); - insta::assert_snapshot!(stdout, @r#" - jobs=[{"name":"aarch64-gnu","full_name":"try - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"DIST_TRY_BUILD":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}] + insta::assert_snapshot!(stdout, @r###" + jobs=[{"name":"aarch64-gnu","full_name":"try - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}] run_type=try - "#); + "###); } #[test] diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml index ff4d1772f59b9..3593b3f7df633 100644 --- a/src/ci/citool/tests/test-jobs.yml +++ b/src/ci/citool/tests/test-jobs.yml @@ -53,13 +53,6 @@ envs: try: <<: *production - # The following env var activates faster `try` builds in `opt-dist` by, e.g. - # - building only the more commonly useful components (we rarely need e.g. rust-docs in try - # builds) - # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain - # - # If you *want* these to happen however, temporarily comment it before triggering a try build. - DIST_TRY_BUILD: 1 auto: <<: *production diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index d8c3625af2861..ae029cb777995 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -82,15 +82,13 @@ envs: AWS_REGION: us-west-1 TOOLSTATE_PUBLISH: 1 + # Try builds started through `@bors try` (without specifying custom jobs + # in the PR description) will be passed the `DIST_TRY_BUILD` environment + # variable by citool. + # This tells the `opt-dist` tool to skip building certain components + # and skip running tests, so that the try build finishes faster. try: <<: *production - # The following env var activates faster `try` builds in `opt-dist` by, e.g. - # - building only the more commonly useful components (we rarely need e.g. rust-docs in try - # builds) - # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain - # - # If you *want* these to happen however, temporarily comment it before triggering a try build. - DIST_TRY_BUILD: 1 auto: <<: *production From b2fda93aacd2ad795199140068b9c8a055840b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 16 Mar 2025 20:42:37 +0100 Subject: [PATCH 15/21] Add a note to rustc-dev-guide --- src/doc/rustc-dev-guide/src/tests/ci.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index 0c0f750a45d72..2af09a60513b0 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -180,6 +180,8 @@ their results can be seen [here](https://github.com/rust-lang-ci/rust/actions), although usually you will be notified of the result by a comment made by bors on the corresponding PR. +Note that if you start the default try job using `@bors try`, it will skip building several `dist` components and running post-optimization tests, to make the build duration shorter. If you want to execute the full build as it would happen before a merge, add an explicit `try-job` pattern with the name of the default try job (currently `dist-x86_64-linux`). + Multiple try builds can execute concurrently across different PRs.
From 6698c26b3ab9ef90a31af1afc367bab3a359563c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Mar 2025 13:45:48 +1100 Subject: [PATCH 16/21] Fix `is_relevant_impl`. It determines if a function should have any `inline` attributes checked. For `ItemKind::Fn` it returns true or false depending on the details of the function; for anything other item kind it returns *true*. This latter case should instead be *false*. (In the nearby and similar functions `is_relevant_impl` and `is_relevant_trait` the non-function cases return false.) The effect of this is that non-functions are no longer checked. But rustc already disallows `inline` on any non-function items. So if anything its a tiny performance win, because that was useless anyway. --- src/tools/clippy/clippy_lints/src/attrs/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs index 0e650e4939252..a5ce2137bffeb 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs @@ -24,7 +24,7 @@ pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { if let ItemKind::Fn { body: eid, .. } = item.kind { is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value) } else { - true + false } } From b14810669a805003cf6392447c08eed79441936f Mon Sep 17 00:00:00 2001 From: Charalampos Mitrodimas Date: Sun, 16 Mar 2025 11:28:21 +0100 Subject: [PATCH 17/21] Fix ICE: attempted to remap an already remapped filename This commit fixes an internal compiler error (ICE) that occurs when rustdoc attempts to process macros with a remapped filename. The issue arose during macro expansion when the `--remap-path-prefix` option was used. Instead of passing remapped filenames through, which would trigger the "attempted to remap an already remapped filename" panic, we now extract the original local path from remapped filenames before processing them. A test case has been added to verify this behavior. Fixes #138520 Signed-off-by: Charalampos Mitrodimas --- src/librustdoc/clean/render_macro_matchers.rs | 4 ++-- tests/rustdoc-ui/remap-path-prefix-macro.rs | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 tests/rustdoc-ui/remap-path-prefix-macro.rs diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index 88db853d7c38f..31f9c284d7dd5 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -4,8 +4,8 @@ use rustc_ast_pretty::pprust::PrintState; use rustc_ast_pretty::pprust::state::State as Printer; use rustc_middle::ty::TyCtxt; use rustc_session::parse::ParseSess; -use rustc_span::Span; use rustc_span::symbol::{Ident, Symbol, kw}; +use rustc_span::{FileName, Span}; /// Render a macro matcher in a format suitable for displaying to the user /// as part of an item declaration. @@ -63,7 +63,7 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option parser, diff --git a/tests/rustdoc-ui/remap-path-prefix-macro.rs b/tests/rustdoc-ui/remap-path-prefix-macro.rs new file mode 100644 index 0000000000000..1be22694b8cdc --- /dev/null +++ b/tests/rustdoc-ui/remap-path-prefix-macro.rs @@ -0,0 +1,9 @@ +// Regression test for "attempted to remap an already remapped filename" ICE in rustdoc +// when using --remap-path-prefix with macro rendering. +// + +//@ compile-flags:-Z unstable-options --remap-path-prefix={{src-base}}=remapped_path +//@ rustc-env:RUST_BACKTRACE=0 +//@ build-pass + +macro_rules! f(() => {}); From 0ee99cf240053bc6a73a70922a3c156343555f4b Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Mon, 17 Mar 2025 15:03:33 +0800 Subject: [PATCH 18/21] rustc_target: Add target feature constraints for LoongArch Part of https://github.com/rust-lang/rust/issues/116344 --- compiler/rustc_target/src/target_features.rs | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index a32b42a6fe333..a96caf227f747 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -923,6 +923,28 @@ impl Target { _ => unreachable!(), } } + "loongarch64" => { + // LoongArch handles ABI in a very sane way, being fully explicit via `llvm_abiname` + // about what the intended ABI is. + match &*self.llvm_abiname { + "ilp32d" | "lp64d" => { + // Requires d (which implies f), incompatible with nothing. + FeatureConstraints { required: &["d"], incompatible: &[] } + } + "ilp32f" | "lp64f" => { + // Requires f, incompatible with nothing. + FeatureConstraints { required: &["f"], incompatible: &[] } + } + "ilp32s" | "lp64s" => { + // The soft-float ABI does not require any features and is also not + // incompatible with any features. Rust targets explicitly specify the + // LLVM ABI names, which allows for enabling hard-float support even on + // soft-float targets, and ensures that the ABI behavior is as expected. + NOTHING + } + _ => unreachable!(), + } + } _ => NOTHING, } } From 36f6bc5e3d8a4c68b47462ea243ed3f69525dee7 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Mon, 17 Mar 2025 18:56:52 +0000 Subject: [PATCH 19/21] Flatten `if`s in `rustc_codegen_ssa` --- .../rustc_codegen_ssa/src/back/archive.rs | 9 ++-- compiler/rustc_codegen_ssa/src/back/link.rs | 53 +++++++++---------- compiler/rustc_codegen_ssa/src/back/linker.rs | 26 +++++---- compiler/rustc_codegen_ssa/src/back/write.rs | 32 +++++------ .../src/debuginfo/type_names.rs | 8 ++- compiler/rustc_codegen_ssa/src/mir/block.rs | 38 ++++++------- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 15 +++--- 7 files changed, 82 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 60af462b6b619..34c84c64070d2 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -389,11 +389,10 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { mut skip: Box bool + 'static>, ) -> io::Result<()> { let mut archive_path = archive_path.to_path_buf(); - if self.sess.target.llvm_target.contains("-apple-macosx") { - if let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)? - { - archive_path = new_archive_path - } + if self.sess.target.llvm_target.contains("-apple-macosx") + && let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)? + { + archive_path = new_archive_path } if self.src_archives.iter().any(|archive| archive.0 == archive_path) { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 535f94f6e69cd..a7e9311099d66 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -151,17 +151,17 @@ pub fn link_binary( sess.dcx().emit_artifact_notification(&out_filename, "link"); } - if sess.prof.enabled() { - if let Some(artifact_name) = out_filename.file_name() { - // Record size for self-profiling - let file_size = std::fs::metadata(&out_filename).map(|m| m.len()).unwrap_or(0); - - sess.prof.artifact_size( - "linked_artifact", - artifact_name.to_string_lossy(), - file_size, - ); - } + if sess.prof.enabled() + && let Some(artifact_name) = out_filename.file_name() + { + // Record size for self-profiling + let file_size = std::fs::metadata(&out_filename).map(|m| m.len()).unwrap_or(0); + + sess.prof.artifact_size( + "linked_artifact", + artifact_name.to_string_lossy(), + file_size, + ); } if output.is_stdout() { @@ -186,16 +186,12 @@ pub fn link_binary( let maybe_remove_temps_from_module = |preserve_objects: bool, preserve_dwarf_objects: bool, module: &CompiledModule| { - if !preserve_objects { - if let Some(ref obj) = module.object { - ensure_removed(sess.dcx(), obj); - } + if !preserve_objects && let Some(ref obj) = module.object { + ensure_removed(sess.dcx(), obj); } - if !preserve_dwarf_objects { - if let Some(ref dwo_obj) = module.dwarf_object { - ensure_removed(sess.dcx(), dwo_obj); - } + if !preserve_dwarf_objects && let Some(ref dwo_obj) = module.dwarf_object { + ensure_removed(sess.dcx(), dwo_obj); } }; @@ -2116,11 +2112,11 @@ fn add_local_crate_metadata_objects( // When linking a dynamic library, we put the metadata into a section of the // executable. This metadata is in a separate object file from the main // object file, so we link that in here. - if crate_type == CrateType::Dylib || crate_type == CrateType::ProcMacro { - if let Some(obj) = codegen_results.metadata_module.as_ref().and_then(|m| m.object.as_ref()) - { - cmd.add_object(obj); - } + if matches!(crate_type, CrateType::Dylib | CrateType::ProcMacro) + && let Some(m) = &codegen_results.metadata_module + && let Some(obj) = &m.object + { + cmd.add_object(obj); } } @@ -2540,10 +2536,11 @@ fn add_order_independent_options( cmd.output_filename(out_filename); - if crate_type == CrateType::Executable && sess.target.is_like_windows { - if let Some(ref s) = codegen_results.crate_info.windows_subsystem { - cmd.subsystem(s); - } + if crate_type == CrateType::Executable + && sess.target.is_like_windows + && let Some(s) = &codegen_results.crate_info.windows_subsystem + { + cmd.subsystem(s); } // Try to strip as much out of the generated object by removing unused diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index a8405a2aec98d..e2a59c6efb883 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -111,24 +111,22 @@ pub(crate) fn get_linker<'a>( // PATH for the child. let mut new_path = sess.get_tools_search_paths(self_contained); let mut msvc_changed_path = false; - if sess.target.is_like_msvc { - if let Some(ref tool) = msvc_tool { - cmd.args(tool.args()); - for (k, v) in tool.env() { - if k == "PATH" { - new_path.extend(env::split_paths(v)); - msvc_changed_path = true; - } else { - cmd.env(k, v); - } + if sess.target.is_like_msvc + && let Some(ref tool) = msvc_tool + { + cmd.args(tool.args()); + for (k, v) in tool.env() { + if k == "PATH" { + new_path.extend(env::split_paths(v)); + msvc_changed_path = true; + } else { + cmd.env(k, v); } } } - if !msvc_changed_path { - if let Some(path) = env::var_os("PATH") { - new_path.extend(env::split_paths(&path)); - } + if !msvc_changed_path && let Some(path) = env::var_os("PATH") { + new_path.extend(env::split_paths(&path)); } cmd.env("PATH", env::join_paths(new_path).unwrap()); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 9cc737d194ce7..2ec203458a358 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -566,16 +566,13 @@ fn produce_final_output_artifacts( // Produce final compile outputs. let copy_gracefully = |from: &Path, to: &OutFileName| match to { - OutFileName::Stdout => { - if let Err(e) = copy_to_stdout(from) { - sess.dcx().emit_err(errors::CopyPath::new(from, to.as_path(), e)); - } + OutFileName::Stdout if let Err(e) = copy_to_stdout(from) => { + sess.dcx().emit_err(errors::CopyPath::new(from, to.as_path(), e)); } - OutFileName::Real(path) => { - if let Err(e) = fs::copy(from, path) { - sess.dcx().emit_err(errors::CopyPath::new(from, path, e)); - } + OutFileName::Real(path) if let Err(e) = fs::copy(from, path) => { + sess.dcx().emit_err(errors::CopyPath::new(from, path, e)); } + _ => {} }; let copy_if_one_unit = |output_type: OutputType, keep_numbered: bool| { @@ -685,14 +682,12 @@ fn produce_final_output_artifacts( needs_crate_object || (user_wants_objects && sess.codegen_units().as_usize() > 1); for module in compiled_modules.modules.iter() { - if let Some(ref path) = module.object { - if !keep_numbered_objects { + if !keep_numbered_objects { + if let Some(ref path) = module.object { ensure_removed(sess.dcx(), path); } - } - if let Some(ref path) = module.dwarf_object { - if !keep_numbered_objects { + if let Some(ref path) = module.dwarf_object { ensure_removed(sess.dcx(), path); } } @@ -704,12 +699,11 @@ fn produce_final_output_artifacts( } } - if !user_wants_bitcode { - if let Some(ref allocator_module) = compiled_modules.allocator_module { - if let Some(ref path) = allocator_module.bytecode { - ensure_removed(sess.dcx(), path); - } - } + if !user_wants_bitcode + && let Some(ref allocator_module) = compiled_modules.allocator_module + && let Some(ref path) = allocator_module.bytecode + { + ensure_removed(sess.dcx(), path); } } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 84703a0a15692..18279a4d05fe0 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -555,11 +555,9 @@ pub fn compute_debuginfo_vtable_name<'tcx>( pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: &mut String) { let def_key = tcx.def_key(def_id); - if qualified { - if let Some(parent) = def_key.parent { - push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output); - output.push_str("::"); - } + if qualified && let Some(parent) = def_key.parent { + push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output); + output.push_str("::"); } push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 6d1930a402d37..d184ce3d61dea 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -163,25 +163,25 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { mergeable_succ: bool, ) -> MergingSucc { let tcx = bx.tcx(); - if let Some(instance) = instance { - if is_call_from_compiler_builtins_to_upstream_monomorphization(tcx, instance) { - if destination.is_some() { - let caller_def = fx.instance.def_id(); - let e = CompilerBuiltinsCannotCall { - span: tcx.def_span(caller_def), - caller: with_no_trimmed_paths!(tcx.def_path_str(caller_def)), - callee: with_no_trimmed_paths!(tcx.def_path_str(instance.def_id())), - }; - tcx.dcx().emit_err(e); - } else { - info!( - "compiler_builtins call to diverging function {:?} replaced with abort", - instance.def_id() - ); - bx.abort(); - bx.unreachable(); - return MergingSucc::False; - } + if let Some(instance) = instance + && is_call_from_compiler_builtins_to_upstream_monomorphization(tcx, instance) + { + if destination.is_some() { + let caller_def = fx.instance.def_id(); + let e = CompilerBuiltinsCannotCall { + span: tcx.def_span(caller_def), + caller: with_no_trimmed_paths!(tcx.def_path_str(caller_def)), + callee: with_no_trimmed_paths!(tcx.def_path_str(instance.def_id())), + }; + tcx.dcx().emit_err(e); + } else { + info!( + "compiler_builtins call to diverging function {:?} replaced with abort", + instance.def_id() + ); + bx.abort(); + bx.unreachable(); + return MergingSucc::False; } } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 72cfd2bffb5d0..0fe6a17473592 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -837,15 +837,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn evaluate_array_len(&mut self, bx: &mut Bx, place: mir::Place<'tcx>) -> Bx::Value { // ZST are passed as operands and require special handling // because codegen_place() panics if Local is operand. - if let Some(index) = place.as_local() { - if let LocalRef::Operand(op) = self.locals[index] { - if let ty::Array(_, n) = op.layout.ty.kind() { - let n = n - .try_to_target_usize(bx.tcx()) - .expect("expected monomorphic const in codegen"); - return bx.cx().const_usize(n); - } - } + if let Some(index) = place.as_local() + && let LocalRef::Operand(op) = self.locals[index] + && let ty::Array(_, n) = op.layout.ty.kind() + { + let n = n.try_to_target_usize(bx.tcx()).expect("expected monomorphic const in codegen"); + return bx.cx().const_usize(n); } // use common size calculation for non zero-sized types let cg_value = self.codegen_place(bx, place.as_ref()); From f2ddbcd24b3e71a2c919721f854043f1bb81ff79 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 6 Mar 2025 19:07:36 +1100 Subject: [PATCH 20/21] Move `hir::Item::ident` into `hir::ItemKind`. `hir::Item` has an `ident` field. - It's always non-empty for these item kinds: `ExternCrate`, `Static`, `Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`, Trait`, TraitAalis`. - It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`, `Impl`. - For `Use`, it is non-empty for `UseKind::Single` and empty for `UseKind::{Glob,ListStem}`. All of this is quite non-obvious; the only documentation is a single comment saying "The name might be a dummy name in case of anonymous items". Some sites that handle items check for an empty ident, some don't. This is a very C-like way of doing things, but this is Rust, we have sum types, we can do this properly and never forget to check for the exceptional case and never YOLO possibly empty identifiers (or possibly dummy spans) around and hope that things will work out. The commit is large but it's mostly obvious plumbing work. Some notable things. - A similar transformation makes sense for `ast::Item`, but this is already a big change. That can be done later. - Lots of assertions are added to item lowering to ensure that identifiers are empty/non-empty as expected. These will be removable when `ast::Item` is done later. - `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does. - `lower_use_tree` is significantly simpler. No more confusing `&mut Ident` to deal with. - `ItemKind::ident` is a new method, it returns an `Option`. It's used with `unwrap` in a few places; sometimes it's hard to tell exactly which item kinds might occur. None of these unwraps fail on the test suite. It's conceivable that some might fail on alternative input. We can deal with those if/when they happen. - In `trait_path` the `find_map`/`if let` is replaced with a loop, and things end up much clearer that way. - `named_span` no longer checks for an empty name; instead the call site now checks for a missing identifier if necessary. - `maybe_inline_local` doesn't need the `glob` argument, it can be computed in-function from the `renamed` argument. - `arbitrary_source_item_ordering::check_mod` had a big `if` statement that was just getting the ident from the item kinds that had one. It could be mostly replaced by a single call to the new `ItemKind::ident` method. - `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size, and that's what matters, because `ItemKind` only occurs within `Item`. --- compiler/rustc_ast_lowering/src/index.rs | 2 +- compiler/rustc_ast_lowering/src/item.rs | 114 +++++++++----- .../src/diagnostics/mutability_errors.rs | 8 +- compiler/rustc_hir/src/hir.rs | 148 +++++++++++------- compiler/rustc_hir/src/intravisit.rs | 45 ++++-- .../rustc_hir_analysis/src/check/wfcheck.rs | 24 +-- compiler/rustc_hir_analysis/src/collect.rs | 34 ++-- .../rustc_hir_analysis/src/collect/dump.rs | 2 +- .../src/collect/predicates_of.rs | 7 +- .../src/collect/resolve_bound_vars.rs | 16 +- .../rustc_hir_analysis/src/collect/type_of.rs | 12 +- .../src/hir_ty_lowering/lint.rs | 7 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 6 +- compiler/rustc_hir_pretty/src/lib.rs | 63 ++++---- compiler/rustc_hir_typeck/src/callee.rs | 4 +- compiler/rustc_hir_typeck/src/demand.rs | 5 +- .../src/fn_ctxt/suggestions.rs | 3 +- .../src/method/prelude_edition_lints.rs | 23 +-- .../rustc_hir_typeck/src/method/suggest.rs | 10 +- compiler/rustc_hir_typeck/src/pat.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 18 +-- .../src/default_could_be_derived.rs | 6 +- compiler/rustc_lint/src/internal.rs | 6 +- .../src/multiple_supertrait_upcastable.rs | 4 +- compiler/rustc_lint/src/non_local_def.rs | 6 +- compiler/rustc_lint/src/nonstandard_style.rs | 14 +- compiler/rustc_lint/src/types.rs | 10 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/hir/map.rs | 36 +++-- compiler/rustc_middle/src/ty/print/pretty.rs | 8 +- compiler/rustc_mir_build/src/builder/mod.rs | 2 +- .../src/thir/pattern/check_match.rs | 6 +- compiler/rustc_passes/src/check_attr.rs | 16 +- compiler/rustc_passes/src/dead.rs | 8 +- compiler/rustc_passes/src/reachable.rs | 4 +- compiler/rustc_passes/src/stability.rs | 6 +- compiler/rustc_privacy/src/lib.rs | 23 +-- .../src/error_reporting/infer/mod.rs | 2 +- .../src/error_reporting/traits/ambiguity.rs | 9 +- .../src/error_reporting/traits/mod.rs | 7 +- .../src/error_reporting/traits/suggestions.rs | 50 +++--- compiler/rustc_trait_selection/src/errors.rs | 2 +- src/librustdoc/clean/mod.rs | 35 +++-- src/librustdoc/clean/types.rs | 4 +- src/librustdoc/doctest/rust.rs | 50 ++++-- src/librustdoc/html/render/span_map.rs | 29 ++-- .../passes/calculate_doc_coverage.rs | 2 +- src/librustdoc/visit_ast.rs | 41 +++-- .../src/arbitrary_source_item_ordering.rs | 86 ++++------ .../clippy/clippy_lints/src/attrs/mod.rs | 6 +- .../clippy_lints/src/disallowed_types.rs | 2 +- .../clippy/clippy_lints/src/enum_clike.rs | 2 +- .../clippy_lints/src/error_impl_error.rs | 6 +- src/tools/clippy/clippy_lints/src/escape.rs | 2 +- .../clippy_lints/src/excessive_bools.rs | 2 +- .../clippy_lints/src/exhaustive_items.rs | 2 +- .../clippy_lints/src/functions/result.rs | 2 +- .../clippy_lints/src/item_name_repetitions.rs | 38 +++-- .../src/items_after_test_module.rs | 14 +- .../clippy_lints/src/large_const_arrays.rs | 4 +- .../clippy_lints/src/large_enum_variant.rs | 4 +- .../src/legacy_numeric_constants.rs | 4 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 18 +-- .../clippy_lints/src/manual_non_exhaustive.rs | 4 +- .../clippy/clippy_lints/src/missing_doc.rs | 8 +- .../src/missing_enforced_import_rename.rs | 2 +- .../src/missing_fields_in_debug.rs | 2 +- .../clippy/clippy_lints/src/missing_inline.rs | 2 +- .../src/no_mangle_with_rust_abi.rs | 4 +- .../clippy_lints/src/non_std_lazy_statics.rs | 2 +- .../clippy_lints/src/pub_underscore_fields.rs | 2 +- .../clippy_lints/src/redundant_pub_crate.rs | 6 +- .../src/self_named_constructors.rs | 3 +- .../clippy_lints/src/trailing_empty_array.rs | 2 +- .../clippy/clippy_lints/src/trait_bounds.rs | 4 +- .../clippy/clippy_lints/src/types/mod.rs | 2 +- .../src/undocumented_unsafe_blocks.rs | 4 +- .../src/unnecessary_box_returns.rs | 4 +- .../clippy_lints/src/unused_trait_names.rs | 6 +- .../clippy_lints/src/upper_case_acronyms.rs | 8 +- .../clippy_utils/src/check_proc_macro.rs | 4 +- src/tools/clippy/clippy_utils/src/lib.rs | 21 +-- 82 files changed, 667 insertions(+), 556 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index d1e23bf252229..26c0e7e5f82af 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -164,7 +164,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_item(&mut self, i: &'hir Item<'hir>) { debug_assert_eq!(i.owner_id, self.owner); self.with_parent(i.hir_id(), |this| { - if let ItemKind::Struct(struct_def, _) = &i.kind { + if let ItemKind::Struct(_, struct_def, _) = &i.kind { // If this is a tuple or unit-like struct, register the constructor. if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def)); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9adc8bdd3616d..680015a30e7c1 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -111,6 +111,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } fn lower_foreign_item(&mut self, item: &ForeignItem) { + debug_assert_ne!(item.ident.name, kw::Empty); self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) } } @@ -154,14 +155,12 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { - let mut ident = i.ident; let vis_span = self.lower_span(i.vis.span); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); - let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind); + let kind = self.lower_item_kind(i.span, i.id, hir_id, i.ident, attrs, vis_span, &i.kind); let item = hir::Item { owner_id: hir_id.expect_owner(), - ident: self.lower_ident(ident), kind, vis_span, span: self.lower_span(i.span), @@ -174,25 +173,34 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, id: NodeId, hir_id: hir::HirId, - ident: &mut Ident, + ident: Ident, attrs: &'hir [hir::Attribute], vis_span: Span, i: &ItemKind, ) -> hir::ItemKind<'hir> { match i { - ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(*orig_name), + ItemKind::ExternCrate(orig_name) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); + hir::ItemKind::ExternCrate(*orig_name, ident) + } ItemKind::Use(use_tree) => { + debug_assert_eq!(ident.name, kw::Empty); // Start with an empty prefix. let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None }; - self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs) + self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs) } ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (ty, body_id) = self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy); - hir::ItemKind::Static(ty, *m, body_id) + hir::ItemKind::Static(ident, ty, *m, body_id) } ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, (ty, body_id)) = self.lower_generics( generics, id, @@ -201,7 +209,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy) }, ); - hir::ItemKind::Const(ty, generics, body_id) + hir::ItemKind::Const(ident, ty, generics, body_id) } ItemKind::Fn(box Fn { sig: FnSig { decl, header, span: fn_sig_span }, @@ -211,6 +219,7 @@ impl<'hir> LoweringContext<'_, 'hir> { define_opaque, .. }) => { + debug_assert_ne!(ident.name, kw::Empty); self.with_new_scopes(*fn_sig_span, |this| { // Note: we don't need to change the return type from `T` to // `impl Future` here because lower_body @@ -238,28 +247,44 @@ impl<'hir> LoweringContext<'_, 'hir> { span: this.lower_span(*fn_sig_span), }; this.lower_define_opaque(hir_id, &define_opaque); - hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() } + let ident = this.lower_ident(ident); + hir::ItemKind::Fn { + ident, + sig, + generics, + body: body_id, + has_body: body.is_some(), + } }) } - ItemKind::Mod(_, mod_kind) => match mod_kind { - ModKind::Loaded(items, _, spans, _) => { - hir::ItemKind::Mod(self.lower_mod(items, spans)) + ItemKind::Mod(_, mod_kind) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); + match mod_kind { + ModKind::Loaded(items, _, spans, _) => { + hir::ItemKind::Mod(ident, self.lower_mod(items, spans)) + } + ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), } - ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), - }, - ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod { - abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)), - items: self - .arena - .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), - }, + } + ItemKind::ForeignMod(fm) => { + debug_assert_eq!(ident.name, kw::Empty); + hir::ItemKind::ForeignMod { + abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)), + items: self + .arena + .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), + } + } ItemKind::GlobalAsm(asm) => { + debug_assert_eq!(ident.name, kw::Empty); let asm = self.lower_inline_asm(span, asm); let fake_body = self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm)))); hir::ItemKind::GlobalAsm { asm, fake_body } } ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => { + debug_assert_ne!(ident.name, kw::Empty); // We lower // // type Foo = impl Trait @@ -268,6 +293,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // // type Foo = Foo1 // opaque type Foo1: Trait + let ident = self.lower_ident(ident); let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, true); let (generics, ty) = self.lower_generics( @@ -293,9 +319,11 @@ impl<'hir> LoweringContext<'_, 'hir> { ), }, ); - hir::ItemKind::TyAlias(ty, generics) + hir::ItemKind::TyAlias(ident, ty, generics) } ItemKind::Enum(enum_definition, generics) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, variants) = self.lower_generics( generics, id, @@ -306,25 +334,29 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }, ); - hir::ItemKind::Enum(hir::EnumDef { variants }, generics) + hir::ItemKind::Enum(ident, hir::EnumDef { variants }, generics) } ItemKind::Struct(struct_def, generics) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, struct_def) = self.lower_generics( generics, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), ); - hir::ItemKind::Struct(struct_def, generics) + hir::ItemKind::Struct(ident, struct_def, generics) } ItemKind::Union(vdata, generics) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, vdata) = self.lower_generics( generics, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), ); - hir::ItemKind::Union(vdata, generics) + hir::ItemKind::Union(ident, vdata, generics) } ItemKind::Impl(box Impl { safety, @@ -336,6 +368,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self_ty: ty, items: impl_items, }) => { + debug_assert_eq!(ident.name, kw::Empty); // Lower the "impl header" first. This ordering is important // for in-band lifetimes! Consider `'a` here: // @@ -401,6 +434,8 @@ impl<'hir> LoweringContext<'_, 'hir> { })) } ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, (safety, items, bounds)) = self.lower_generics( generics, id, @@ -417,9 +452,11 @@ impl<'hir> LoweringContext<'_, 'hir> { (safety, items, bounds) }, ); - hir::ItemKind::Trait(*is_auto, safety, generics, bounds, items) + hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items) } ItemKind::TraitAlias(generics, bounds) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, bounds) = self.lower_generics( generics, id, @@ -431,9 +468,11 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }, ); - hir::ItemKind::TraitAlias(generics, bounds) + hir::ItemKind::TraitAlias(ident, generics, bounds) } ItemKind::MacroDef(MacroDef { body, macro_rules }) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let body = P(self.lower_delim_args(body)); let def_id = self.local_def_id(id); let def_kind = self.tcx.def_kind(def_id); @@ -444,11 +483,14 @@ impl<'hir> LoweringContext<'_, 'hir> { ); }; let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules }); - hir::ItemKind::Macro(macro_def, macro_kind) + hir::ItemKind::Macro(ident, macro_def, macro_kind) } ItemKind::Delegation(box delegation) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let delegation_results = self.lower_delegation(delegation, id); hir::ItemKind::Fn { + ident, sig: delegation_results.sig, generics: delegation_results.generics, body: delegation_results.body_id, @@ -479,7 +521,6 @@ impl<'hir> LoweringContext<'_, 'hir> { prefix: &Path, id: NodeId, vis_span: Span, - ident: &mut Ident, attrs: &'hir [hir::Attribute], ) -> hir::ItemKind<'hir> { let path = &tree.prefix; @@ -487,7 +528,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match tree.kind { UseTreeKind::Simple(rename) => { - *ident = tree.ident(); + let mut ident = tree.ident(); // First, apply the prefix to the path. let mut path = Path { segments, span: path.span, tokens: None }; @@ -498,13 +539,14 @@ impl<'hir> LoweringContext<'_, 'hir> { { let _ = path.segments.pop(); if rename.is_none() { - *ident = path.segments.last().unwrap().ident; + ident = path.segments.last().unwrap().ident; } } let res = self.lower_import_res(id, path.span); let path = self.lower_use_path(res, &path, ParamMode::Explicit); - hir::ItemKind::Use(path, hir::UseKind::Single) + let ident = self.lower_ident(ident); + hir::ItemKind::Use(path, hir::UseKind::Single(ident)) } UseTreeKind::Glob => { let res = self.expect_full_res(id); @@ -551,20 +593,16 @@ impl<'hir> LoweringContext<'_, 'hir> { // own its own names, we have to adjust the owner before // lowering the rest of the import. self.with_hir_id_owner(id, |this| { - let mut ident = *ident; - // `prefix` is lowered multiple times, but in different HIR owners. // So each segment gets renewed `HirId` with the same // `ItemLocalId` and the new owner. (See `lower_node_id`) - let kind = - this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs); + let kind = this.lower_use_tree(use_tree, &prefix, id, vis_span, attrs); if !attrs.is_empty() { this.attrs.insert(hir::ItemLocalId::ZERO, attrs); } let item = hir::Item { owner_id: hir::OwnerId { def_id: new_hir_id }, - ident: this.lower_ident(ident), kind, vis_span, span: this.lower_span(use_tree.span), @@ -604,7 +642,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Impl(impl_) => { self.is_in_trait_impl = impl_.of_trait.is_some(); } - hir::ItemKind::Trait(_, _, _, _, _) => {} + hir::ItemKind::Trait(..) => {} kind => { span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr()) } @@ -760,6 +798,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { + debug_assert_ne!(i.ident.name, kw::Empty); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let trait_item_def_id = hir_id.expect_owner(); @@ -907,6 +946,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { + debug_assert_ne!(i.ident.name, kw::Empty); // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 3951b467961a5..b2b8a45af6e69 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -691,7 +691,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { true, td.is_local(), td.as_local().and_then(|tld| match self.infcx.tcx.hir_node_by_def_id(tld) { - Node::Item(hir::Item { kind: hir::ItemKind::Trait(_, _, _, _, items), .. }) => { + Node::Item(hir::Item { + kind: hir::ItemKind::Trait(_, _, _, _, _, items), .. + }) => { let mut f_in_trait_opt = None; for hir::TraitItemRef { id: fi, kind: k, .. } in *items { let hi = fi.hir_id(); @@ -980,7 +982,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let arg = match tcx.hir_get_if_local(callee_def_id) { Some( hir::Node::Item(hir::Item { - ident, kind: hir::ItemKind::Fn { sig, .. }, .. + kind: hir::ItemKind::Fn { ident, sig, .. }, .. }) | hir::Node::TraitItem(hir::TraitItem { ident, @@ -1021,7 +1023,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // return type. match tcx.hir_node_by_def_id(tcx.hir_get_parent_item(fn_call_id).def_id) { hir::Node::Item(hir::Item { - ident, kind: hir::ItemKind::Fn { sig, .. }, .. + kind: hir::ItemKind::Fn { ident, sig, .. }, .. }) | hir::Node::TraitItem(hir::TraitItem { ident, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 5cf231d566828..b5857e359a2ce 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3755,7 +3755,10 @@ pub enum UseKind { /// One import, e.g., `use foo::bar` or `use foo::bar as baz`. /// Also produced for each element of a list `use`, e.g. /// `use foo::{a, b}` lowers to `use foo::a; use foo::b;`. - Single, + /// + /// The identifier is the name defined by the import. E.g. for `use + /// foo::bar` it is `bar`, for `use foo::bar as baz` it is `baz`. + Single(Ident), /// Glob import, e.g., `use foo::*`. Glob, @@ -3897,8 +3900,6 @@ impl ItemId { /// An item /// -/// The name might be a dummy name in case of anonymous items -/// /// For more details, see the [rust lang reference]. /// Note that the reference does not document nightly-only features. /// There may be also slight differences in the names and representation of AST nodes between @@ -3907,7 +3908,6 @@ impl ItemId { /// [rust lang reference]: https://doc.rust-lang.org/reference/items.html #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Item<'hir> { - pub ident: Ident, pub owner_id: OwnerId, pub kind: ItemKind<'hir>, pub span: Span, @@ -3937,46 +3937,56 @@ impl<'hir> Item<'hir> { } expect_methods_self_kind! { - expect_extern_crate, Option, ItemKind::ExternCrate(s), *s; + expect_extern_crate, (Option, Ident), + ItemKind::ExternCrate(s, ident), (*s, *ident); expect_use, (&'hir UsePath<'hir>, UseKind), ItemKind::Use(p, uk), (p, *uk); - expect_static, (&'hir Ty<'hir>, Mutability, BodyId), - ItemKind::Static(ty, mutbl, body), (ty, *mutbl, *body); + expect_static, (Ident, &'hir Ty<'hir>, Mutability, BodyId), + ItemKind::Static(ident, ty, mutbl, body), (*ident, ty, *mutbl, *body); - expect_const, (&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId), - ItemKind::Const(ty, generics, body), (ty, generics, *body); + expect_const, (Ident, &'hir Ty<'hir>, &'hir Generics<'hir>, BodyId), + ItemKind::Const(ident, ty, generics, body), (*ident, ty, generics, *body); - expect_fn, (&FnSig<'hir>, &'hir Generics<'hir>, BodyId), - ItemKind::Fn { sig, generics, body, .. }, (sig, generics, *body); + expect_fn, (Ident, &FnSig<'hir>, &'hir Generics<'hir>, BodyId), + ItemKind::Fn { ident, sig, generics, body, .. }, (*ident, sig, generics, *body); - expect_macro, (&ast::MacroDef, MacroKind), ItemKind::Macro(def, mk), (def, *mk); + expect_macro, (Ident, &ast::MacroDef, MacroKind), + ItemKind::Macro(ident, def, mk), (*ident, def, *mk); - expect_mod, &'hir Mod<'hir>, ItemKind::Mod(m), m; + expect_mod, (Ident, &'hir Mod<'hir>), ItemKind::Mod(ident, m), (*ident, m); expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]), ItemKind::ForeignMod { abi, items }, (*abi, items); expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm, .. }, asm; - expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>), - ItemKind::TyAlias(ty, generics), (ty, generics); + expect_ty_alias, (Ident, &'hir Ty<'hir>, &'hir Generics<'hir>), + ItemKind::TyAlias(ident, ty, generics), (*ident, ty, generics); - expect_enum, (&EnumDef<'hir>, &'hir Generics<'hir>), ItemKind::Enum(def, generics), (def, generics); + expect_enum, (Ident, &EnumDef<'hir>, &'hir Generics<'hir>), + ItemKind::Enum(ident, def, generics), (*ident, def, generics); - expect_struct, (&VariantData<'hir>, &'hir Generics<'hir>), - ItemKind::Struct(data, generics), (data, generics); + expect_struct, (Ident, &VariantData<'hir>, &'hir Generics<'hir>), + ItemKind::Struct(ident, data, generics), (*ident, data, generics); - expect_union, (&VariantData<'hir>, &'hir Generics<'hir>), - ItemKind::Union(data, generics), (data, generics); + expect_union, (Ident, &VariantData<'hir>, &'hir Generics<'hir>), + ItemKind::Union(ident, data, generics), (*ident, data, generics); expect_trait, - (IsAuto, Safety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), - ItemKind::Trait(is_auto, safety, generics, bounds, items), - (*is_auto, *safety, generics, bounds, items); - - expect_trait_alias, (&'hir Generics<'hir>, GenericBounds<'hir>), - ItemKind::TraitAlias(generics, bounds), (generics, bounds); + ( + IsAuto, + Safety, + Ident, + &'hir Generics<'hir>, + GenericBounds<'hir>, + &'hir [TraitItemRef] + ), + ItemKind::Trait(is_auto, safety, ident, generics, bounds, items), + (*is_auto, *safety, *ident, generics, bounds, items); + + expect_trait_alias, (Ident, &'hir Generics<'hir>, GenericBounds<'hir>), + ItemKind::TraitAlias(ident, generics, bounds), (*ident, generics, bounds); expect_impl, &'hir Impl<'hir>, ItemKind::Impl(imp), imp; } @@ -4094,7 +4104,7 @@ pub enum ItemKind<'hir> { /// An `extern crate` item, with optional *original* crate name if the crate was renamed. /// /// E.g., `extern crate foo` or `extern crate foo_bar as foo`. - ExternCrate(Option), + ExternCrate(Option, Ident), /// `use foo::bar::*;` or `use foo::bar::baz as quux;` /// @@ -4104,11 +4114,12 @@ pub enum ItemKind<'hir> { Use(&'hir UsePath<'hir>, UseKind), /// A `static` item. - Static(&'hir Ty<'hir>, Mutability, BodyId), + Static(Ident, &'hir Ty<'hir>, Mutability, BodyId), /// A `const` item. - Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId), + Const(Ident, &'hir Ty<'hir>, &'hir Generics<'hir>, BodyId), /// A function declaration. Fn { + ident: Ident, sig: FnSig<'hir>, generics: &'hir Generics<'hir>, body: BodyId, @@ -4118,9 +4129,9 @@ pub enum ItemKind<'hir> { has_body: bool, }, /// A MBE macro definition (`macro_rules!` or `macro`). - Macro(&'hir ast::MacroDef, MacroKind), + Macro(Ident, &'hir ast::MacroDef, MacroKind), /// A module. - Mod(&'hir Mod<'hir>), + Mod(Ident, &'hir Mod<'hir>), /// An external module, e.g. `extern { .. }`. ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] }, /// Module-level inline assembly (from `global_asm!`). @@ -4134,17 +4145,17 @@ pub enum ItemKind<'hir> { fake_body: BodyId, }, /// A type alias, e.g., `type Foo = Bar`. - TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>), - /// An enum definition, e.g., `enum Foo {C, D}`. - Enum(EnumDef<'hir>, &'hir Generics<'hir>), + TyAlias(Ident, &'hir Ty<'hir>, &'hir Generics<'hir>), + /// An enum definition, e.g., `enum Foo { C, D }`. + Enum(Ident, EnumDef<'hir>, &'hir Generics<'hir>), /// A struct definition, e.g., `struct Foo {x: A}`. - Struct(VariantData<'hir>, &'hir Generics<'hir>), + Struct(Ident, VariantData<'hir>, &'hir Generics<'hir>), /// A union definition, e.g., `union Foo {x: A, y: B}`. - Union(VariantData<'hir>, &'hir Generics<'hir>), + Union(Ident, VariantData<'hir>, &'hir Generics<'hir>), /// A trait definition. - Trait(IsAuto, Safety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), + Trait(IsAuto, Safety, Ident, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), /// A trait alias. - TraitAlias(&'hir Generics<'hir>, GenericBounds<'hir>), + TraitAlias(Ident, &'hir Generics<'hir>, GenericBounds<'hir>), /// An implementation, e.g., `impl Trait for Foo { .. }`. Impl(&'hir Impl<'hir>), @@ -4173,16 +4184,39 @@ pub struct Impl<'hir> { } impl ItemKind<'_> { + pub fn ident(&self) -> Option { + match *self { + ItemKind::ExternCrate(_, ident) + | ItemKind::Use(_, UseKind::Single(ident)) + | ItemKind::Static(ident, ..) + | ItemKind::Const(ident, ..) + | ItemKind::Fn { ident, .. } + | ItemKind::Macro(ident, ..) + | ItemKind::Mod(ident, ..) + | ItemKind::TyAlias(ident, ..) + | ItemKind::Enum(ident, ..) + | ItemKind::Struct(ident, ..) + | ItemKind::Union(ident, ..) + | ItemKind::Trait(_, _, ident, ..) + | ItemKind::TraitAlias(ident, ..) => Some(ident), + + ItemKind::Use(_, UseKind::Glob | UseKind::ListStem) + | ItemKind::ForeignMod { .. } + | ItemKind::GlobalAsm { .. } + | ItemKind::Impl(_) => None, + } + } + pub fn generics(&self) -> Option<&Generics<'_>> { Some(match self { ItemKind::Fn { generics, .. } - | ItemKind::TyAlias(_, generics) - | ItemKind::Const(_, generics, _) - | ItemKind::Enum(_, generics) - | ItemKind::Struct(_, generics) - | ItemKind::Union(_, generics) - | ItemKind::Trait(_, _, generics, _, _) - | ItemKind::TraitAlias(generics, _) + | ItemKind::TyAlias(_, _, generics) + | ItemKind::Const(_, _, generics, _) + | ItemKind::Enum(_, _, generics) + | ItemKind::Struct(_, _, generics) + | ItemKind::Union(_, _, generics) + | ItemKind::Trait(_, _, _, generics, _, _) + | ItemKind::TraitAlias(_, generics, _) | ItemKind::Impl(Impl { generics, .. }) => generics, _ => return None, }) @@ -4374,8 +4408,8 @@ impl<'hir> OwnerNode<'hir> { match self { OwnerNode::Item(Item { kind: - ItemKind::Static(_, _, body) - | ItemKind::Const(_, _, body) + ItemKind::Static(_, _, _, body) + | ItemKind::Const(_, _, _, body) | ItemKind::Fn { body, .. }, .. }) @@ -4518,12 +4552,12 @@ impl<'hir> Node<'hir> { /// ``` pub fn ident(&self) -> Option { match self { + Node::Item(item) => item.kind.ident(), Node::TraitItem(TraitItem { ident, .. }) | Node::ImplItem(ImplItem { ident, .. }) | Node::ForeignItem(ForeignItem { ident, .. }) | Node::Field(FieldDef { ident, .. }) | Node::Variant(Variant { ident, .. }) - | Node::Item(Item { ident, .. }) | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident), Node::Lifetime(lt) => Some(lt.ident), Node::GenericParam(p) => Some(p.name.ident()), @@ -4599,9 +4633,9 @@ impl<'hir> Node<'hir> { pub fn ty(self) -> Option<&'hir Ty<'hir>> { match self { Node::Item(it) => match it.kind { - ItemKind::TyAlias(ty, _) - | ItemKind::Static(ty, _, _) - | ItemKind::Const(ty, _, _) => Some(ty), + ItemKind::TyAlias(_, ty, _) + | ItemKind::Static(_, ty, _, _) + | ItemKind::Const(_, ty, _, _) => Some(ty), ItemKind::Impl(impl_item) => Some(&impl_item.self_ty), _ => None, }, @@ -4621,7 +4655,7 @@ impl<'hir> Node<'hir> { pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> { match self { - Node::Item(Item { kind: ItemKind::TyAlias(ty, ..), .. }) => Some(ty), + Node::Item(Item { kind: ItemKind::TyAlias(_, ty, _), .. }) => Some(ty), _ => None, } } @@ -4632,7 +4666,9 @@ impl<'hir> Node<'hir> { Node::Item(Item { owner_id, kind: - ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn { body, .. }, + ItemKind::Const(_, _, _, body) + | ItemKind::Static(.., body) + | ItemKind::Fn { body, .. }, .. }) | Node::TraitItem(TraitItem { @@ -4693,8 +4729,8 @@ impl<'hir> Node<'hir> { pub fn fn_kind(self) -> Option> { match self { Node::Item(i) => match i.kind { - ItemKind::Fn { sig, generics, .. } => { - Some(FnKind::ItemFn(i.ident, generics, sig.header)) + ItemKind::Fn { ident, sig, generics, .. } => { + Some(FnKind::ItemFn(ident, generics, sig.header)) } _ => None, }, @@ -4767,7 +4803,7 @@ mod size_asserts { static_assert_size!(ImplItem<'_>, 88); static_assert_size!(ImplItemKind<'_>, 40); static_assert_size!(Item<'_>, 88); - static_assert_size!(ItemKind<'_>, 56); + static_assert_size!(ItemKind<'_>, 64); static_assert_size!(LetStmt<'_>, 64); static_assert_size!(Param<'_>, 32); static_assert_size!(Pat<'_>, 72); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 3ef645a5f6172..b79ae1e7cc21e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -533,34 +533,44 @@ pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::Result { try_visit!(visitor.visit_id(item.hir_id())); - try_visit!(visitor.visit_ident(item.ident)); match item.kind { - ItemKind::ExternCrate(orig_name) => { + ItemKind::ExternCrate(orig_name, ident) => { visit_opt!(visitor, visit_name, orig_name); + try_visit!(visitor.visit_ident(ident)); } - ItemKind::Use(ref path, _) => { + ItemKind::Use(ref path, kind) => { try_visit!(visitor.visit_use(path, item.hir_id())); + match kind { + UseKind::Single(ident) => try_visit!(visitor.visit_ident(ident)), + UseKind::Glob | UseKind::ListStem => {} + } } - ItemKind::Static(ref typ, _, body) => { + ItemKind::Static(ident, ref typ, _, body) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ty_unambig(typ)); try_visit!(visitor.visit_nested_body(body)); } - ItemKind::Const(ref typ, ref generics, body) => { + ItemKind::Const(ident, ref typ, ref generics, body) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ty_unambig(typ)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_nested_body(body)); } - ItemKind::Fn { sig, generics, body: body_id, .. } => { + ItemKind::Fn { ident, sig, generics, body: body_id, .. } => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_fn( - FnKind::ItemFn(item.ident, generics, sig.header), + FnKind::ItemFn(ident, generics, sig.header), sig.decl, body_id, item.span, item.owner_id.def_id, )); } - ItemKind::Macro(..) => {} - ItemKind::Mod(ref module) => { + ItemKind::Macro(ident, _def, _kind) => { + try_visit!(visitor.visit_ident(ident)); + } + ItemKind::Mod(ident, ref module) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_mod(module, item.span, item.hir_id())); } ItemKind::ForeignMod { abi: _, items } => { @@ -573,11 +583,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: // typeck results set correctly. try_visit!(visitor.visit_nested_body(fake_body)); } - ItemKind::TyAlias(ref ty, ref generics) => { + ItemKind::TyAlias(ident, ref ty, ref generics) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ty_unambig(ty)); try_visit!(visitor.visit_generics(generics)); } - ItemKind::Enum(ref enum_definition, ref generics) => { + ItemKind::Enum(ident, ref enum_definition, ref generics) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_enum_def(enum_definition)); } @@ -597,17 +609,20 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_ty_unambig(self_ty)); walk_list!(visitor, visit_impl_item_ref, *items); } - ItemKind::Struct(ref struct_definition, ref generics) - | ItemKind::Union(ref struct_definition, ref generics) => { + ItemKind::Struct(ident, ref struct_definition, ref generics) + | ItemKind::Union(ident, ref struct_definition, ref generics) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_variant_data(struct_definition)); } - ItemKind::Trait(.., ref generics, bounds, trait_item_refs) => { + ItemKind::Trait(_is_auto, _safety, ident, ref generics, bounds, trait_item_refs) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_trait_item_ref, trait_item_refs); } - ItemKind::TraitAlias(ref generics, bounds) => { + ItemKind::TraitAlias(ident, ref generics, bounds) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds); } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4769153ff4d0d..952af5923118c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -269,26 +269,26 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() } res } - hir::ItemKind::Fn { sig, .. } => { - check_item_fn(tcx, def_id, item.ident, item.span, sig.decl) + hir::ItemKind::Fn { ident, sig, .. } => { + check_item_fn(tcx, def_id, ident, item.span, sig.decl) } - hir::ItemKind::Static(ty, ..) => { + hir::ItemKind::Static(_, ty, ..) => { check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) } - hir::ItemKind::Const(ty, ..) => { + hir::ItemKind::Const(_, ty, ..) => { check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) } - hir::ItemKind::Struct(_, hir_generics) => { + hir::ItemKind::Struct(_, _, hir_generics) => { let res = check_type_defn(tcx, item, false); check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Union(_, hir_generics) => { + hir::ItemKind::Union(_, _, hir_generics) => { let res = check_type_defn(tcx, item, true); check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Enum(_, hir_generics) => { + hir::ItemKind::Enum(_, _, hir_generics) => { let res = check_type_defn(tcx, item, true); check_variances_for_type_defn(tcx, item, hir_generics); res @@ -297,7 +297,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::TraitAlias(..) => check_trait(tcx, item), // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => Ok(()), - hir::ItemKind::TyAlias(hir_ty, hir_generics) if tcx.type_alias_is_lazy(item.owner_id) => { + hir::ItemKind::TyAlias(_, hir_ty, hir_generics) + if tcx.type_alias_is_lazy(item.owner_id) => + { let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| { let ty = tcx.type_of(def_id).instantiate_identity(); let item_ty = wfcx.normalize(hir_ty.span, Some(WellFormedLoc::Ty(def_id)), ty); @@ -822,10 +824,10 @@ fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { /// /// In such cases, suggest using `Self` instead. fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) { - let (trait_name, trait_def_id) = + let (trait_ident, trait_def_id) = match tcx.hir_node_by_def_id(tcx.hir_get_parent_item(item.hir_id()).def_id) { hir::Node::Item(item) => match item.kind { - hir::ItemKind::Trait(..) => (item.ident, item.owner_id), + hir::ItemKind::Trait(_, _, ident, ..) => (ident, item.owner_id), _ => return, }, _ => return, @@ -862,7 +864,7 @@ fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitI trait_should_be_self, "associated item referring to unboxed trait object for its own trait", ) - .with_span_label(trait_name.span, "in this trait") + .with_span_label(trait_ident.span, "in this trait") .with_multipart_suggestion( "you might have meant to use `Self` to refer to the implementing type", sugg, diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 54a630f5b005a..075abc3259449 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -247,13 +247,13 @@ fn reject_placeholder_type_signatures_in_item<'tcx>( item: &'tcx hir::Item<'tcx>, ) { let (generics, suggest) = match &item.kind { - hir::ItemKind::Union(_, generics) - | hir::ItemKind::Enum(_, generics) - | hir::ItemKind::TraitAlias(generics, _) - | hir::ItemKind::Trait(_, _, generics, ..) + hir::ItemKind::Union(_, _, generics) + | hir::ItemKind::Enum(_, _, generics) + | hir::ItemKind::TraitAlias(_, generics, _) + | hir::ItemKind::Trait(_, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) - | hir::ItemKind::Struct(_, generics) => (generics, true), - hir::ItemKind::TyAlias(_, generics) => (generics, false), + | hir::ItemKind::Struct(_, _, generics) => (generics, true), + hir::ItemKind::TyAlias(_, _, generics) => (generics, false), // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type. _ => return, }; @@ -470,9 +470,9 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { .tcx .hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id); match &item.kind { - hir::ItemKind::Enum(_, generics) - | hir::ItemKind::Struct(_, generics) - | hir::ItemKind::Union(_, generics) => { + hir::ItemKind::Enum(_, _, generics) + | hir::ItemKind::Struct(_, _, generics) + | hir::ItemKind::Union(_, _, generics) => { let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics); let (lt_sp, sugg) = match generics.params { [] => (generics.span, format!("<{lt_name}>")), @@ -667,16 +667,16 @@ fn get_new_lifetime_name<'tcx>( #[instrument(level = "debug", skip_all)] fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { let it = tcx.hir_item(item_id); - debug!(item = %it.ident, id = %it.hir_id()); + debug!(item = ?it.kind.ident(), id = %it.hir_id()); let def_id = item_id.owner_id.def_id; let icx = ItemCtxt::new(tcx, def_id); match &it.kind { // These don't define types. - hir::ItemKind::ExternCrate(_) + hir::ItemKind::ExternCrate(..) | hir::ItemKind::Use(..) | hir::ItemKind::Macro(..) - | hir::ItemKind::Mod(_) + | hir::ItemKind::Mod(..) | hir::ItemKind::GlobalAsm { .. } => {} hir::ItemKind::ForeignMod { items, .. } => { for item in *items { @@ -736,7 +736,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.at(it.span).explicit_super_predicates_of(def_id); tcx.ensure_ok().predicates_of(def_id); } - hir::ItemKind::Struct(struct_def, _) | hir::ItemKind::Union(struct_def, _) => { + hir::ItemKind::Struct(_, struct_def, _) | hir::ItemKind::Union(_, struct_def, _) => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); @@ -758,7 +758,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure_ok().predicates_of(def_id); } - hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..) => { + hir::ItemKind::Static(_, ty, ..) | hir::ItemKind::Const(_, ty, ..) => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); @@ -1089,7 +1089,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { let repr = tcx.repr_options_of_def(def_id); let (kind, variants) = match &item.kind { - ItemKind::Enum(def, _) => { + ItemKind::Enum(_, def, _) => { let mut distance_from_explicit = 0; let variants = def .variants @@ -1117,7 +1117,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { (AdtKind::Enum, variants) } - ItemKind::Struct(def, _) | ItemKind::Union(def, _) => { + ItemKind::Struct(ident, def, _) | ItemKind::Union(ident, def, _) => { let adt_kind = match item.kind { ItemKind::Struct(..) => AdtKind::Struct, _ => AdtKind::Union, @@ -1125,7 +1125,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { let variants = std::iter::once(lower_variant( tcx, None, - item.ident, + *ident, ty::VariantDiscr::Relative(0), def, adt_kind, diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 7cbd31de6bab2..c3f965d845693 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -134,7 +134,7 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) { }; tcx.vtable_entries(trait_ref) } - hir::ItemKind::TyAlias(_, _) => { + hir::ItemKind::TyAlias(..) => { let ty = tcx.type_of(def_id).instantiate_identity(); if ty.has_non_region_param() { tcx.dcx().span_err( diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 2022127a15b05..4bd89861a9e5a 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -163,7 +163,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } } - ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => { + ItemKind::Trait(_, _, _, _, self_bounds, ..) + | ItemKind::TraitAlias(_, _, self_bounds) => { is_trait = Some(self_bounds); } _ => {} @@ -615,7 +616,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let (generics, superbounds) = match item.kind { hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits), + hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), _ => span_bug!(item.span, "super_predicates invoked on non-trait"), }; @@ -959,7 +960,7 @@ pub(super) fn const_conditions<'tcx>( Node::Item(item) => match item.kind { hir::ItemKind::Impl(impl_) => (impl_.generics, None, false), hir::ItemKind::Fn { generics, .. } => (generics, None, false), - hir::ItemKind::Trait(_, _, generics, supertraits, _) => { + hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => { (generics, Some((item.owner_id.def_id, supertraits)), false) } _ => bug!("const_conditions called on wrong item: {def_id:?}"), diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 883a1acdb3094..9b0d57bd75b11 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -617,7 +617,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }); } - hir::ItemKind::ExternCrate(_) + hir::ItemKind::ExternCrate(..) | hir::ItemKind::Use(..) | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) @@ -627,13 +627,13 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // These sorts of items have no lifetime parameters at all. intravisit::walk_item(self, item); } - hir::ItemKind::TyAlias(_, generics) - | hir::ItemKind::Const(_, generics, _) - | hir::ItemKind::Enum(_, generics) - | hir::ItemKind::Struct(_, generics) - | hir::ItemKind::Union(_, generics) - | hir::ItemKind::Trait(_, _, generics, ..) - | hir::ItemKind::TraitAlias(generics, ..) + hir::ItemKind::TyAlias(_, _, generics) + | hir::ItemKind::Const(_, _, generics, _) + | hir::ItemKind::Enum(_, _, generics) + | hir::ItemKind::Struct(_, _, generics) + | hir::ItemKind::Union(_, _, generics) + | hir::ItemKind::Trait(_, _, _, generics, ..) + | hir::ItemKind::TraitAlias(_, generics, ..) | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => { // These kinds of items have only early-bound lifetime parameters. self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item)); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 4e8f5ce398658..afda2c142e228 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -202,35 +202,35 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ }, Node::Item(item) => match item.kind { - ItemKind::Static(ty, .., body_id) => { + ItemKind::Static(ident, ty, .., body_id) => { if ty.is_suggestable_infer_ty() { infer_placeholder_type( icx.lowerer(), def_id, body_id, ty.span, - item.ident, + ident, "static variable", ) } else { icx.lower_ty(ty) } } - ItemKind::Const(ty, _, body_id) => { + ItemKind::Const(ident, ty, _, body_id) => { if ty.is_suggestable_infer_ty() { infer_placeholder_type( icx.lowerer(), def_id, body_id, ty.span, - item.ident, + ident, "constant", ) } else { icx.lower_ty(ty) } } - ItemKind::TyAlias(self_ty, _) => icx.lower_ty(self_ty), + ItemKind::TyAlias(_, self_ty, _) => icx.lower_ty(self_ty), ItemKind::Impl(hir::Impl { self_ty, .. }) => match self_ty.find_self_aliases() { spans if spans.len() > 0 => { let guar = tcx @@ -479,5 +479,5 @@ pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> } } } - HasTait.visit_ty_unambig(tcx.hir_expect_item(def_id).expect_ty_alias().0).is_break() + HasTait.visit_ty_unambig(tcx.hir_expect_item(def_id).expect_ty_alias().1).is_break() } 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 be726c042dadf..5588631228441 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -140,14 +140,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let generics = match tcx.hir_node_by_def_id(parent_item) { hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(variant, generics), .. + kind: hir::ItemKind::Struct(_, variant, generics), + .. }) => { if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) { return false; } generics } - hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(def, generics), .. }) => { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, def, generics), .. }) => { if !def .variants .iter() @@ -267,7 +268,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::Node::Field(field) => { // Enums can't have unsized fields, fields can only have an unsized tail field. if let hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(variant, _), .. + kind: hir::ItemKind::Struct(_, variant, _), .. }) = tcx.parent_hir_node(field.hir_id) && variant .fields() diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 1f5d69bd1b326..e27a81d4976f4 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -136,9 +136,9 @@ fn diagnostic_hir_wf_check<'tcx>( ref item => bug!("Unexpected TraitItem {:?}", item), }, hir::Node::Item(item) => match item.kind { - hir::ItemKind::TyAlias(ty, _) - | hir::ItemKind::Static(ty, _, _) - | hir::ItemKind::Const(ty, _, _) => vec![ty], + hir::ItemKind::TyAlias(_, ty, _) + | hir::ItemKind::Static(_, ty, _, _) + | hir::ItemKind::Const(_, ty, _, _) => vec![ty], hir::ItemKind::Impl(impl_) => match &impl_.of_trait { Some(t) => t .path diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1409310339a08..98b81dd3def34 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -559,7 +559,7 @@ impl<'a> State<'a> { self.print_attrs_as_outer(attrs); self.ann.pre(self, AnnNode::Item(item)); match item.kind { - hir::ItemKind::ExternCrate(orig_name) => { + hir::ItemKind::ExternCrate(orig_name, ident) => { self.head("extern crate"); if let Some(orig_name) = orig_name { self.print_name(orig_name); @@ -567,7 +567,7 @@ impl<'a> State<'a> { self.word("as"); self.space(); } - self.print_ident(item.ident); + self.print_ident(ident); self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block @@ -577,11 +577,11 @@ impl<'a> State<'a> { self.print_path(path, false); match kind { - hir::UseKind::Single => { - if path.segments.last().unwrap().ident != item.ident { + hir::UseKind::Single(ident) => { + if path.segments.last().unwrap().ident != ident { self.space(); self.word_space("as"); - self.print_ident(item.ident); + self.print_ident(ident); } self.word(";"); } @@ -591,12 +591,12 @@ impl<'a> State<'a> { self.end(); // end inner head-block self.end(); // end outer head-block } - hir::ItemKind::Static(ty, m, expr) => { + hir::ItemKind::Static(ident, ty, m, expr) => { self.head("static"); if m.is_mut() { self.word_space("mut"); } - self.print_ident(item.ident); + self.print_ident(ident); self.word_space(":"); self.print_type(ty); self.space(); @@ -607,9 +607,9 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer cbox } - hir::ItemKind::Const(ty, generics, expr) => { + hir::ItemKind::Const(ident, ty, generics, expr) => { self.head("const"); - self.print_ident(item.ident); + self.print_ident(ident); self.print_generic_params(generics.params); self.word_space(":"); self.print_type(ty); @@ -622,30 +622,23 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer cbox } - hir::ItemKind::Fn { sig, generics, body, .. } => { + hir::ItemKind::Fn { ident, sig, generics, body, .. } => { self.head(""); - self.print_fn( - sig.decl, - sig.header, - Some(item.ident.name), - generics, - &[], - Some(body), - ); + self.print_fn(sig.decl, sig.header, Some(ident.name), generics, &[], Some(body)); self.word(" "); self.end(); // need to close a box self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); } - hir::ItemKind::Macro(macro_def, _) => { - self.print_mac_def(macro_def, &item.ident, item.span, |_| {}); + hir::ItemKind::Macro(ident, macro_def, _) => { + self.print_mac_def(macro_def, &ident, item.span, |_| {}); } - hir::ItemKind::Mod(_mod) => { + hir::ItemKind::Mod(ident, mod_) => { self.head("mod"); - self.print_ident(item.ident); + self.print_ident(ident); self.nbsp(); self.bopen(); - self.print_mod(_mod, attrs); + self.print_mod(mod_, attrs); self.bclose(item.span); } hir::ItemKind::ForeignMod { abi, items } => { @@ -663,9 +656,9 @@ impl<'a> State<'a> { self.print_inline_asm(asm); self.end() } - hir::ItemKind::TyAlias(ty, generics) => { + hir::ItemKind::TyAlias(ident, ty, generics) => { self.head("type"); - self.print_ident(item.ident); + self.print_ident(ident); self.print_generic_params(generics.params); self.end(); // end the inner ibox @@ -676,16 +669,16 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer ibox } - hir::ItemKind::Enum(ref enum_definition, params) => { - self.print_enum_def(enum_definition, params, item.ident.name, item.span); + hir::ItemKind::Enum(ident, ref enum_definition, params) => { + self.print_enum_def(enum_definition, params, ident.name, item.span); } - hir::ItemKind::Struct(ref struct_def, generics) => { + hir::ItemKind::Struct(ident, ref struct_def, generics) => { self.head("struct"); - self.print_struct(struct_def, generics, item.ident.name, item.span, true); + self.print_struct(struct_def, generics, ident.name, item.span, true); } - hir::ItemKind::Union(ref struct_def, generics) => { + hir::ItemKind::Union(ident, ref struct_def, generics) => { self.head("union"); - self.print_struct(struct_def, generics, item.ident.name, item.span, true); + self.print_struct(struct_def, generics, ident.name, item.span, true); } hir::ItemKind::Impl(&hir::Impl { constness, @@ -733,12 +726,12 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::Trait(is_auto, safety, generics, bounds, trait_items) => { + hir::ItemKind::Trait(is_auto, safety, ident, generics, bounds, trait_items) => { self.head(""); self.print_is_auto(is_auto); self.print_safety(safety); self.word_nbsp("trait"); - self.print_ident(item.ident); + self.print_ident(ident); self.print_generic_params(generics.params); self.print_bounds(":", bounds); self.print_where_clause(generics); @@ -749,9 +742,9 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::TraitAlias(generics, bounds) => { + hir::ItemKind::TraitAlias(ident, generics, bounds) => { self.head("trait"); - self.print_ident(item.ident); + self.print_ident(ident); self.print_generic_params(generics.params); self.nbsp(); self.print_bounds("=", bounds); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 2a24d626ac357..5e2daa69628f4 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -713,8 +713,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for id in self.tcx.hir_free_items() { if let Some(node) = self.tcx.hir_get_if_local(id.owner_id.into()) && let hir::Node::Item(item) = node - && let hir::ItemKind::Fn { .. } = item.kind - && item.ident.name == segment.ident.name + && let hir::ItemKind::Fn { ident, .. } = item.kind + && ident.name == segment.ident.name { err.span_label( self.tcx.def_span(id.owner_id), diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 3eef32aa7c17c..41bdd0ca43ef1 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -721,8 +721,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, )) => { if let Some(hir::Node::Item(hir::Item { - ident, - kind: hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..), + kind: + hir::ItemKind::Static(ident, ty, ..) + | hir::ItemKind::Const(ident, ty, ..), .. })) = self.tcx.hir_get_if_local(*def_id) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index f19e36206a7f5..73b8685bd3ddc 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -904,7 +904,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Assumes given function doesn't have a explicit return type. fn can_add_return_type(&self, fn_id: LocalDefId) -> bool { match self.tcx.hir_node_by_def_id(fn_id) { - Node::Item(&hir::Item { ident, .. }) => { + Node::Item(item) => { + let (ident, _, _, _) = item.expect_fn(); // This is less than ideal, it will not suggest a return type span on any // method called `main`, regardless of whether it is actually the entry point, // but it will still present it as the reason for the expected type. diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index 72f8793d78399..0037d5ac042bc 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -367,20 +367,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(); // Find an identifier with which this trait was imported (note that `_` doesn't count). - let any_id = import_items.iter().find_map(|item| { - if item.ident.name != kw::Underscore { Some(item.ident) } else { None } - }); - if let Some(any_id) = any_id { - if any_id.name == kw::Empty { - // Glob import, so just use its name. - return None; - } else { - return Some(format!("{any_id}")); + for item in import_items.iter() { + let (_, kind) = item.expect_use(); + match kind { + hir::UseKind::Single(ident) => { + if ident.name != kw::Underscore { + return Some(format!("{}", ident.name)); + } + } + hir::UseKind::Glob => return None, // Glob import, so just use its name. + hir::UseKind::ListStem => unreachable!(), } } - // All that is left is `_`! We need to use the full path. It doesn't matter which one we pick, - // so just take the first one. + // All that is left is `_`! We need to use the full path. It doesn't matter which one we + // pick, so just take the first one. match import_items[0].kind { ItemKind::Use(path, _) => Some( path.segments diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 1a1540f505d37..b4f7c25ae1b6e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1204,13 +1204,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Some( Node::Item(hir::Item { - ident, - kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..), + kind: + hir::ItemKind::Trait(_, _, ident, ..) + | hir::ItemKind::TraitAlias(ident, ..), .. }) // We may also encounter unsatisfied GAT or method bounds | Node::TraitItem(hir::TraitItem { ident, .. }) - | Node::ImplItem(hir::ImplItem { ident, .. }), + | Node::ImplItem(hir::ImplItem { ident, .. }) ) => { skip_list.insert(p); let entry = spanned_predicates.entry(ident.span); @@ -3960,8 +3961,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } Node::Item(hir::Item { - kind: hir::ItemKind::Trait(.., bounds, _), - ident, + kind: hir::ItemKind::Trait(_, _, ident, _, bounds, _), .. }) => { let (sp, sep, article) = if bounds.is_empty() { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 3d1c61a9c344f..56dae2d7d54a8 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1250,7 +1250,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match opt_def_id { Some(def_id) => match self.tcx.hir_get_if_local(def_id) { Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Const(_, _, body_id), + kind: hir::ItemKind::Const(_, _, _, body_id), .. })) => match self.tcx.hir_node(body_id.hir_id) { hir::Node::Expr(expr) => { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index b4892e73842c3..9dccd4a0552c3 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -441,7 +441,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { // so we will continue to exclude them for compatibility. // // The documentation on `ExternCrate` is not used at the moment so no need to warn for it. - if let hir::ItemKind::Impl(..) | hir::ItemKind::Use(..) | hir::ItemKind::ExternCrate(_) = + if let hir::ItemKind::Impl(..) | hir::ItemKind::Use(..) | hir::ItemKind::ExternCrate(..) = it.kind { return; @@ -545,21 +545,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } let (def, ty) = match item.kind { - hir::ItemKind::Struct(_, ast_generics) => { + hir::ItemKind::Struct(_, _, ast_generics) => { if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(item.owner_id); (def, Ty::new_adt(cx.tcx, def, ty::List::empty())) } - hir::ItemKind::Union(_, ast_generics) => { + hir::ItemKind::Union(_, _, ast_generics) => { if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(item.owner_id); (def, Ty::new_adt(cx.tcx, def, ty::List::empty())) } - hir::ItemKind::Enum(_, ast_generics) => { + hir::ItemKind::Enum(_, _, ast_generics) => { if !ast_generics.params.is_empty() { return; } @@ -1416,7 +1416,7 @@ impl TypeAliasBounds { impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - let hir::ItemKind::TyAlias(hir_ty, generics) = item.kind else { return }; + let hir::ItemKind::TyAlias(_, hir_ty, generics) = item.kind else { return }; // There must not be a where clause. if generics.predicates.is_empty() { @@ -2119,9 +2119,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { use rustc_middle::middle::resolve_bound_vars::ResolvedArg; let def_id = item.owner_id.def_id; - if let hir::ItemKind::Struct(_, hir_generics) - | hir::ItemKind::Enum(_, hir_generics) - | hir::ItemKind::Union(_, hir_generics) = item.kind + if let hir::ItemKind::Struct(_, _, hir_generics) + | hir::ItemKind::Enum(_, _, hir_generics) + | hir::ItemKind::Union(_, _, hir_generics) = item.kind { let inferred_outlives = cx.tcx.inferred_outlives_of(def_id); if inferred_outlives.is_empty() { @@ -2257,7 +2257,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { // generics, except for tuple struct, which have the `where` // after the fields of the struct. let full_where_span = - if let hir::ItemKind::Struct(hir::VariantData::Tuple(..), _) = item.kind { + if let hir::ItemKind::Struct(_, hir::VariantData::Tuple(..), _) = item.kind { where_span } else { hir_generics.span.shrink_to_hi().to(where_span) diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs index 58efca5e994ab..78d129642dc78 100644 --- a/compiler/rustc_lint/src/default_could_be_derived.rs +++ b/compiler/rustc_lint/src/default_could_be_derived.rs @@ -93,7 +93,11 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived { let orig_fields = match cx.tcx.hir_get_if_local(type_def_id) { Some(hir::Node::Item(hir::Item { kind: - hir::ItemKind::Struct(hir::VariantData::Struct { fields, recovered: _ }, _generics), + hir::ItemKind::Struct( + _, + hir::VariantData::Struct { fields, recovered: _ }, + _generics, + ), .. })) => fields.iter().map(|f| (f.ident.name, f)).collect::>(), _ => return, diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 1f999bbea5fe7..b359ee790a50f 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -308,18 +308,18 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr { [.., penultimate, segment] if penultimate.res.opt_def_id().is_some_and(is_mod_inherent) => { - (segment.ident.span, item.ident.span, "*") + (segment.ident.span, item.kind.ident().unwrap().span, "*") } [.., segment] if path.res.iter().flat_map(Res::opt_def_id).any(is_mod_inherent) - && let rustc_hir::UseKind::Single = kind => + && let rustc_hir::UseKind::Single(ident) = kind => { let (lo, snippet) = match cx.tcx.sess.source_map().span_to_snippet(path.span).as_deref() { Ok("self") => (path.span, "*"), _ => (segment.ident.span.shrink_to_hi(), "::*"), }; - (lo, if segment.ident == item.ident { lo } else { item.ident.span }, snippet) + (lo, if segment.ident == ident { lo } else { ident.span }, snippet) } _ => return, }; diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index 35db8632625ec..dea7c8ac70877 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -39,7 +39,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { let def_id = item.owner_id.to_def_id(); // NOTE(nbdd0121): use `dyn_compatibility_violations` instead of `is_dyn_compatible` because // the latter will report `where_clause_object_safety` lint. - if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind + if let hir::ItemKind::Trait(_, _, ident, ..) = item.kind && cx.tcx.is_dyn_compatible(def_id) { let direct_super_traits_iter = cx @@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { cx.emit_span_lint( MULTIPLE_SUPERTRAIT_UPCASTABLE, cx.tcx.def_span(def_id), - crate::lints::MultipleSupertraitUpcastable { ident: item.ident }, + crate::lints::MultipleSupertraitUpcastable { ident }, ); } } diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 0890890d12cbf..f8e0a94f9ec2d 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -181,10 +181,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { && parent_opt_item_name != Some(kw::Underscore) && let Some(parent) = parent.as_local() && let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent) - && let ItemKind::Const(ty, _, _) = item.kind + && let ItemKind::Const(ident, ty, _, _) = item.kind && let TyKind::Tup(&[]) = ty.kind { - Some(item.ident.span) + Some(ident.span) } else { None }; @@ -238,7 +238,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { }, ) } - ItemKind::Macro(_macro, MacroKind::Bang) + ItemKind::Macro(_, _macro, MacroKind::Bang) if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) => { cx.emit_span_lint( diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 9e4fdd2b3ceb0..715e3506ab824 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -415,8 +415,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { } fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { - if let hir::ItemKind::Mod(_) = it.kind { - self.check_snake_case(cx, "module", &it.ident); + if let hir::ItemKind::Mod(ident, _) = it.kind { + self.check_snake_case(cx, "module", &ident); } } @@ -498,11 +498,13 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { let attrs = cx.tcx.hir_attrs(it.hir_id()); match it.kind { - hir::ItemKind::Static(..) if !ast::attr::contains_name(attrs, sym::no_mangle) => { - NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident); + hir::ItemKind::Static(ident, ..) + if !ast::attr::contains_name(attrs, sym::no_mangle) => + { + NonUpperCaseGlobals::check_upper_case(cx, "static variable", &ident); } - hir::ItemKind::Const(..) => { - NonUpperCaseGlobals::check_upper_case(cx, "constant", &it.ident); + hir::ItemKind::Const(ident, ..) => { + NonUpperCaseGlobals::check_upper_case(cx, "constant", &ident); } _ => {} } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7be48a769fe33..a7186eb48fd08 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1664,7 +1664,7 @@ impl ImproperCTypesDefinitions { && cx.tcx.sess.target.os == "aix" && !adt_def.all_fields().next().is_none() { - let struct_variant_data = item.expect_struct().0; + let struct_variant_data = item.expect_struct().1; for (index, ..) in struct_variant_data.fields().iter().enumerate() { // Struct fields (after the first field) are checked for the // power alignment rule, as fields after the first are likely @@ -1696,9 +1696,9 @@ impl ImproperCTypesDefinitions { impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { match item.kind { - hir::ItemKind::Static(ty, ..) - | hir::ItemKind::Const(ty, ..) - | hir::ItemKind::TyAlias(ty, ..) => { + hir::ItemKind::Static(_, ty, ..) + | hir::ItemKind::Const(_, ty, ..) + | hir::ItemKind::TyAlias(_, ty, ..) => { self.check_ty_maybe_containing_foreign_fnptr( cx, ty, @@ -1765,7 +1765,7 @@ declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]); impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { - if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind { + if let hir::ItemKind::Enum(_, ref enum_definition, _) = it.kind { let t = cx.tcx.type_of(it.owner_id).instantiate_identity(); let ty = cx.tcx.erase_regions(t); let Ok(layout) = cx.layout_of(ty) else { return }; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 2b9113242aa5d..6b773a2b52f93 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1836,7 +1836,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_macro(&mut self, def_id: LocalDefId) { let tcx = self.tcx; - let hir::ItemKind::Macro(macro_def, _) = tcx.hir_expect_item(def_id).kind else { bug!() }; + let (_, macro_def, _) = tcx.hir_expect_item(def_id).expect_macro(); self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules); record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body); } diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index c61c7a4fb026a..2e589150d3ee6 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -385,7 +385,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn hir_get_module(self, module: LocalModDefId) -> (&'tcx Mod<'tcx>, Span, HirId) { let hir_id = HirId::make_owner(module.to_local_def_id()); match self.hir_owner_node(hir_id.owner) { - OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. }) => (m, span, hir_id), + OwnerNode::Item(&Item { span, kind: ItemKind::Mod(_, m), .. }) => (m, span, hir_id), OwnerNode::Crate(item) => (item, item.spans.inner_span, hir_id), node => panic!("not a module: {node:?}"), } @@ -847,7 +847,7 @@ impl<'tcx> TyCtxt<'tcx> { // A `Ctor` doesn't have an identifier itself, but its parent // struct/variant does. Compare with `hir::Map::span`. Node::Ctor(..) => match self.parent_hir_node(id) { - Node::Item(item) => Some(item.ident), + Node::Item(item) => Some(item.kind.ident().unwrap()), Node::Variant(variant) => Some(variant.ident), _ => unreachable!(), }, @@ -894,18 +894,14 @@ impl<'hir> Map<'hir> { } fn named_span(item_span: Span, ident: Ident, generics: Option<&Generics<'_>>) -> Span { - if ident.name != kw::Empty { - let mut span = until_within(item_span, ident.span); - if let Some(g) = generics - && !g.span.is_dummy() - && let Some(g_span) = g.span.find_ancestor_inside(item_span) - { - span = span.to(g_span); - } - span - } else { - item_span + let mut span = until_within(item_span, ident.span); + if let Some(g) = generics + && !g.span.is_dummy() + && let Some(g_span) = g.span.find_ancestor_inside(item_span) + { + span = span.to(g_span); } + span } let span = match self.tcx.hir_node(hir_id) { @@ -936,7 +932,7 @@ impl<'hir> Map<'hir> { }) => until_within(*outer_span, generics.where_clause_span), // Constants and Statics. Node::Item(Item { - kind: ItemKind::Const(ty, ..) | ItemKind::Static(ty, ..), + kind: ItemKind::Const(_, ty, ..) | ItemKind::Static(_, ty, ..), span: outer_span, .. }) @@ -957,7 +953,7 @@ impl<'hir> Map<'hir> { }) => until_within(*outer_span, ty.span), // With generics and bounds. Node::Item(Item { - kind: ItemKind::Trait(_, _, generics, bounds, _), + kind: ItemKind::Trait(_, _, _, generics, bounds, _), span: outer_span, .. }) @@ -977,7 +973,13 @@ impl<'hir> Map<'hir> { // SyntaxContext of the path. path.span.find_ancestor_in_same_ctxt(item.span).unwrap_or(item.span) } - _ => named_span(item.span, item.ident, item.kind.generics()), + _ => { + if let Some(ident) = item.kind.ident() { + named_span(item.span, ident, item.kind.generics()) + } else { + item.span + } + } }, Node::Variant(variant) => named_span(variant.span, variant.ident, None), Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)), @@ -1327,7 +1329,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { self.items.push(item.item_id()); // Items that are modules are handled here instead of in visit_mod. - if let ItemKind::Mod(module) = &item.kind { + if let ItemKind::Mod(_, module) = &item.kind { self.submodules.push(item.owner_id); // A module collector does not recurse inside nested modules. if self.crate_collector { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index d200b1437c567..3ef8ecc59e402 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3406,20 +3406,18 @@ define_print_and_forward_display! { } fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) { - // Iterate all local crate items no matter where they are defined. + // Iterate all (non-anonymous) local crate items no matter where they are defined. for id in tcx.hir_free_items() { if matches!(tcx.def_kind(id.owner_id), DefKind::Use) { continue; } let item = tcx.hir_item(id); - if item.ident.name == kw::Empty { - continue; - } + let Some(ident) = item.kind.ident() else { continue }; let def_id = item.owner_id.to_def_id(); let ns = tcx.def_kind(def_id).ns().unwrap_or(Namespace::TypeNS); - collect_fn(&item.ident, ns, def_id); + collect_fn(&ident, ns, def_id); } // Now take care of extern crate items. diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 2909dea98b747..c8b69a6ec62f5 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -563,7 +563,7 @@ fn construct_const<'a, 'tcx>( // Figure out what primary body this item has. let (span, const_ty_span) = match tcx.hir_node(hir_id) { Node::Item(hir::Item { - kind: hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _, _), + kind: hir::ItemKind::Static(_, ty, _, _) | hir::ItemKind::Const(_, ty, _, _), span, .. }) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index cbd29ba837ef6..095d3e75da1ee 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1044,7 +1044,6 @@ fn find_fallback_pattern_typo<'tcx>( if let DefKind::Use = cx.tcx.def_kind(item.owner_id) { // Look for consts being re-exported. let item = cx.tcx.hir_expect_item(item.owner_id.def_id); - let use_name = item.ident.name; let hir::ItemKind::Use(path, _) = item.kind else { continue; }; @@ -1064,8 +1063,9 @@ fn find_fallback_pattern_typo<'tcx>( { // The const is accessible only through the re-export, point at // the `use`. - imported.push(use_name); - imported_spans.push(item.ident.span); + let ident = item.kind.ident().unwrap(); + imported.push(ident.name); + imported_spans.push(ident.span); } } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ece5a53aaa9c4..6b76b19103cbf 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -743,7 +743,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match target { Target::Struct => { if let Some(ItemLike::Item(hir::Item { - kind: hir::ItemKind::Struct(hir::VariantData::Struct { fields, .. }, _), + kind: hir::ItemKind::Struct(_, hir::VariantData::Struct { fields, .. }, _), .. })) = item && !fields.is_empty() @@ -1019,7 +1019,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { _ => None, }; match item_kind { - Some(ItemKind::Mod(module)) => { + Some(ItemKind::Mod(_, module)) => { if !module.item_ids.is_empty() { self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() }); return; @@ -1072,9 +1072,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { return; }; match item.kind { - ItemKind::Enum(_, generics) | ItemKind::Struct(_, generics) + ItemKind::Enum(_, _, generics) | ItemKind::Struct(_, _, generics) if generics.params.len() != 0 => {} - ItemKind::Trait(_, _, generics, _, items) + ItemKind::Trait(_, _, _, generics, _, items) if generics.params.len() != 0 || items.iter().any(|item| matches!(item.kind, AssocItemKind::Type)) => {} _ => { @@ -2293,7 +2293,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } else { // special case when `#[macro_export]` is applied to a macro 2.0 - let (macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro(); + let (_, macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro(); let is_decl_macro = !macro_definition.macro_rules; if is_decl_macro { @@ -2624,7 +2624,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { // Historically we've run more checks on non-exported than exported macros, // so this lets us continue to run them while maintaining backwards compatibility. // In the long run, the checks should be harmonized. - if let ItemKind::Macro(macro_def, _) = item.kind { + if let ItemKind::Macro(_, macro_def, _) = item.kind { let def_id = item.owner_id.to_def_id(); if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) { check_non_exported_macro_for_invalid_attrs(self.tcx, item); @@ -2736,7 +2736,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { } fn is_c_like_enum(item: &Item<'_>) -> bool { - if let ItemKind::Enum(ref def, _) = item.kind { + if let ItemKind::Enum(_, ref def, _) = item.kind { for variant in def.variants { match variant.data { hir::VariantData::Unit(..) => { /* continue */ } @@ -2784,7 +2784,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { .map(|id| tcx.hir_item(id)) .find(|item| !item.span.is_dummy()) // Skip prelude `use`s .map(|item| errors::ItemFollowingInnerAttr { - span: item.ident.span, + span: if let Some(ident) = item.kind.ident() { ident.span } else { item.span }, kind: item.kind.descr(), }); let err = tcx.dcx().create_err(errors::InvalidAttrAtCrateLevel { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 7029c60c3439b..808ebc8552bee 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -751,7 +751,7 @@ fn check_item<'tcx>( match tcx.def_kind(id.owner_id) { DefKind::Enum => { let item = tcx.hir_item(id); - if let hir::ItemKind::Enum(ref enum_def, _) = item.kind { + if let hir::ItemKind::Enum(_, ref enum_def, _) = item.kind { if let Some(comes_from_allow) = allow_dead_code { worklist.extend( enum_def.variants.iter().map(|variant| (variant.def_id, comes_from_allow)), @@ -806,7 +806,7 @@ fn check_item<'tcx>( } DefKind::Struct => { let item = tcx.hir_item(id); - if let hir::ItemKind::Struct(ref variant_data, _) = item.kind + if let hir::ItemKind::Struct(_, ref variant_data, _) = item.kind && let Some(ctor_def_id) = variant_data.ctor_def_id() { struct_constructors.insert(ctor_def_id, item.owner_id.def_id); @@ -987,7 +987,7 @@ impl<'tcx> DeadVisitor<'tcx> { && let Some(enum_did) = tcx.opt_parent(may_variant.to_def_id()) && let Some(enum_local_id) = enum_did.as_local() && let Node::Item(item) = tcx.hir_node_by_def_id(enum_local_id) - && let ItemKind::Enum(_, _) = item.kind + && let ItemKind::Enum(..) = item.kind { enum_local_id } else { @@ -1062,7 +1062,7 @@ impl<'tcx> DeadVisitor<'tcx> { let tuple_fields = if let Some(parent_id) = parent_item && let node = tcx.hir_node_by_def_id(parent_id) && let hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(hir::VariantData::Tuple(fields, _, _), _), + kind: hir::ItemKind::Struct(_, hir::VariantData::Tuple(fields, _, _), _), .. }) = node { diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 599a08bac20de..f65c1f40bed56 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -206,7 +206,7 @@ impl<'tcx> ReachableContext<'tcx> { } } - hir::ItemKind::Const(_, _, init) => { + hir::ItemKind::Const(_, _, _, init) => { // Only things actually ending up in the final constant value are reachable // for codegen. Everything else is only needed during const-eval, so even if // const-eval happens in a downstream crate, all they need is @@ -234,7 +234,7 @@ impl<'tcx> ReachableContext<'tcx> { // These are normal, nothing reachable about these // inherently and their children are already in the // worklist, as determined by the privacy pass - hir::ItemKind::ExternCrate(_) + hir::ItemKind::ExternCrate(..) | hir::ItemKind::Use(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Macro(..) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index aea4386295f31..9e55914f8f2f7 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -430,7 +430,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { kind = AnnotationKind::DeprecationProhibited; const_stab_inherit = InheritConstStability::Yes; } - hir::ItemKind::Struct(ref sd, _) => { + hir::ItemKind::Struct(_, ref sd, _) => { if let Some(ctor_def_id) = sd.ctor_def_id() { self.annotate( ctor_def_id, @@ -773,10 +773,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { match item.kind { - hir::ItemKind::ExternCrate(_) => { + hir::ItemKind::ExternCrate(_, ident) => { // compiler-generated `extern crate` items have a dummy span. // `std` is still checked for the `restricted-std` feature. - if item.span.is_dummy() && item.ident.name != sym::std { + if item.span.is_dummy() && ident.name != sym::std { return; } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index cf32f237b8676..bcde13423eec0 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -574,7 +574,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { // privacy and mark them reachable. DefKind::Macro(_) => { let item = self.tcx.hir_expect_item(def_id); - if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }, _) = item.kind { + if let hir::ItemKind::Macro(_, MacroDef { macro_rules: false, .. }, _) = item.kind { if vis.is_accessible_from(module, self.tcx) { self.update(def_id, macro_ev, Level::Reachable); } @@ -598,8 +598,8 @@ impl<'tcx> EmbargoVisitor<'tcx> { DefKind::Struct | DefKind::Union => { // While structs and unions have type privacy, their fields do not. let item = self.tcx.hir_expect_item(def_id); - if let hir::ItemKind::Struct(ref struct_def, _) - | hir::ItemKind::Union(ref struct_def, _) = item.kind + if let hir::ItemKind::Struct(_, ref struct_def, _) + | hir::ItemKind::Union(_, ref struct_def, _) = item.kind { for field in struct_def.fields() { let field_vis = self.tcx.local_visibility(field.def_id); @@ -653,7 +653,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { | hir::ItemKind::GlobalAsm { .. } => {} // The interface is empty, and all nested items are processed by `visit_item`. hir::ItemKind::Mod(..) => {} - hir::ItemKind::Macro(macro_def, _) => { + hir::ItemKind::Macro(_, macro_def, _) => { if let Some(item_ev) = item_ev { self.update_reachability_from_macro(item.owner_id.def_id, macro_def, item_ev); } @@ -724,7 +724,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } - hir::ItemKind::Enum(ref def, _) => { + hir::ItemKind::Enum(_, ref def, _) => { if let Some(item_ev) = item_ev { self.reach(item.owner_id.def_id, item_ev).generics().predicates(); } @@ -762,7 +762,8 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } - hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { + hir::ItemKind::Struct(_, ref struct_def, _) + | hir::ItemKind::Union(_, ref struct_def, _) => { if let Some(item_ev) = item_ev { self.reach(item.owner_id.def_id, item_ev).generics().predicates(); for field in struct_def.fields() { @@ -866,7 +867,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TestReachabilityVisitor<'a, 'tcx> { self.effective_visibility_diagnostic(item.owner_id.def_id); match item.kind { - hir::ItemKind::Enum(ref def, _) => { + hir::ItemKind::Enum(_, ref def, _) => { for variant in def.variants.iter() { self.effective_visibility_diagnostic(variant.def_id); if let Some(ctor_def_id) = variant.data.ctor_def_id() { @@ -877,7 +878,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TestReachabilityVisitor<'a, 'tcx> { } } } - hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { + hir::ItemKind::Struct(_, ref def, _) | hir::ItemKind::Union(_, ref def, _) => { if let Some(ctor_def_id) = def.ctor_def_id() { self.effective_visibility_diagnostic(ctor_def_id); } @@ -1636,7 +1637,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { } DefKind::Enum => { let item = tcx.hir_item(id); - if let hir::ItemKind::Enum(ref def, _) = item.kind { + if let hir::ItemKind::Enum(_, ref def, _) = item.kind { self.check_unnameable(item.owner_id.def_id, effective_vis); self.check(item.owner_id.def_id, item_visibility, effective_vis) @@ -1674,8 +1675,8 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { // Subitems of structs and unions have their own publicity. DefKind::Struct | DefKind::Union => { let item = tcx.hir_item(id); - if let hir::ItemKind::Struct(ref struct_def, _) - | hir::ItemKind::Union(ref struct_def, _) = item.kind + if let hir::ItemKind::Struct(_, ref struct_def, _) + | hir::ItemKind::Union(_, ref struct_def, _) = item.kind { self.check_unnameable(item.owner_id.def_id, effective_vis); self.check(item.owner_id.def_id, item_visibility, effective_vis) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 6510dbbbe9d9b..40f8af1f6913a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -2026,7 +2026,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } LetVisitor { span }.visit_body(body).break_value() } - hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. }) => { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(_, ty, _, _), .. }) => { Some(&ty.peel_refs().kind) } _ => None, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index d673e5672a00b..59c93db9c8fff 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -338,7 +338,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .. }, hir::PathSegment { - ident: assoc_item_name, + ident: assoc_item_ident, res: Res::Def(_, item_id), .. }, @@ -368,17 +368,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(local_def_id) = data.trait_ref.def_id.as_local() && let hir::Node::Item(hir::Item { - ident: trait_name, - kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), + kind: hir::ItemKind::Trait(_, _, trait_ident, _, _, trait_item_refs), .. }) = self.tcx.hir_node_by_def_id(local_def_id) && let Some(method_ref) = trait_item_refs .iter() - .find(|item_ref| item_ref.ident == *assoc_item_name) + .find(|item_ref| item_ref.ident == *assoc_item_ident) { err.span_label( method_ref.span, - format!("`{trait_name}::{assoc_item_name}` defined here"), + format!("`{trait_ident}::{assoc_item_ident}` defined here"), ); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 4d87a93be0ca0..98df09b6f7b01 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -419,7 +419,12 @@ pub fn report_dyn_incompatibility<'tcx>( ) -> Diag<'tcx> { let trait_str = tcx.def_path_str(trait_def_id); let trait_span = tcx.hir_get_if_local(trait_def_id).and_then(|node| match node { - hir::Node::Item(item) => Some(item.ident.span), + hir::Node::Item(item) => match item.kind { + hir::ItemKind::Trait(_, _, ident, ..) | hir::ItemKind::TraitAlias(ident, _, _) => { + Some(ident.span) + } + _ => unreachable!(), + }, _ => None, }); 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 9383b82ff3cde..f3ee28fe82f63 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -267,8 +267,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let node = self.tcx.hir_node_by_def_id(body_id); match node { hir::Node::Item(hir::Item { - ident, - kind: hir::ItemKind::Trait(_, _, generics, bounds, _), + kind: hir::ItemKind::Trait(_, _, ident, generics, bounds, _), .. }) if self_ty == self.tcx.types.self_param => { assert!(param_ty); @@ -282,7 +281,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { None, projection, trait_pred, - Some((ident, bounds)), + Some((&ident, bounds)), ); return; } @@ -331,7 +330,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } hir::Node::Item(hir::Item { kind: - hir::ItemKind::Trait(_, _, generics, ..) + hir::ItemKind::Trait(_, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }), .. }) if projection.is_some() => { @@ -352,15 +351,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { hir::Node::Item(hir::Item { kind: - hir::ItemKind::Struct(_, generics) - | hir::ItemKind::Enum(_, generics) - | hir::ItemKind::Union(_, generics) - | hir::ItemKind::Trait(_, _, generics, ..) + hir::ItemKind::Struct(_, _, generics) + | hir::ItemKind::Enum(_, _, generics) + | hir::ItemKind::Union(_, _, generics) + | hir::ItemKind::Trait(_, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Fn { generics, .. } - | hir::ItemKind::TyAlias(_, generics) - | hir::ItemKind::Const(_, generics, _) - | hir::ItemKind::TraitAlias(generics, _), + | hir::ItemKind::TyAlias(_, _, generics) + | hir::ItemKind::Const(_, _, generics, _) + | hir::ItemKind::TraitAlias(_, generics, _), .. }) | hir::Node::TraitItem(hir::TraitItem { generics, .. }) @@ -417,15 +416,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { hir::Node::Item(hir::Item { kind: - hir::ItemKind::Struct(_, generics) - | hir::ItemKind::Enum(_, generics) - | hir::ItemKind::Union(_, generics) - | hir::ItemKind::Trait(_, _, generics, ..) + hir::ItemKind::Struct(_, _, generics) + | hir::ItemKind::Enum(_, _, generics) + | hir::ItemKind::Union(_, _, generics) + | hir::ItemKind::Trait(_, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Fn { generics, .. } - | hir::ItemKind::TyAlias(_, generics) - | hir::ItemKind::Const(_, generics, _) - | hir::ItemKind::TraitAlias(generics, _), + | hir::ItemKind::TyAlias(_, _, generics) + | hir::ItemKind::Const(_, _, generics, _) + | hir::ItemKind::TraitAlias(_, generics, _), .. }) if !param_ty => { // Missing generic type parameter bound. @@ -847,7 +846,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { name.to_string() } Some(hir::Node::Item(hir::Item { - ident, kind: hir::ItemKind::Fn { .. }, .. + kind: hir::ItemKind::Fn { ident, .. }, .. })) => { err.span_label(ident.span, "consider calling this function"); ident.to_string() @@ -1593,20 +1592,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(typeck_results) = &self.typeck_results && let ty = typeck_results.expr_ty_adjusted(base) && let ty::FnDef(def_id, _args) = ty.kind() - && let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) = - self.tcx.hir_get_if_local(*def_id) + && let Some(hir::Node::Item(item)) = self.tcx.hir_get_if_local(*def_id) { + let (ident, _, _, _) = item.expect_fn(); let msg = format!("alternatively, consider making `fn {ident}` asynchronous"); - if vis_span.is_empty() { + if item.vis_span.is_empty() { err.span_suggestion_verbose( - span.shrink_to_lo(), + item.span.shrink_to_lo(), msg, "async ", Applicability::MaybeIncorrect, ); } else { err.span_suggestion_verbose( - vis_span.shrink_to_hi(), + item.vis_span.shrink_to_hi(), msg, " async", Applicability::MaybeIncorrect, @@ -3308,8 +3307,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut is_auto_trait = false; match tcx.hir_get_if_local(data.impl_or_alias_def_id) { Some(Node::Item(hir::Item { - kind: hir::ItemKind::Trait(is_auto, ..), - ident, + kind: hir::ItemKind::Trait(is_auto, _, ident, ..), .. })) => { // FIXME: we should do something else so that it works even on crate foreign diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index fe859eb53cd78..7159397c4b1a4 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -516,7 +516,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.scope)) { hir::Node::Item(hir::Item { - kind: hir::ItemKind::Trait(_, _, generics, ..), + kind: hir::ItemKind::Trait(_, _, _, generics, ..), .. }) | hir::Node::Item(hir::Item { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 929402d41707e..4ecf702d7b6ef 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -125,7 +125,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< items.extend(doc.items.values().flat_map(|(item, renamed, _)| { // Now we actually lower the imports, skipping everything else. if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind { - let name = renamed.unwrap_or_else(|| cx.tcx.hir_name(item.hir_id())); + let name = renamed.unwrap_or(kw::Empty); // using kw::Empty is a bit of a hack clean_use_statement(item, name, path, hir::UseKind::Glob, cx, &mut inserted) } else { // skip everything else @@ -1629,8 +1629,7 @@ fn first_non_private<'tcx>( if let Some(use_def_id) = reexp.id() && let Some(local_use_def_id) = use_def_id.as_local() && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_use_def_id) - && !item.ident.name.is_empty() - && let hir::ItemKind::Use(path, _) = item.kind + && let hir::ItemKind::Use(path, hir::UseKind::Single(_)) = item.kind { for res in &path.res { if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { @@ -1775,7 +1774,7 @@ fn maybe_expand_private_type_alias<'tcx>( } else { return None; }; - let hir::ItemKind::TyAlias(ty, generics) = alias else { return None }; + let hir::ItemKind::TyAlias(_, ty, generics) = alias else { return None }; let final_seg = &path.segments.last().expect("segments were empty"); let mut args = DefIdMap::default(); @@ -2794,20 +2793,24 @@ fn clean_maybe_renamed_item<'tcx>( use hir::ItemKind; let def_id = item.owner_id.to_def_id(); - let mut name = renamed.unwrap_or_else(|| cx.tcx.hir_name(item.hir_id())); + let mut name = renamed.unwrap_or_else(|| { + // FIXME: using kw::Empty is a bit of a hack + cx.tcx.hir_opt_name(item.hir_id()).unwrap_or(kw::Empty) + }); + cx.with_param_env(def_id, |cx| { let kind = match item.kind { - ItemKind::Static(ty, mutability, body_id) => StaticItem(Static { + ItemKind::Static(_, ty, mutability, body_id) => StaticItem(Static { type_: Box::new(clean_ty(ty, cx)), mutability, expr: Some(body_id), }), - ItemKind::Const(ty, generics, body_id) => ConstantItem(Box::new(Constant { + ItemKind::Const(_, ty, generics, body_id) => ConstantItem(Box::new(Constant { generics: clean_generics(generics, cx), type_: clean_ty(ty, cx), kind: ConstantKind::Local { body: body_id, def_id }, })), - ItemKind::TyAlias(hir_ty, generics) => { + ItemKind::TyAlias(_, hir_ty, generics) => { *cx.current_type_aliases.entry(def_id).or_insert(0) += 1; let rustdoc_ty = clean_ty(hir_ty, cx); let type_ = @@ -2840,34 +2843,34 @@ fn clean_maybe_renamed_item<'tcx>( )); return ret; } - ItemKind::Enum(ref def, generics) => EnumItem(Enum { + ItemKind::Enum(_, ref def, generics) => EnumItem(Enum { variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(), generics: clean_generics(generics, cx), }), - ItemKind::TraitAlias(generics, bounds) => TraitAliasItem(TraitAlias { + ItemKind::TraitAlias(_, generics, bounds) => TraitAliasItem(TraitAlias { generics: clean_generics(generics, cx), bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), }), - ItemKind::Union(ref variant_data, generics) => UnionItem(Union { + ItemKind::Union(_, ref variant_data, generics) => UnionItem(Union { generics: clean_generics(generics, cx), fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(), }), - ItemKind::Struct(ref variant_data, generics) => StructItem(Struct { + ItemKind::Struct(_, ref variant_data, generics) => StructItem(Struct { ctor_kind: variant_data.ctor_kind(), generics: clean_generics(generics, cx), fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(), }), ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx), - ItemKind::Macro(macro_def, MacroKind::Bang) => MacroItem(Macro { + ItemKind::Macro(_, macro_def, MacroKind::Bang) => MacroItem(Macro { source: display_macro_source(cx, name, macro_def), macro_rules: macro_def.macro_rules, }), - ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx), + ItemKind::Macro(_, _, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx), // proc macros can have a name set by attributes ItemKind::Fn { ref sig, generics, body: body_id, .. } => { clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) } - ItemKind::Trait(_, _, generics, bounds, item_ids) => { + ItemKind::Trait(_, _, _, generics, bounds, item_ids) => { let items = item_ids .iter() .map(|ti| clean_trait_item(cx.tcx.hir_trait_item(ti.id), cx)) @@ -2880,7 +2883,7 @@ fn clean_maybe_renamed_item<'tcx>( bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), })) } - ItemKind::ExternCrate(orig_name) => { + ItemKind::ExternCrate(orig_name, _) => { return clean_extern_crate(item, name, orig_name, cx); } ItemKind::Use(path, kind) => { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 3f9023659dbac..ebfd1338b2ec0 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -226,7 +226,7 @@ impl ExternalCrate { .filter_map(|&id| { let item = tcx.hir_item(id); match item.kind { - hir::ItemKind::Mod(_) => { + hir::ItemKind::Mod(..) => { as_keyword(Res::Def(DefKind::Mod, id.owner_id.to_def_id())) } _ => None, @@ -282,7 +282,7 @@ impl ExternalCrate { .filter_map(|&id| { let item = tcx.hir_item(id); match item.kind { - hir::ItemKind::Mod(_) => { + hir::ItemKind::Mod(..) => { as_primitive(Res::Def(DefKind::Mod, id.owner_id.to_def_id())) } _ => None, diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 18ad442d01789..d007225694140 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -80,7 +80,7 @@ impl<'tcx> HirCollector<'tcx> { pub fn collect_crate(mut self) -> Vec { let tcx = self.tcx; - self.visit_testable("".to_string(), CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID), |this| { + self.visit_testable(None, CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID), |this| { tcx.hir_walk_toplevel_module(this) }); self.collector.tests @@ -90,7 +90,7 @@ impl<'tcx> HirCollector<'tcx> { impl HirCollector<'_> { fn visit_testable( &mut self, - name: String, + name: Option, def_id: LocalDefId, sp: Span, nested: F, @@ -103,9 +103,10 @@ impl HirCollector<'_> { return; } - let has_name = !name.is_empty(); - if has_name { + let mut has_name = false; + if let Some(name) = name { self.collector.cur_path.push(name); + has_name = true; } // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with @@ -153,9 +154,9 @@ impl<'tcx> intravisit::Visitor<'tcx> for HirCollector<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'_>) { let name = match &item.kind { hir::ItemKind::Impl(impl_) => { - rustc_hir_pretty::id_to_string(&self.tcx, impl_.self_ty.hir_id) + Some(rustc_hir_pretty::id_to_string(&self.tcx, impl_.self_ty.hir_id)) } - _ => item.ident.to_string(), + _ => item.kind.ident().map(|ident| ident.to_string()), }; self.visit_testable(name, item.owner_id.def_id, item.span, |this| { @@ -164,31 +165,46 @@ impl<'tcx> intravisit::Visitor<'tcx> for HirCollector<'tcx> { } fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'_>) { - self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| { - intravisit::walk_trait_item(this, item); - }); + self.visit_testable( + Some(item.ident.to_string()), + item.owner_id.def_id, + item.span, + |this| { + intravisit::walk_trait_item(this, item); + }, + ); } fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'_>) { - self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| { - intravisit::walk_impl_item(this, item); - }); + self.visit_testable( + Some(item.ident.to_string()), + item.owner_id.def_id, + item.span, + |this| { + intravisit::walk_impl_item(this, item); + }, + ); } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'_>) { - self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| { - intravisit::walk_foreign_item(this, item); - }); + self.visit_testable( + Some(item.ident.to_string()), + item.owner_id.def_id, + item.span, + |this| { + intravisit::walk_foreign_item(this, item); + }, + ); } fn visit_variant(&mut self, v: &'tcx hir::Variant<'_>) { - self.visit_testable(v.ident.to_string(), v.def_id, v.span, |this| { + self.visit_testable(Some(v.ident.to_string()), v.def_id, v.span, |this| { intravisit::walk_variant(this, v); }); } fn visit_field_def(&mut self, f: &'tcx hir::FieldDef<'_>) { - self.visit_testable(f.ident.to_string(), f.def_id, f.span, |this| { + self.visit_testable(Some(f.ident.to_string()), f.def_id, f.span, |this| { intravisit::walk_field_def(this, f); }); } diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 3228f71df0743..3676051b1bd29 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -242,10 +242,9 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { // Now that we confirmed it's a file import, we want to get the span for the module // name only and not all the "mod foo;". if let Node::Item(item) = self.tcx.hir_node(id) { - self.matches.insert( - item.ident.span, - LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)), - ); + let (ident, _) = item.expect_mod(); + self.matches + .insert(ident.span, LinkFromSrc::Local(clean::Span::new(m.spans.inner_span))); } } else { // If it's a "mod foo {}", we want to look to its documentation page. @@ -273,22 +272,22 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx Item<'tcx>) { match item.kind { ItemKind::Static(..) - | ItemKind::Const(_, _, _) + | ItemKind::Const(..) | ItemKind::Fn { .. } - | ItemKind::Macro(_, _) - | ItemKind::TyAlias(_, _) - | ItemKind::Enum(_, _) - | ItemKind::Struct(_, _) - | ItemKind::Union(_, _) - | ItemKind::Trait(_, _, _, _, _) - | ItemKind::TraitAlias(_, _) => self.extract_info_from_hir_id(item.hir_id()), + | ItemKind::Macro(..) + | ItemKind::TyAlias(..) + | ItemKind::Enum(..) + | ItemKind::Struct(..) + | ItemKind::Union(..) + | ItemKind::Trait(..) + | ItemKind::TraitAlias(..) => self.extract_info_from_hir_id(item.hir_id()), ItemKind::Impl(_) - | ItemKind::Use(_, _) - | ItemKind::ExternCrate(_) + | ItemKind::Use(..) + | ItemKind::ExternCrate(..) | ItemKind::ForeignMod { .. } | ItemKind::GlobalAsm { .. } // We already have "visit_mod" above so no need to check it here. - | ItemKind::Mod(_) => {} + | ItemKind::Mod(..) => {} } intravisit::walk_item(self, item); } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 45b8dafa90792..f8f670f575bf4 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -240,7 +240,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { data: hir::VariantData::Tuple(_, _, _), .. }) | hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(hir::VariantData::Tuple(_, _, _), _), + kind: hir::ItemKind::Struct(_, hir::VariantData::Tuple(_, _, _), _), .. }) ) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 68e381fa3f171..254549e72c649 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -144,9 +144,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { && inserted.insert(def_id) { let item = self.cx.tcx.hir_expect_item(local_def_id); - top_level_module - .items - .insert((local_def_id, Some(item.ident.name)), (item, None, None)); + let (ident, _, _) = item.expect_macro(); + top_level_module.items.insert((local_def_id, Some(ident.name)), (item, None, None)); } } @@ -224,11 +223,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { def_id: LocalDefId, res: Res, renamed: Option, - glob: bool, please_inline: bool, ) -> bool { debug!("maybe_inline_local (renamed: {renamed:?}) res: {res:?}"); + let glob = renamed.is_none(); if renamed == Some(kw::Underscore) { // We never inline `_` reexports. return false; @@ -286,7 +285,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { is_hidden && // If it's a doc hidden module, we need to keep it in case some of its inner items // are re-exported. - !matches!(item, Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_), .. })) + !matches!(item, Node::Item(&hir::Item { kind: hir::ItemKind::Mod(..), .. })) ) || // The imported item is public and not `doc(hidden)` so no need to inline it. self.reexport_public_and_not_hidden(def_id, res_did) @@ -297,7 +296,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let is_bang_macro = matches!( item, - Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, MacroKind::Bang), .. }) + Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, _, MacroKind::Bang), .. }) ); if !self.view_item_stack.insert(res_did) && !is_bang_macro { @@ -311,7 +310,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Node::Item(_) if is_bang_macro && !please_inline && renamed.is_some() && is_hidden => { return false; } - Node::Item(&hir::Item { kind: hir::ItemKind::Mod(m), .. }) if glob => { + Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_, m), .. }) if glob => { let prev = mem::replace(&mut self.inlining, true); for &i in m.item_ids { let i = tcx.hir_item(i); @@ -378,7 +377,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // attribute can still be visible. || match item.kind { hir::ItemKind::Impl(..) => true, - hir::ItemKind::Macro(_, MacroKind::Bang) => { + hir::ItemKind::Macro(_, _, MacroKind::Bang) => { self.cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) } _ => false, @@ -419,7 +418,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } return; } - let name = renamed.unwrap_or(item.ident.name); + let get_name = || renamed.unwrap_or(item.kind.ident().unwrap().name); let tcx = self.cx.tcx; let def_id = item.owner_id.to_def_id(); @@ -459,15 +458,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } _ => false, }); - let is_glob = kind == hir::UseKind::Glob; - let ident = if is_glob { None } else { Some(name) }; - if self.maybe_inline_local( - item.owner_id.def_id, - res, - ident, - is_glob, - please_inline, - ) { + let ident = match kind { + hir::UseKind::Single(ident) => Some(renamed.unwrap_or(ident.name)), + hir::UseKind::Glob => None, + hir::UseKind::ListStem => unreachable!(), + }; + if self.maybe_inline_local(item.owner_id.def_id, res, ident, please_inline) + { debug!("Inlining {:?}", item.owner_id.def_id); continue; } @@ -475,7 +472,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.add_to_current_mod(item, renamed, import_id); } } - hir::ItemKind::Macro(macro_def, _) => { + hir::ItemKind::Macro(_, macro_def, _) => { // `#[macro_export] macro_rules!` items are handled separately in `visit()`, // above, since they need to be documented at the module top level. Accordingly, // we only want to handle macros if one of three conditions holds: @@ -495,8 +492,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.add_to_current_mod(item, renamed, import_id); } } - hir::ItemKind::Mod(m) => { - self.enter_mod(item.owner_id.def_id, m, name, renamed, import_id); + hir::ItemKind::Mod(_, m) => { + self.enter_mod(item.owner_id.def_id, m, get_name(), renamed, import_id); } hir::ItemKind::Fn { .. } | hir::ItemKind::ExternCrate(..) @@ -512,7 +509,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { hir::ItemKind::Const(..) => { // Underscore constants do not correspond to a nameable item and // so are never useful in documentation. - if name != kw::Underscore { + if get_name() != kw::Underscore { self.add_to_current_mod(item, renamed, import_id); } } diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index c0ae4960e10d9..39528a8f55c38 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -5,7 +5,7 @@ use clippy_config::types::{ }; use clippy_utils::diagnostics::span_lint_and_note; use rustc_hir::{ - AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, UseKind, + AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, Variant, VariantData, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -178,8 +178,8 @@ impl ArbitrarySourceItemOrdering { /// Produces a linting warning for incorrectly ordered item members. fn lint_member_name( cx: &T, - ident: &rustc_span::symbol::Ident, - before_ident: &rustc_span::symbol::Ident, + ident: &rustc_span::Ident, + before_ident: &rustc_span::Ident, ) { span_lint_and_note( cx, @@ -192,21 +192,21 @@ impl ArbitrarySourceItemOrdering { } fn lint_member_item(cx: &T, item: &Item<'_>, before_item: &Item<'_>) { - let span = if item.ident.as_str().is_empty() { - &item.span + let span = if let Some(ident) = item.kind.ident() { + ident.span } else { - &item.ident.span + item.span }; - let (before_span, note) = if before_item.ident.as_str().is_empty() { + let (before_span, note) = if let Some(ident) = before_item.kind.ident() { ( - &before_item.span, - "should be placed before the following item".to_owned(), + ident.span, + format!("should be placed before `{}`", ident.as_str(),), ) } else { ( - &before_item.ident.span, - format!("should be placed before `{}`", before_item.ident.as_str(),), + before_item.span, + "should be placed before the following item".to_owned(), ) }; @@ -218,9 +218,9 @@ impl ArbitrarySourceItemOrdering { span_lint_and_note( cx, ARBITRARY_SOURCE_ITEM_ORDERING, - *span, + span, "incorrect ordering of items (must be alphabetically ordered)", - Some(*before_span), + Some(before_span), note, ); } @@ -244,7 +244,7 @@ impl ArbitrarySourceItemOrdering { impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { match &item.kind { - ItemKind::Enum(enum_def, _generics) if self.enable_ordering_for_enum => { + ItemKind::Enum(_, enum_def, _generics) if self.enable_ordering_for_enum => { let mut cur_v: Option<&Variant<'_>> = None; for variant in enum_def.variants { if variant.span.in_external_macro(cx.sess().source_map()) { @@ -259,7 +259,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { cur_v = Some(variant); } }, - ItemKind::Struct(VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => { + ItemKind::Struct(_, VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => { let mut cur_f: Option<&FieldDef<'_>> = None; for field in *fields { if field.span.in_external_macro(cx.sess().source_map()) { @@ -274,7 +274,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { cur_f = Some(field); } }, - ItemKind::Trait(is_auto, _safety, _generics, _generic_bounds, item_ref) + ItemKind::Trait(is_auto, _safety, _ident, _generics, _generic_bounds, item_ref) if self.enable_ordering_for_trait && *is_auto == IsAuto::No => { let mut cur_t: Option<&TraitItemRef> = None; @@ -351,50 +351,24 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { continue; } - // The following exceptions (skipping with `continue;`) may not be - // complete, edge cases have not been explored further than what - // appears in the existing code base. - if item.ident.name == rustc_span::symbol::kw::Empty { - if let ItemKind::Impl(_) = item.kind { - // Sorting trait impls for unnamed types makes no sense. - if get_item_name(item).is_empty() { - continue; - } - } else if let ItemKind::ForeignMod { .. } = item.kind { - continue; - } else if let ItemKind::GlobalAsm { .. } = item.kind { - continue; - } else if let ItemKind::Use(path, use_kind) = item.kind { - if path.segments.is_empty() { - // Use statements that contain braces get caught here. - // They will still be linted internally. - continue; - } else if path.segments.len() >= 2 - && (path.segments[0].ident.name == rustc_span::sym::std - || path.segments[0].ident.name == rustc_span::sym::core) - && path.segments[1].ident.name == rustc_span::sym::prelude - { - // Filters the autogenerated prelude use statement. - // e.g. `use std::prelude::rustc_2021` - } else if use_kind == UseKind::Glob { - // Filters glob kinds of uses. - // e.g. `use std::sync::*` - } else { - // This can be used for debugging. - // println!("Unknown autogenerated use statement: {:?}", item); - } - continue; - } - } + let ident = if let Some(ident) = item.kind.ident() { + ident + } else if let ItemKind::Impl(_) = item.kind + && !get_item_name(item).is_empty() + { + rustc_span::Ident::empty() // FIXME: a bit strange, is there a better way to do it? + } else { + continue; + }; - if item.ident.name.as_str().starts_with('_') { + if ident.name.as_str().starts_with('_') { // Filters out unnamed macro-like impls for various derives, // e.g. serde::Serialize or num_derive::FromPrimitive. continue; } - if item.ident.name == rustc_span::sym::std && item.span.is_dummy() { - if let ItemKind::ExternCrate(None) = item.kind { + if ident.name == rustc_span::sym::std && item.span.is_dummy() { + if let ItemKind::ExternCrate(None, _) = item.kind { // Filters the auto-included Rust standard library. continue; } @@ -525,6 +499,8 @@ fn get_item_name(item: &Item<'_>) -> String { String::new() } }, - _ => item.ident.name.as_str().to_owned(), + // FIXME: `Ident::empty` for anonymous items is a bit strange, is there + // a better way to do it? + _ => item.kind.ident().unwrap_or(rustc_span::Ident::empty()).name.as_str().to_owned(), } } diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index f9a2f011a144f..54ec8c7b2758b 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -16,7 +16,7 @@ mod utils; use clippy_config::Conf; use clippy_utils::msrvs::{self, Msrv, MsrvStack}; use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind}; -use rustc_hir::{ImplItem, Item, TraitItem}; +use rustc_hir::{ImplItem, Item, ItemKind, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::sym; @@ -466,8 +466,8 @@ impl Attributes { impl<'tcx> LateLintPass<'tcx> for Attributes { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { let attrs = cx.tcx.hir_attrs(item.hir_id()); - if is_relevant_item(cx, item) { - inline_always::check(cx, item.span, item.ident.name, attrs); + if let ItemKind::Fn { ident, .. } = item.kind && is_relevant_item(cx, item) { + inline_always::check(cx, item.span, ident.name, attrs); } repr_attributes::check(cx, item.span, attrs, self.msrv); } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs index 3659946b70424..38903596414cf 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs @@ -99,7 +99,7 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]); impl<'tcx> LateLintPass<'tcx> for DisallowedTypes { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if let ItemKind::Use(path, UseKind::Single) = &item.kind { + if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind { for res in &path.res { self.check_res_emit(cx, res, item.span); } diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index 2e1f8ac615a23..f01b5c840d290 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { if cx.tcx.data_layout.pointer_size.bits() != 64 { return; } - if let ItemKind::Enum(def, _) = &item.kind { + if let ItemKind::Enum(_, def, _) = &item.kind { for var in def.variants { if let Some(anon_const) = &var.disr_expr { let def_id = cx.tcx.hir_body_owner_def_id(anon_const.body); diff --git a/src/tools/clippy/clippy_lints/src/error_impl_error.rs b/src/tools/clippy/clippy_lints/src/error_impl_error.rs index 1e6447dc25370..6525648efb1e9 100644 --- a/src/tools/clippy/clippy_lints/src/error_impl_error.rs +++ b/src/tools/clippy/clippy_lints/src/error_impl_error.rs @@ -37,8 +37,8 @@ declare_lint_pass!(ErrorImplError => [ERROR_IMPL_ERROR]); impl<'tcx> LateLintPass<'tcx> for ErrorImplError { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { match item.kind { - ItemKind::TyAlias(..) - if item.ident.name == sym::Error + ItemKind::TyAlias(ident, ..) + if ident.name == sym::Error && is_visible_outside_module(cx, item.owner_id.def_id) && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error) @@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError { span_lint( cx, ERROR_IMPL_ERROR, - item.ident.span, + ident.span, "exported type alias named `Error` that implements `Error`", ); }, diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 9298f56b68bee..3433b2cd857a9 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -91,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { } // find `self` ty for this trait if relevant - if let ItemKind::Trait(_, _, _, _, items) = item.kind { + if let ItemKind::Trait(_, _, _, _, _, items) = item.kind { for trait_item in items { if trait_item.id.owner_id.def_id == fn_def_id { // be sure we have `self` parameter in this function diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs index 54a1ac21c85c3..2509c04cd86dd 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs @@ -122,7 +122,7 @@ fn check_fn_decl(cx: &LateContext<'_>, decl: &FnDecl<'_>, sp: Span, max: u64) { impl<'tcx> LateLintPass<'tcx> for ExcessiveBools { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if let ItemKind::Struct(variant_data, _) = &item.kind + if let ItemKind::Struct(_, variant_data, _) = &item.kind && variant_data.fields().len() as u64 > self.max_struct_bools && has_n_bools( variant_data.fields().iter().map(|field| field.ty), diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs index 591912cc8d5e8..5a74e97c97c5e 100644 --- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs +++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs @@ -76,7 +76,7 @@ impl LateLintPass<'_> for ExhaustiveItems { "exported enums should not be exhaustive", [].as_slice(), ), - ItemKind::Struct(v, ..) => ( + ItemKind::Struct(_, v, ..) => ( EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive", v.fields(), diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index cade56f582261..07a92a4ed70c6 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -103,7 +103,7 @@ fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty .did() .as_local() && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_def_id) - && let hir::ItemKind::Enum(ref def, _) = item.kind + && let hir::ItemKind::Enum(_, ref def, _) = item.kind { let variants_size = AdtVariantInfo::new(cx, *adt, subst); if let Some((first_variant, variants)) = variants_size.split_first() diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs index 6363f717a5c2f..8de6125d1f2b3 100644 --- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs +++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::Span; +use rustc_span::{Ident, Span}; use rustc_span::symbol::Symbol; declare_clippy_lint! { @@ -196,16 +196,16 @@ fn have_no_extra_prefix(prefixes: &[&str]) -> bool { prefixes.iter().all(|p| p == &"" || p == &"_") } -fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: &[FieldDef<'_>]) { +fn check_fields(cx: &LateContext<'_>, threshold: u64, ident: Ident, span: Span, fields: &[FieldDef<'_>]) { if (fields.len() as u64) < threshold { return; } - check_struct_name_repetition(cx, item, fields); + check_struct_name_repetition(cx, ident, fields); // if the SyntaxContext of the identifiers of the fields and struct differ dont lint them. // this prevents linting in macros in which the location of the field identifier names differ - if !fields.iter().all(|field| item.ident.span.eq_ctxt(field.ident.span)) { + if !fields.iter().all(|field| ident.span.eq_ctxt(field.ident.span)) { return; } @@ -256,7 +256,7 @@ fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: & span_lint_and_help( cx, STRUCT_FIELD_NAMES, - item.span, + span, format!("all fields have the same {what}fix: `{value}`"), None, format!("remove the {what}fixes"), @@ -264,11 +264,11 @@ fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: & } } -fn check_struct_name_repetition(cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { - let snake_name = to_snake_case(item.ident.name.as_str()); +fn check_struct_name_repetition(cx: &LateContext<'_>, ident: Ident, fields: &[FieldDef<'_>]) { + let snake_name = to_snake_case(ident.name.as_str()); let item_name_words: Vec<&str> = snake_name.split('_').collect(); for field in fields { - if field.ident.span.eq_ctxt(item.ident.span) { + if field.ident.span.eq_ctxt(ident.span) { //consider linting only if the field identifier has the same SyntaxContext as the item(struct) let field_words: Vec<&str> = field.ident.name.as_str().split('_').collect(); if field_words.len() >= item_name_words.len() { @@ -397,19 +397,23 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n } impl LateLintPass<'_> for ItemNameRepetitions { - fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) { + fn check_item_post(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) { + let Some(_ident) = item.kind.ident() else { return }; + let last = self.modules.pop(); assert!(last.is_some()); } fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - let item_name = item.ident.name.as_str(); + let Some(ident) = item.kind.ident() else { return }; + + let item_name = ident.name.as_str(); let item_camel = to_camel_case(item_name); if !item.span.from_expansion() && is_present_in_source(cx, item.span) { if let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules { // constants don't have surrounding modules if !mod_camel.is_empty() { - if mod_name == &item.ident.name + if mod_name == &ident.name && let ItemKind::Mod(..) = item.kind && (!self.allow_private_module_inception || cx.tcx.visibility(mod_owner_id.def_id).is_public()) { @@ -438,7 +442,7 @@ impl LateLintPass<'_> for ItemNameRepetitions { Some(c) if is_word_beginning(c) => span_lint( cx, MODULE_NAME_REPETITIONS, - item.ident.span, + ident.span, "item name starts with its containing module's name", ), _ => (), @@ -450,7 +454,7 @@ impl LateLintPass<'_> for ItemNameRepetitions { span_lint( cx, MODULE_NAME_REPETITIONS, - item.ident.span, + ident.span, "item name ends with its containing module's name", ); } @@ -462,13 +466,13 @@ impl LateLintPass<'_> for ItemNameRepetitions { && span_is_local(item.span) { match item.kind { - ItemKind::Enum(def, _) => check_variant(cx, self.enum_threshold, &def, item_name, item.span), - ItemKind::Struct(VariantData::Struct { fields, .. }, _) => { - check_fields(cx, self.struct_threshold, item, fields); + ItemKind::Enum(_, def, _) => check_variant(cx, self.enum_threshold, &def, item_name, item.span), + ItemKind::Struct(_, VariantData::Struct { fields, .. }, _) => { + check_fields(cx, self.struct_threshold, ident, item.span, fields); }, _ => (), } } - self.modules.push((item.ident.name, item_camel, item.owner_id)); + self.modules.push((ident.name, item_camel, item.owner_id)); } } diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs index 9df044f25eb78..dd63de288b87f 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs @@ -44,7 +44,7 @@ declare_clippy_lint! { declare_lint_pass!(ItemsAfterTestModule => [ITEMS_AFTER_TEST_MODULE]); fn cfg_test_module<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { - if let ItemKind::Mod(test_mod) = item.kind + if let ItemKind::Mod(_, test_mod) = item.kind && item.span.hi() == test_mod.spans.inner_span.hi() && is_cfg_test(cx.tcx, item.hir_id()) && !item.span.from_expansion() @@ -67,14 +67,20 @@ impl LateLintPass<'_> for ItemsAfterTestModule { let after: Vec<_> = items .filter(|item| { // Ignore the generated test main function - !(item.ident.name == sym::main - && item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness)) + if let ItemKind::Fn { ident, .. } = item.kind + && ident.name == sym::main + && item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness) + { + false + } else { + true + } }) .collect(); if let Some(last) = after.last() && after.iter().all(|&item| { - !matches!(item.kind, ItemKind::Mod(_)) && !item.span.from_expansion() && !is_from_proc_macro(cx, item) + !matches!(item.kind, ItemKind::Mod(..)) && !item.span.from_expansion() && !is_from_proc_macro(cx, item) }) && !fulfill_or_allowed(cx, ITEMS_AFTER_TEST_MODULE, after.iter().map(|item| item.hir_id())) { diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index cabf10b7e0ea9..394005e991295 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -48,7 +48,7 @@ impl_lint_pass!(LargeConstArrays => [LARGE_CONST_ARRAYS]); impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Const(_, generics, _) = &item.kind + if let ItemKind::Const(ident, _, generics, _) = &item.kind // Since static items may not have generics, skip generic const items. // FIXME(generic_const_items): I don't think checking `generics.hwcp` suffices as it // doesn't account for empty where-clauses that only consist of keyword `where` IINM. @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size) { - let hi_pos = item.ident.span.lo() - BytePos::from_usize(1); + let hi_pos = ident.span.lo() - BytePos::from_usize(1); let sugg_span = Span::new( hi_pos - BytePos::from_usize("const".len()), hi_pos, diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index d9953dbc261b0..d08efa0ec9cc0 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -73,7 +73,7 @@ impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]); impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) { - if let ItemKind::Enum(ref def, _) = item.kind + if let ItemKind::Enum(ident, ref def, _) = item.kind && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let ty::Adt(adt, subst) = ty.kind() && adt.variants().len() > 1 @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { let mut applicability = Applicability::MaybeIncorrect; if is_copy(cx, ty) || maybe_copy(cx, ty) { diag.span_note( - item.ident.span, + ident.span, "boxing a variant would require the type no longer be `Copy`", ); } else { diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs index 3939318bee6ea..ca51d8b618ee3 100644 --- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs +++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { // Integer modules are "TBD" deprecated, and the contents are too, // so lint on the `use` statement directly. - if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind + if let ItemKind::Use(path, kind @ (UseKind::Single(_) | UseKind::Glob)) = item.kind && !item.span.in_external_macro(cx.sess().source_map()) && let Some(def_id) = path.res[0].opt_def_id() && self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS) @@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { "importing a legacy numeric constant" }, |diag| { - if item.ident.name == kw::Underscore { + if let UseKind::Single(ident) = kind && ident.name == kw::Underscore { diag.help("remove this import"); return; } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 98ba52f12707f..72e22ae59d8f4 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::{self, AssocKind, FnSig, Ty}; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; -use rustc_span::{Span, Symbol}; +use rustc_span::{Ident, Span, Symbol}; use rustc_trait_selection::traits::supertrait_def_ids; declare_clippy_lint! { @@ -123,10 +123,10 @@ declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY, COMPARISON_TO_EMP impl<'tcx> LateLintPass<'tcx> for LenZero { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Trait(_, _, _, _, trait_items) = item.kind + if let ItemKind::Trait(_, _, ident, _, _, trait_items) = item.kind && !item.span.from_expansion() { - check_trait_items(cx, item, trait_items); + check_trait_items(cx, item, ident, trait_items); } } @@ -150,10 +150,10 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { let (name, kind) = match cx.tcx.hir_node(ty_hir_id) { Node::ForeignItem(x) => (x.ident.name, "extern type"), Node::Item(x) => match x.kind { - ItemKind::Struct(..) => (x.ident.name, "struct"), - ItemKind::Enum(..) => (x.ident.name, "enum"), - ItemKind::Union(..) => (x.ident.name, "union"), - _ => (x.ident.name, "type"), + ItemKind::Struct(ident, ..) => (ident.name, "struct"), + ItemKind::Enum(ident, ..) => (ident.name, "enum"), + ItemKind::Union(ident, ..) => (ident.name, "union"), + _ => (x.kind.ident().unwrap().name, "type"), }, _ => return, }; @@ -250,7 +250,7 @@ fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span { } } -fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) { +fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, ident: Ident, trait_items: &[TraitItemRef]) { fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool { item.ident.name == name && if let AssocItemKind::Fn { has_self } = item.kind { @@ -300,7 +300,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items visited_trait.span, format!( "trait `{}` has a `len` method but no (possibly inherited) `is_empty` method", - visited_trait.ident.name + ident.name ), ); } diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 64b07a5536b4d..067b92cd46eed 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -87,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { } match item.kind { - ItemKind::Enum(def, _) if def.variants.len() > 1 => { + ItemKind::Enum(_, def, _) if def.variants.len() > 1 => { let iter = def.variants.iter().filter_map(|v| { (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir_attrs(v.hir_id))) .then_some((v.def_id, v.span)) @@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { self.potential_enums.push((item.owner_id.def_id, id, item.span, span)); } }, - ItemKind::Struct(variant_data, _) => { + ItemKind::Struct(_, variant_data, _) => { let fields = variant_data.fields(); let private_fields = fields .iter() diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 3470c266c4917..b234b190153b6 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -192,17 +192,17 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { match it.kind { - hir::ItemKind::Fn { .. } => { + hir::ItemKind::Fn { ident, .. } => { // ignore main() - if it.ident.name == sym::main { + if ident.name == sym::main { let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID; if at_root { note_prev_span_then_ret!(self.prev_span, it.span); } } }, - hir::ItemKind::Const(..) => { - if it.ident.name == kw::Underscore { + hir::ItemKind::Const(ident, ..) => { + if ident.name == kw::Underscore { note_prev_span_then_ret!(self.prev_span, it.span); } }, diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs index 59f29d242abf3..66631a6920636 100644 --- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs +++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs @@ -67,7 +67,7 @@ impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]); impl LateLintPass<'_> for ImportRename { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - if let ItemKind::Use(path, UseKind::Single) = &item.kind { + if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind { for &res in &path.res { if let Res::Def(_, id) = res && let Some(name) = self.renames.get(&id) diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs index 675989156cad0..28dc242742842 100644 --- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs +++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs @@ -226,7 +226,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { && should_lint(cx, typeck_results, block) { // we intentionally only lint structs, see lint description - if let ItemKind::Struct(data, _) = &self_item.kind { + if let ItemKind::Struct(_, data, _) = &self_item.kind { check_struct(cx, typeck_results, block, self_ty, item, data); } } diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 2c578d816025f..8045ab97d3847 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { let attrs = cx.tcx.hir_attrs(it.hir_id()); check_missing_inline_attrs(cx, attrs, it.span, desc); }, - hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _generics, _bounds, trait_items) => { + hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _ident, _generics, _bounds, trait_items) => { // note: we need to check if the trait is exported so we can't use // `LateLintPass::check_trait_item` here. for tit in trait_items { diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs index fe8a02c64c660..b71dde9069184 100644 --- a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs +++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs @@ -37,12 +37,12 @@ declare_lint_pass!(NoMangleWithRustAbi => [NO_MANGLE_WITH_RUST_ABI]); impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if let ItemKind::Fn { sig: fn_sig, .. } = &item.kind + if let ItemKind::Fn { ident, sig: fn_sig, .. } = &item.kind && !item.span.from_expansion() { let attrs = cx.tcx.hir_attrs(item.hir_id()); let mut app = Applicability::MaybeIncorrect; - let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(item.ident.span.lo()), "..", &mut app); + let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(ident.span.lo()), "..", &mut app); for attr in attrs { if let Some(ident) = attr.ident() && ident.name == rustc_span::sym::no_mangle diff --git a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs index a82365f943181..8305bf345ef19 100644 --- a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs +++ b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs @@ -192,7 +192,7 @@ struct LazyInfo { impl LazyInfo { fn from_item(state: &NonStdLazyStatic, cx: &LateContext<'_>, item: &Item<'_>) -> Option { // Check if item is a `once_cell:sync::Lazy` static. - if let ItemKind::Static(ty, _, body_id) = item.kind + if let ItemKind::Static(_, ty, _, body_id) = item.kind && let Some(path_def_id) = path_def_id(cx, ty) && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind && state.once_cell_sync_lazy.contains(&path_def_id) diff --git a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs index fd21893232dbb..e4a9bf7a84812 100644 --- a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs +++ b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs @@ -58,7 +58,7 @@ impl PubUnderscoreFields { impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { // This lint only pertains to structs. - let ItemKind::Struct(variant_data, _) = &item.kind else { + let ItemKind::Struct(_, variant_data, _) = &item.kind else { return; }; diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 6a17b83b3d01b..3a5f44db8720a 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -52,7 +52,11 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { && is_not_macro_export(item) && !item.span.in_external_macro(cx.sess().source_map()) { - let span = item.span.with_hi(item.ident.span.hi()); + // FIXME: `DUMMY_SP` isn't right here, because it causes the + // resulting span to begin at the start of the file. + let span = item.span.with_hi( + item.kind.ident().map(|ident| ident.span.hi()).unwrap_or(rustc_span::DUMMY_SP.hi()) + ); let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id()); span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs index 8b2d597b9e323..534ba3a50c6b4 100644 --- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs +++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs @@ -73,7 +73,8 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { if let Some(self_def) = self_ty.ty_adt_def() && let Some(self_local_did) = self_def.did().as_local() && let Node::Item(x) = cx.tcx.hir_node_by_def_id(self_local_did) - && let type_name = x.ident.name.as_str().to_lowercase() + && let Some(type_ident) = x.kind.ident() + && let type_name = type_ident.name.as_str().to_lowercase() && (impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace('_', "") == type_name) { diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs index 82cc5155380ea..20bf3a0bff1c3 100644 --- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs +++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs @@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray { } fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { - if let ItemKind::Struct(data, _) = &item.kind + if let ItemKind::Struct(_, data, _) = &item.kind && let Some(last_field) = data.fields().last() && let field_ty = cx.tcx.normalize_erasing_regions( cx.typing_env(), diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index f961e1c4d1a36..fa36c9a21f65e 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { // special handling for self trait bounds as these are not considered generics // ie. trait Foo: Display {} if let Item { - kind: ItemKind::Trait(_, _, _, bounds, ..), + kind: ItemKind::Trait(_, _, _, _, bounds, ..), .. } = item { @@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { .. }) = segments.first() && let Some(Node::Item(Item { - kind: ItemKind::Trait(_, _, _, self_bounds, _), + kind: ItemKind::Trait(_, _, _, _, self_bounds, _), .. })) = cx.tcx.hir_get_if_local(*def_id) { diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 151a6f67437c0..2e974374c99e7 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -451,7 +451,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); match item.kind { - ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty( + ItemKind::Static(_, ty, _, _) | ItemKind::Const(_, ty, _, _) => self.check_ty( cx, ty, CheckTyContext { diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index be533ca915ed4..4f1a017522e40 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -454,7 +454,7 @@ fn item_has_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>) -> HasSaf let comment_start = match cx.tcx.parent_hir_node(item.hir_id()) { Node::Crate(parent_mod) => comment_start_before_item_in_mod(cx, parent_mod, parent_mod.spans.inner_span, item), Node::Item(parent_item) => { - if let ItemKind::Mod(parent_mod) = &parent_item.kind { + if let ItemKind::Mod(_, parent_mod) = &parent_item.kind { comment_start_before_item_in_mod(cx, parent_mod, parent_item.span, item) } else { // Doesn't support impls in this position. Pretend a comment was found. @@ -614,7 +614,7 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option { .. }) => maybe_global_var = true, Node::Item(hir::Item { - kind: ItemKind::Mod(_), + kind: ItemKind::Mod(..), span: item_span, .. }) => { diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs index 4158050f969a8..2b7d3dc0c90a9 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs @@ -130,9 +130,9 @@ impl LateLintPass<'_> for UnnecessaryBoxReturns { } fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - let ItemKind::Fn { sig, .. } = &item.kind else { + let ItemKind::Fn { ident, sig, .. } = &item.kind else { return; }; - self.check_fn_item(cx, sig.decl, item.owner_id.def_id, item.ident.name); + self.check_fn_item(cx, sig.decl, item.owner_id.def_id, ident.name); } } diff --git a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs index 2577f1ceaa2c0..14ac65cf4dfe1 100644 --- a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs +++ b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs @@ -60,9 +60,9 @@ impl_lint_pass!(UnusedTraitNames => [UNUSED_TRAIT_NAMES]); impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if !item.span.in_external_macro(cx.sess().source_map()) - && let ItemKind::Use(path, UseKind::Single) = item.kind + && let ItemKind::Use(path, UseKind::Single(ident)) = item.kind // Ignore imports that already use Underscore - && item.ident.name != kw::Underscore + && ident.name != kw::Underscore // Only check traits && let Some(Res::Def(DefKind::Trait, _)) = path.res.first() && cx.tcx.maybe_unused_trait_imports(()).contains(&item.owner_id.def_id) @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { && self.msrv.meets(cx, msrvs::UNDERSCORE_IMPORTS) && !is_from_proc_macro(cx, &last_segment.ident) { - let complete_span = last_segment.ident.span.to(item.ident.span); + let complete_span = last_segment.ident.span.to(ident.span); span_lint_and_sugg( cx, UNUSED_TRAIT_NAMES, diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index 3449468ef4804..8922478e71830 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -131,11 +131,11 @@ impl LateLintPass<'_> for UpperCaseAcronyms { return; } match it.kind { - ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) => { - check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive); + ItemKind::TyAlias(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Trait(_, _, ident, ..) => { + check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive); }, - ItemKind::Enum(ref enumdef, _) => { - check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive); + ItemKind::Enum(ident, ref enumdef, _) => { + check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive); // check enum variants separately because again we only want to lint on private enums and // the fn check_variant does not know about the vis of the enum of its variants enumdef.variants.iter().for_each(|variant| { diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 4f48fb3b8a969..004c840c3310b 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -242,14 +242,14 @@ fn fn_header_search_pat(header: FnHeader) -> Pat { fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) { let (start_pat, end_pat) = match &item.kind { - ItemKind::ExternCrate(_) => (Pat::Str("extern"), Pat::Str(";")), + ItemKind::ExternCrate(..) => (Pat::Str("extern"), Pat::Str(";")), ItemKind::Static(..) => (Pat::Str("static"), Pat::Str(";")), ItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")), ItemKind::Fn { sig, .. } => (fn_header_search_pat(sig.header), Pat::Str("")), ItemKind::ForeignMod { .. } => (Pat::Str("extern"), Pat::Str("}")), ItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")), ItemKind::Enum(..) => (Pat::Str("enum"), Pat::Str("}")), - ItemKind::Struct(VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")), + ItemKind::Struct(_, VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")), ItemKind::Struct(..) => (Pat::Str("struct"), Pat::Str(";")), ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")), ItemKind::Trait(_, Safety::Unsafe, ..) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 80613a51c1400..eb4e1a7722f3c 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -644,7 +644,7 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb let root_mod; let item_kind = match tcx.hir_node_by_def_id(local_id) { Node::Crate(r#mod) => { - root_mod = ItemKind::Mod(r#mod); + root_mod = ItemKind::Mod(Ident::dummy(), r#mod); &root_mod }, Node::Item(item) => &item.kind, @@ -661,10 +661,13 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb }; match item_kind { - ItemKind::Mod(r#mod) => r#mod + ItemKind::Mod(_, r#mod) => r#mod .item_ids .iter() - .filter_map(|&item_id| res(tcx.hir_item(item_id).ident, item_id.owner_id)) + .filter_map(|&item_id| { + let ident = tcx.hir_item(item_id).kind.ident()?; + res(ident, item_id.owner_id) + }) .collect(), ItemKind::Impl(r#impl) => r#impl .items @@ -1416,8 +1419,8 @@ pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { let parent_id = cx.tcx.hir_get_parent_item(expr.hir_id).def_id; match cx.tcx.hir_node_by_def_id(parent_id) { - Node::Item(Item { ident, .. }) - | Node::TraitItem(TraitItem { ident, .. }) + Node::Item(item) => item.kind.ident().map(|ident| ident.name), + Node::TraitItem(TraitItem { ident, .. }) | Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name), _ => None, } @@ -2634,7 +2637,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym for id in tcx.hir_module_free_items(module) { if matches!(tcx.def_kind(id.owner_id), DefKind::Const) && let item = tcx.hir_item(id) - && let ItemKind::Const(ty, _generics, _body) = item.kind + && let ItemKind::Const(ident, ty, _generics, _body) = item.kind { if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind { // We could also check for the type name `test::TestDescAndFn` @@ -2644,7 +2647,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym .iter() .any(|a| a.has_name(sym::rustc_test_marker)); if has_test_marker { - names.push(item.ident.name); + names.push(ident.name); } } } @@ -2668,10 +2671,10 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool { // function scope .any(|(_id, node)| { if let Node::Item(item) = node { - if let ItemKind::Fn { .. } = item.kind { + if let ItemKind::Fn { ident, .. } = item.kind { // Note that we have sorted the item names in the visitor, // so the binary_search gets the same as `contains`, but faster. - return names.binary_search(&item.ident.name).is_ok(); + return names.binary_search(&ident.name).is_ok(); } } false From c9d314773e3ece5e2ecbca5ac6ddf9184dbfafc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 17 Mar 2025 21:48:39 +0100 Subject: [PATCH 21/21] Small review improvements --- .github/workflows/ci.yml | 4 ++-- src/ci/citool/src/metrics.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aaae67c28bc70..25397006ee23c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -244,9 +244,9 @@ jobs: continue-on-error: true run: | if [ -f build/metrics.json ]; then - METRICS=build/metrics.json + METRICS=build/metrics.json elif [ -f obj/build/metrics.json ]; then - METRICS=obj/build/metrics.json + METRICS=obj/build/metrics.json else echo "No metrics.json found" exit 0 diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 263011a337089..086aa5009f341 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -57,9 +57,9 @@ pub fn download_auto_job_metrics( Ok(metrics) => Some(metrics), Err(error) => { eprintln!( - r#"Did not find metrics for job `{}` at `{}`: {error:?}. + r#"Did not find metrics for job `{}` at `{parent}`: {error:?}. Maybe it was newly added?"#, - job.name, parent + job.name ); None }