From 96ac5714455dfba4f3e090d4b2545cc00d96a097 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 19 Feb 2025 10:22:17 +0000 Subject: Move -Zcrate-attr injection to just after crate root parsing This way after_crate_root_parsing and -Zpretty will see them. --- compiler/rustc_interface/src/passes.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'compiler/rustc_interface/src') diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 8f6c5b47ee2..75d92ae7a2e 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -45,7 +45,7 @@ use crate::interface::Compiler; use crate::{errors, limits, proc_macro_decls, util}; pub fn parse<'a>(sess: &'a Session) -> ast::Crate { - let krate = sess + let mut krate = sess .time("parse_crate", || { let mut parser = unwrap_or_emit_fatal(match &sess.io.input { Input::File(file) => new_parser_from_file(&sess.psess, file, None), @@ -64,6 +64,12 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate { input_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1"); } + rustc_builtin_macros::cmdline_attrs::inject( + &mut krate, + &sess.psess, + &sess.opts.unstable_opts.crate_attr, + ); + krate } @@ -805,17 +811,11 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( compiler: &Compiler, - mut krate: rustc_ast::Crate, + krate: rustc_ast::Crate, f: F, ) -> T { let sess = &compiler.sess; - rustc_builtin_macros::cmdline_attrs::inject( - &mut krate, - &sess.psess, - &sess.opts.unstable_opts.crate_attr, - ); - let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs); let crate_name = get_crate_name(sess, &pre_configured_attrs); -- cgit 1.4.1-3-g733a5 From 3f526eeec4efe8a31154b7b20b64d99c1badce9e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 May 2025 23:25:57 +1000 Subject: coverage: Revert "unused local file IDs" due to empty function names This reverts commit 3b22c21dd8c30f499051fe7a758ca0e5d81eb638, reversing changes made to 5f292eea6d63abbd26f1e6e00a0b8cf21d828d7d. --- .../rustc_codegen_llvm/src/coverageinfo/ffi.rs | 26 +++---------- .../src/coverageinfo/mapgen/covfun.rs | 44 +++++----------------- .../src/coverageinfo/mapgen/spans.rs | 28 ++++++++++++-- compiler/rustc_interface/src/tests.rs | 3 +- compiler/rustc_mir_transform/src/coverage/spans.rs | 38 +------------------ compiler/rustc_session/src/config.rs | 5 --- compiler/rustc_session/src/options.rs | 1 - compiler/rustc_session/src/session.rs | 5 --- tests/coverage/async_closure.cov-map | 21 ++++++----- tests/coverage/unused-local-file.coverage | 7 ---- tests/coverage/unused-local-file.rs | 22 ----------- .../branch_match_arms.main.InstrumentCoverage.diff | 2 +- ...instrument_coverage.bar.InstrumentCoverage.diff | 2 +- ...nstrument_coverage.main.InstrumentCoverage.diff | 4 +- ..._coverage_cleanup.main.CleanupPostBorrowck.diff | 4 +- ...t_coverage_cleanup.main.InstrumentCoverage.diff | 4 +- 16 files changed, 62 insertions(+), 154 deletions(-) delete mode 100644 tests/coverage/unused-local-file.coverage delete mode 100644 tests/coverage/unused-local-file.rs (limited to 'compiler/rustc_interface/src') diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index c207df2fb0b..f6000e72840 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -155,20 +155,6 @@ pub(crate) struct Regions { impl Regions { /// Returns true if none of this structure's tables contain any regions. pub(crate) fn has_no_regions(&self) -> bool { - // Every region has a span, so if there are no spans then there are no regions. - self.all_cov_spans().next().is_none() - } - - pub(crate) fn all_cov_spans(&self) -> impl Iterator { - macro_rules! iter_cov_spans { - ( $( $regions:expr ),* $(,)? ) => { - std::iter::empty() - $( - .chain( $regions.iter().map(|region| ®ion.cov_span) ) - )* - } - } - let Self { code_regions, expansion_regions, @@ -177,13 +163,11 @@ impl Regions { mcdc_decision_regions, } = self; - iter_cov_spans!( - code_regions, - expansion_regions, - branch_regions, - mcdc_branch_regions, - mcdc_decision_regions, - ) + code_regions.is_empty() + && expansion_regions.is_empty() + && branch_regions.is_empty() + && mcdc_branch_regions.is_empty() + && mcdc_decision_regions.is_empty() } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index d3a815fabe7..7bdbc685952 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -11,7 +11,6 @@ use rustc_abi::Align; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods as _, ConstCodegenMethods, StaticCodegenMethods, }; -use rustc_index::IndexVec; use rustc_middle::mir::coverage::{ BasicCoverageBlock, CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping, MappingKind, Op, @@ -105,16 +104,6 @@ fn fill_region_tables<'tcx>( ids_info: &'tcx CoverageIdsInfo, covfun: &mut CovfunRecord<'tcx>, ) { - // If this function is unused, replace all counters with zero. - let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter { - let term = if covfun.is_used { - ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term") - } else { - CovTerm::Zero - }; - ffi::Counter::from_term(term) - }; - // Currently a function's mappings must all be in the same file, so use the // first mapping's span to determine the file. let source_map = tcx.sess.source_map(); @@ -126,12 +115,6 @@ fn fill_region_tables<'tcx>( let local_file_id = covfun.virtual_file_mapping.push_file(&source_file); - // If this testing flag is set, add an extra unused entry to the local - // file table, to help test the code for detecting unused file IDs. - if tcx.sess.coverage_inject_unused_local_file() { - covfun.virtual_file_mapping.push_file(&source_file); - } - // In rare cases, _all_ of a function's spans are discarded, and coverage // codegen needs to handle that gracefully to avoid #133606. // It's hard for tests to trigger this organically, so instead we set @@ -152,6 +135,16 @@ fn fill_region_tables<'tcx>( // For each counter/region pair in this function+file, convert it to a // form suitable for FFI. for &Mapping { ref kind, span } in &fn_cov_info.mappings { + // If this function is unused, replace all counters with zero. + let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter { + let term = if covfun.is_used { + ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term") + } else { + CovTerm::Zero + }; + ffi::Counter::from_term(term) + }; + let Some(coords) = make_coords(span) else { continue }; let cov_span = coords.make_coverage_span(local_file_id); @@ -184,19 +177,6 @@ fn fill_region_tables<'tcx>( } } -/// LLVM requires all local file IDs to have at least one mapping region. -/// If that's not the case, skip this function, to avoid an assertion failure -/// (or worse) in LLVM. -fn check_local_file_table(covfun: &CovfunRecord<'_>) -> bool { - let mut local_file_id_seen = - IndexVec::::from_elem_n(false, covfun.virtual_file_mapping.local_file_table.len()); - for cov_span in covfun.regions.all_cov_spans() { - local_file_id_seen[cov_span.file_id] = true; - } - - local_file_id_seen.into_iter().all(|seen| seen) -} - /// Generates the contents of the covfun record for this function, which /// contains the function's coverage mapping data. The record is then stored /// as a global variable in the `__llvm_covfun` section. @@ -205,10 +185,6 @@ pub(crate) fn generate_covfun_record<'tcx>( global_file_table: &GlobalFileTable, covfun: &CovfunRecord<'tcx>, ) { - if !check_local_file_table(covfun) { - return; - } - let &CovfunRecord { mangled_function_name, source_hash, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs index 574463be7ff..39a59560c9d 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs @@ -39,10 +39,7 @@ impl Coords { /// or other expansions), and if it does happen then skipping a span or function is /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span) -> Option { - if span.is_empty() { - debug_assert!(false, "can't make coords from empty span: {span:?}"); - return None; - } + let span = ensure_non_empty_span(source_map, span)?; let lo = span.lo(); let hi = span.hi(); @@ -73,6 +70,29 @@ pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span) }) } +fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option { + if !span.is_empty() { + return Some(span); + } + + // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'. + source_map + .span_to_source(span, |src, start, end| try { + // Adjusting span endpoints by `BytePos(1)` is normally a bug, + // but in this case we have specifically checked that the character + // we're skipping over is one of two specific ASCII characters, so + // adjusting by exactly 1 byte is correct. + if src.as_bytes().get(end).copied() == Some(b'{') { + Some(span.with_hi(span.hi() + BytePos(1))) + } else if start > 0 && src.as_bytes()[start - 1] == b'}' { + Some(span.with_lo(span.lo() - BytePos(1))) + } else { + None + } + }) + .ok()? +} + /// If `llvm-cov` sees a source region that is improperly ordered (end < start), /// it will immediately exit with a fatal error. To prevent that from happening, /// discard regions that are improperly ordered, or might be interpreted in a diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 20e081d3360..068d96c860f 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -776,8 +776,7 @@ fn test_unstable_options_tracking_hash() { CoverageOptions { level: CoverageLevel::Mcdc, no_mir_spans: true, - discard_all_spans_in_codegen: true, - inject_unused_local_file: true, + discard_all_spans_in_codegen: true } ); tracked!(crate_attr, vec!["abc".to_string()]); diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index ddeae093df5..ec76076020e 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,8 +1,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; use rustc_middle::ty::TyCtxt; -use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span}; +use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span}; use tracing::instrument; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; @@ -84,18 +83,8 @@ pub(super) fn extract_refined_covspans<'tcx>( // Discard any span that overlaps with a hole. discard_spans_overlapping_holes(&mut covspans, &holes); - // Discard spans that overlap in unwanted ways. + // Perform more refinement steps after holes have been dealt with. let mut covspans = remove_unwanted_overlapping_spans(covspans); - - // For all empty spans, either enlarge them to be non-empty, or discard them. - let source_map = tcx.sess.source_map(); - covspans.retain_mut(|covspan| { - let Some(span) = ensure_non_empty_span(source_map, covspan.span) else { return false }; - covspan.span = span; - true - }); - - // Merge covspans that can be merged. covspans.dedup_by(|b, a| a.merge_if_eligible(b)); code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| { @@ -241,26 +230,3 @@ fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering { // - Both have the same start and span A extends further right .then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse()) } - -fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option { - if !span.is_empty() { - return Some(span); - } - - // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'. - source_map - .span_to_source(span, |src, start, end| try { - // Adjusting span endpoints by `BytePos(1)` is normally a bug, - // but in this case we have specifically checked that the character - // we're skipping over is one of two specific ASCII characters, so - // adjusting by exactly 1 byte is correct. - if src.as_bytes().get(end).copied() == Some(b'{') { - Some(span.with_hi(span.hi() + BytePos(1))) - } else if start > 0 && src.as_bytes()[start - 1] == b'}' { - Some(span.with_lo(span.lo() - BytePos(1))) - } else { - None - } - }) - .ok()? -} diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 144aeb5c369..60e1b465ba9 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -195,11 +195,6 @@ pub struct CoverageOptions { /// regression tests for #133606, because we don't have an easy way to /// reproduce it from actual source code. pub discard_all_spans_in_codegen: bool, - - /// `-Zcoverage-options=inject-unused-local-file`: During codegen, add an - /// extra dummy entry to each function's local file table, to exercise the - /// code that checks for local file IDs with no mapping regions. - pub inject_unused_local_file: bool, } /// Controls whether branch coverage or MC/DC coverage is enabled. diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 3d9fdcbc7b1..5b4068740a1 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1413,7 +1413,6 @@ pub mod parse { "mcdc" => slot.level = CoverageLevel::Mcdc, "no-mir-spans" => slot.no_mir_spans = true, "discard-all-spans-in-codegen" => slot.discard_all_spans_in_codegen = true, - "inject-unused-local-file" => slot.inject_unused_local_file = true, _ => return false, } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 34ac37d6378..010ae42c280 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -371,11 +371,6 @@ impl Session { self.opts.unstable_opts.coverage_options.discard_all_spans_in_codegen } - /// True if testing flag `-Zcoverage-options=inject-unused-local-file` was passed. - pub fn coverage_inject_unused_local_file(&self) -> bool { - self.opts.unstable_opts.coverage_options.inject_unused_local_file - } - pub fn is_sanitizer_cfi_enabled(&self) -> bool { self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI) } diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map index 53128dd7a48..9f8dc8d6cbb 100644 --- a/tests/coverage/async_closure.cov-map +++ b/tests/coverage/async_closure.cov-map @@ -37,29 +37,32 @@ Number of file 0 mappings: 8 Highest counter ID seen: c0 Function name: async_closure::main::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24] Number of files: 1 - file 0 => $DIR/async_closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35) +- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36) Highest counter ID seen: c0 Function name: async_closure::main::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24] Number of files: 1 - file 0 => $DIR/async_closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35) +- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36) Highest counter ID seen: c0 Function name: async_closure::main::{closure#0}::{closure#0}:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24] Number of files: 1 - file 0 => $DIR/async_closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35) +- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36) Highest counter ID seen: c0 diff --git a/tests/coverage/unused-local-file.coverage b/tests/coverage/unused-local-file.coverage deleted file mode 100644 index 8f5a32f6d70..00000000000 --- a/tests/coverage/unused-local-file.coverage +++ /dev/null @@ -1,7 +0,0 @@ - LL| |//@ edition: 2021 - LL| | - LL| |// Force this function to be generated in its home crate, so that it ends up - LL| |// with normal coverage metadata. - LL| |#[inline(never)] - LL| 1|pub fn external_function() {} - diff --git a/tests/coverage/unused-local-file.rs b/tests/coverage/unused-local-file.rs deleted file mode 100644 index cf43c62d703..00000000000 --- a/tests/coverage/unused-local-file.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! If we give LLVM a local file table for a function, but some of the entries -//! in that table have no associated mapping regions, then an assertion failure -//! will occur in LLVM. We therefore need to detect and skip any function that -//! would trigger that assertion. -//! -//! To test that this case is handled, even before adding code that could allow -//! it to happen organically (for expansion region support), we use a special -//! testing-only flag to force it to occur. - -//@ edition: 2024 -//@ compile-flags: -Zcoverage-options=inject-unused-local-file - -// The `llvm-cov` tool will complain if the test binary ends up having no -// coverage metadata at all. To prevent that, we also link to instrumented -// code in an auxiliary crate that doesn't have the special flag set. - -//@ aux-build: discard_all_helper.rs -extern crate discard_all_helper; - -fn main() { - discard_all_helper::external_function(); -} diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index fa88211383a..d465b8bded2 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -40,7 +40,7 @@ + coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:18 (#0); + coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:23: 19:30 (#0); + coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:31: 19:32 (#0); -+ coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:1: 21:2 (#0); ++ coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0); + bb0: { + Coverage::VirtualCounter(bcb0); diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff index 9b6d2b22087..cf6d85abd80 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -6,7 +6,7 @@ + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:27:1: 27:17 (#0); + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:28:5: 28:9 (#0); -+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:1: 29:2 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:2: 29:2 (#0); + bb0: { + Coverage::VirtualCounter(bcb0); diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index b2bb2375aee..980c5e202ff 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -10,8 +10,8 @@ + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:10 (#0); + coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:15 (#0); + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0); -+ coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:9: 17:10 (#0); -+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:1: 19:2 (#0); ++ coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0); ++ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:2: 19:2 (#0); + bb0: { + Coverage::VirtualCounter(bcb0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff index 2eb78c08ee8..b707cd41788 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -10,8 +10,8 @@ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0); coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); - coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:38: 14:39 (#0); - coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:1: 15:2 (#0); + coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); bb0: { diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff index 0c1bc24b6dc..239b845c231 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -10,8 +10,8 @@ + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0); + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); + coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); -+ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:38: 14:39 (#0); -+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:1: 15:2 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); ++ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); + coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); + bb0: { -- cgit 1.4.1-3-g733a5 From c56a3093ea08395a5d928269249256a40b31d5db Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 30 May 2025 07:26:39 +0000 Subject: Merge coroutine obligation checking into borrowck parallel loop --- compiler/rustc_interface/src/passes.rs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'compiler/rustc_interface/src') diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 75d92ae7a2e..5bc7559d29a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1012,10 +1012,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { { tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id); } - }); - }); - sess.time("coroutine_obligations", || { - tcx.par_hir_body_owners(|def_id| { if tcx.is_coroutine(def_id.to_def_id()) { tcx.ensure_ok().mir_coroutine_witnesses(def_id); let _ = tcx.ensure_ok().check_coroutine_obligations( -- cgit 1.4.1-3-g733a5 From 685d1c9e2904813876f233622148838d3575b518 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 30 May 2025 15:06:51 +0000 Subject: Change a per-module query to just run on the items it internally filters for --- compiler/rustc_hir_typeck/src/lib.rs | 6 ++++- compiler/rustc_interface/src/passes.rs | 1 - compiler/rustc_middle/src/hooks/mod.rs | 5 ++++ compiler/rustc_middle/src/query/mod.rs | 4 --- compiler/rustc_passes/src/lib.rs | 2 +- compiler/rustc_passes/src/naked_functions.rs | 39 ++++++---------------------- 6 files changed, 19 insertions(+), 38 deletions(-) (limited to 'compiler/rustc_interface/src') diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 5a814822163..30651534d7b 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -55,8 +55,8 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config; -use rustc_span::Span; use rustc_span::def_id::LocalDefId; +use rustc_span::{Span, sym}; use tracing::{debug, instrument}; use typeck_root_ctxt::TypeckRootCtxt; @@ -170,6 +170,10 @@ fn typeck_with_inspect<'tcx>( .map(|(idx, ty)| fcx.normalize(arg_span(idx), ty)), ); + if tcx.has_attr(def_id, sym::naked) { + tcx.typeck_naked_fn(def_id, body); + } + check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params()); } else { let expected_type = if let Some(infer_ty) = infer_type_if_missing(&fcx, node) { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 75d92ae7a2e..696f4b493f2 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -960,7 +960,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { tcx.par_hir_for_each_module(|module| { tcx.ensure_ok().check_mod_loops(module); tcx.ensure_ok().check_mod_attrs(module); - tcx.ensure_ok().check_mod_naked_functions(module); tcx.ensure_ok().check_mod_unstable_api_usage(module); }); }, diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs index c5ce6efcb81..12110c36044 100644 --- a/compiler/rustc_middle/src/hooks/mod.rs +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -102,6 +102,11 @@ declare_hooks! { /// Ensure the given scalar is valid for the given type. /// This checks non-recursive runtime validity. hook validate_scalar_in_layout(scalar: crate::ty::ScalarInt, ty: Ty<'tcx>) -> bool; + + /// Naked fns can only have trivial binding patterns in arguments, + /// may not actually use those arguments, and the body must consist of just + /// a single asm statement. + hook typeck_naked_fn(def_id: LocalDefId, body: &'tcx rustc_hir::Body<'tcx>) -> (); } #[cold] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 279033ee072..bb0b0a41d5a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1119,10 +1119,6 @@ rustc_queries! { desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) } } - query check_mod_naked_functions(key: LocalModDefId) { - desc { |tcx| "checking naked functions in {}", describe_as_module(key, tcx) } - } - query check_mod_privacy(key: LocalModDefId) { desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) } } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index f9445485f60..aa4c56846c5 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -14,7 +14,7 @@ #![feature(try_blocks)] // tidy-alphabetical-end -use rustc_middle::query::Providers; +use rustc_middle::util::Providers; pub mod abi_test; mod check_attr; diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index e9e88424bcc..4397a323dfc 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -1,13 +1,12 @@ //! Checks validity of naked functions. use rustc_hir as hir; -use rustc_hir::def::DefKind; -use rustc_hir::def_id::{LocalDefId, LocalModDefId}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::Visitor; use rustc_hir::{ExprKind, HirIdSet, StmtKind}; -use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; +use rustc_middle::util::Providers; use rustc_span::{Span, sym}; use crate::errors::{ @@ -15,36 +14,14 @@ use crate::errors::{ }; pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { check_mod_naked_functions, ..*providers }; + providers.hooks.typeck_naked_fn = typeck_naked_fn; } -fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { - let items = tcx.hir_module_items(module_def_id); - for def_id in items.definitions() { - if !matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) { - continue; - } - - let body = match tcx.hir_node_by_def_id(def_id) { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn { body: body_id, .. }, .. - }) - | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)), - .. - }) - | hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(_, body_id), .. - }) => tcx.hir_body(*body_id), - _ => continue, - }; - - if tcx.has_attr(def_id, sym::naked) { - check_no_patterns(tcx, body.params); - check_no_parameters_use(tcx, body); - check_asm(tcx, def_id, body); - } - } +fn typeck_naked_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<'tcx>) { + debug_assert!(tcx.has_attr(def_id, sym::naked)); + check_no_patterns(tcx, body.params); + check_no_parameters_use(tcx, body); + check_asm(tcx, def_id, body); } /// Checks that parameters don't use patterns. Mirrors the checks for function declarations. -- cgit 1.4.1-3-g733a5 From 1e169d8dc406ff2eb5cd38b35053e2f50cbb0f54 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 1 Jun 2025 17:29:33 +0200 Subject: Optionally don't steal the THIR --- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_middle/src/query/mod.rs | 3 ++- compiler/rustc_mir_build/src/check_unsafety.rs | 16 +++++++++++++--- compiler/rustc_session/src/options.rs | 2 ++ .../unstable-book/src/compiler-flags/no-steal-thir.md | 7 +++++++ 5 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/no-steal-thir.md (limited to 'compiler/rustc_interface/src') diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 068d96c860f..558f13a832c 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -715,6 +715,7 @@ fn test_unstable_options_tracking_hash() { untracked!(no_analysis, true); untracked!(no_leak_check, true); untracked!(no_parallel_backend, true); + untracked!(no_steal_thir, true); untracked!(parse_crate_root_only, true); // `pre_link_arg` is omitted because it just forwards to `pre_link_args`. untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 279033ee072..542653efd30 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -535,7 +535,8 @@ rustc_queries! { separate_provide_extern } - /// Fetch the THIR for a given body. + /// Fetch the THIR for a given body. The THIR body gets stolen by unsafety checking unless + /// `-Zno-steal-thir` is on. query thir_body(key: LocalDefId) -> Result<(&'tcx Steal>, thir::ExprId), ErrorGuaranteed> { // Perf tests revealed that hashing THIR is inefficient (see #85729). no_hash diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 9d0681b19b9..d5061b71699 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -201,9 +201,14 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { /// Handle closures/coroutines/inline-consts, which is unsafecked with their parent body. fn visit_inner_body(&mut self, def: LocalDefId) { if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) { - // Runs all other queries that depend on THIR. + // Run all other queries that depend on THIR. self.tcx.ensure_done().mir_built(def); - let inner_thir = &inner_thir.steal(); + let inner_thir = if self.tcx.sess.opts.unstable_opts.no_steal_thir { + &inner_thir.borrow() + } else { + // We don't have other use for the THIR. Steal it to reduce memory usage. + &inner_thir.steal() + }; let hir_context = self.tcx.local_def_id_to_hir_id(def); let safety_context = mem::replace(&mut self.safety_context, SafetyContext::Safe); let mut inner_visitor = UnsafetyVisitor { @@ -1157,7 +1162,12 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { let Ok((thir, expr)) = tcx.thir_body(def) else { return }; // Runs all other queries that depend on THIR. tcx.ensure_done().mir_built(def); - let thir = &thir.steal(); + let thir = if tcx.sess.opts.unstable_opts.no_steal_thir { + &thir.borrow() + } else { + // We don't have other use for the THIR. Steal it to reduce memory usage. + &thir.steal() + }; let hir_id = tcx.local_def_id_to_hir_id(def); let safety_context = tcx.hir_fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 5b4068740a1..12fa05118ca 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2366,6 +2366,8 @@ options! { "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"), no_profiler_runtime: bool = (false, parse_no_value, [TRACKED], "prevent automatic injection of the profiler_builtins crate"), + no_steal_thir: bool = (false, parse_bool, [UNTRACKED], + "don't steal the THIR when we're done with it; useful for rustc drivers (default: no)"), no_trait_vptr: bool = (false, parse_no_value, [TRACKED], "disable generation of trait vptr in vtable for upcasting"), no_unique_section_names: bool = (false, parse_bool, [TRACKED], diff --git a/src/doc/unstable-book/src/compiler-flags/no-steal-thir.md b/src/doc/unstable-book/src/compiler-flags/no-steal-thir.md new file mode 100644 index 00000000000..d83677d1711 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/no-steal-thir.md @@ -0,0 +1,7 @@ +# `no-steal-thir` + +By default, to save on memory, the THIR body (obtained from the `tcx.thir_body` query) is stolen +once no longer used. This is inconvenient for authors of rustc drivers who want to access the THIR. + +This option disables the stealing. This has no observable effect on compiler behavior, only on +memory usage. -- cgit 1.4.1-3-g733a5 From 02a86dbd1d929b1235b57ef26198f95ec1d41e51 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Jun 2025 10:19:31 +1000 Subject: Remove pre-expansion AST stats. They're very little value, because they only measure the top-level `main.rs` or `lib.rs` file. (Other `.rs` files don't get read and parsed until expansion occurs.) I saw an example recently where the pre-expansion AST was 3KB in size and the post-expansion AST was 66MB. I kept the "POST EXPANSION" in the output header, I think that's useful information to avoid possible confusion about when the measurement happens. --- compiler/rustc_interface/src/passes.rs | 6 +- tests/ui/stats/input-stats.stderr | 177 +++++++++++---------------------- 2 files changed, 61 insertions(+), 122 deletions(-) (limited to 'compiler/rustc_interface/src') diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 75d92ae7a2e..ada3bf96a62 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -60,10 +60,6 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate { guar.raise_fatal(); }); - if sess.opts.unstable_opts.input_stats { - input_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1"); - } - rustc_builtin_macros::cmdline_attrs::inject( &mut krate, &sess.psess, @@ -298,7 +294,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let mut lint_buffer = resolver.lint_buffer.steal(); if sess.opts.unstable_opts.input_stats { - input_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats-2"); + input_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats"); } // Needs to go *after* expansion to be able to check the results of macro expansion. diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 58ab1a72556..f2598bd7eaf 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -1,120 +1,63 @@ -ast-stats-1 PRE EXPANSION AST STATS -ast-stats-1 Name Accumulated Size Count Item Size -ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Crate 40 (NN.N%) 1 40 -ast-stats-1 GenericArgs 40 (NN.N%) 1 40 -ast-stats-1 - AngleBracketed 40 (NN.N%) 1 -ast-stats-1 ExprField 48 (NN.N%) 1 48 -ast-stats-1 Attribute 64 (NN.N%) 2 32 -ast-stats-1 - DocComment 32 (NN.N%) 1 -ast-stats-1 - Normal 32 (NN.N%) 1 -ast-stats-1 WherePredicate 72 (NN.N%) 1 72 -ast-stats-1 - BoundPredicate 72 (NN.N%) 1 -ast-stats-1 ForeignItem 80 (NN.N%) 1 80 -ast-stats-1 - Fn 80 (NN.N%) 1 -ast-stats-1 Arm 96 (NN.N%) 2 48 -ast-stats-1 Local 96 (NN.N%) 1 96 -ast-stats-1 FnDecl 120 (NN.N%) 5 24 -ast-stats-1 Param 160 (NN.N%) 4 40 -ast-stats-1 Stmt 160 (NN.N%) 5 32 -ast-stats-1 - Let 32 (NN.N%) 1 -ast-stats-1 - MacCall 32 (NN.N%) 1 -ast-stats-1 - Expr 96 (NN.N%) 3 -ast-stats-1 Block 192 (NN.N%) 6 32 -ast-stats-1 FieldDef 208 (NN.N%) 2 104 -ast-stats-1 Variant 208 (NN.N%) 2 104 -ast-stats-1 AssocItem 320 (NN.N%) 4 80 -ast-stats-1 - Fn 160 (NN.N%) 2 -ast-stats-1 - Type 160 (NN.N%) 2 -ast-stats-1 GenericBound 352 (NN.N%) 4 88 -ast-stats-1 - Trait 352 (NN.N%) 4 -ast-stats-1 GenericParam 480 (NN.N%) 5 96 -ast-stats-1 Pat 504 (NN.N%) 7 72 -ast-stats-1 - Struct 72 (NN.N%) 1 -ast-stats-1 - Wild 72 (NN.N%) 1 -ast-stats-1 - Ident 360 (NN.N%) 5 -ast-stats-1 Expr 576 (NN.N%) 8 72 -ast-stats-1 - Match 72 (NN.N%) 1 -ast-stats-1 - Path 72 (NN.N%) 1 -ast-stats-1 - Struct 72 (NN.N%) 1 -ast-stats-1 - Lit 144 (NN.N%) 2 -ast-stats-1 - Block 216 (NN.N%) 3 -ast-stats-1 PathSegment 744 (NN.N%) 31 24 -ast-stats-1 Ty 896 (NN.N%) 14 64 -ast-stats-1 - Ptr 64 (NN.N%) 1 -ast-stats-1 - Ref 64 (NN.N%) 1 -ast-stats-1 - ImplicitSelf 128 (NN.N%) 2 -ast-stats-1 - Path 640 (NN.N%) 10 -ast-stats-1 Item 1_296 (NN.N%) 9 144 -ast-stats-1 - Enum 144 (NN.N%) 1 -ast-stats-1 - ForeignMod 144 (NN.N%) 1 -ast-stats-1 - Impl 144 (NN.N%) 1 -ast-stats-1 - Trait 144 (NN.N%) 1 -ast-stats-1 - Fn 288 (NN.N%) 2 -ast-stats-1 - Use 432 (NN.N%) 3 -ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_752 116 -ast-stats-1 -ast-stats-2 POST EXPANSION AST STATS -ast-stats-2 Name Accumulated Size Count Item Size -ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Crate 40 (NN.N%) 1 40 -ast-stats-2 GenericArgs 40 (NN.N%) 1 40 -ast-stats-2 - AngleBracketed 40 (NN.N%) 1 -ast-stats-2 ExprField 48 (NN.N%) 1 48 -ast-stats-2 WherePredicate 72 (NN.N%) 1 72 -ast-stats-2 - BoundPredicate 72 (NN.N%) 1 -ast-stats-2 ForeignItem 80 (NN.N%) 1 80 -ast-stats-2 - Fn 80 (NN.N%) 1 -ast-stats-2 Arm 96 (NN.N%) 2 48 -ast-stats-2 Local 96 (NN.N%) 1 96 -ast-stats-2 FnDecl 120 (NN.N%) 5 24 -ast-stats-2 InlineAsm 120 (NN.N%) 1 120 -ast-stats-2 Attribute 128 (NN.N%) 4 32 -ast-stats-2 - DocComment 32 (NN.N%) 1 -ast-stats-2 - Normal 96 (NN.N%) 3 -ast-stats-2 Param 160 (NN.N%) 4 40 -ast-stats-2 Stmt 160 (NN.N%) 5 32 -ast-stats-2 - Let 32 (NN.N%) 1 -ast-stats-2 - Semi 32 (NN.N%) 1 -ast-stats-2 - Expr 96 (NN.N%) 3 -ast-stats-2 Block 192 (NN.N%) 6 32 -ast-stats-2 FieldDef 208 (NN.N%) 2 104 -ast-stats-2 Variant 208 (NN.N%) 2 104 -ast-stats-2 AssocItem 320 (NN.N%) 4 80 -ast-stats-2 - Fn 160 (NN.N%) 2 -ast-stats-2 - Type 160 (NN.N%) 2 -ast-stats-2 GenericBound 352 (NN.N%) 4 88 -ast-stats-2 - Trait 352 (NN.N%) 4 -ast-stats-2 GenericParam 480 (NN.N%) 5 96 -ast-stats-2 Pat 504 (NN.N%) 7 72 -ast-stats-2 - Struct 72 (NN.N%) 1 -ast-stats-2 - Wild 72 (NN.N%) 1 -ast-stats-2 - Ident 360 (NN.N%) 5 -ast-stats-2 Expr 648 (NN.N%) 9 72 -ast-stats-2 - InlineAsm 72 (NN.N%) 1 -ast-stats-2 - Match 72 (NN.N%) 1 -ast-stats-2 - Path 72 (NN.N%) 1 -ast-stats-2 - Struct 72 (NN.N%) 1 -ast-stats-2 - Lit 144 (NN.N%) 2 -ast-stats-2 - Block 216 (NN.N%) 3 -ast-stats-2 PathSegment 864 (NN.N%) 36 24 -ast-stats-2 Ty 896 (NN.N%) 14 64 -ast-stats-2 - Ptr 64 (NN.N%) 1 -ast-stats-2 - Ref 64 (NN.N%) 1 -ast-stats-2 - ImplicitSelf 128 (NN.N%) 2 -ast-stats-2 - Path 640 (NN.N%) 10 -ast-stats-2 Item 1_584 (NN.N%) 11 144 -ast-stats-2 - Enum 144 (NN.N%) 1 -ast-stats-2 - ExternCrate 144 (NN.N%) 1 -ast-stats-2 - ForeignMod 144 (NN.N%) 1 -ast-stats-2 - Impl 144 (NN.N%) 1 -ast-stats-2 - Trait 144 (NN.N%) 1 -ast-stats-2 - Fn 288 (NN.N%) 2 -ast-stats-2 - Use 576 (NN.N%) 4 -ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_416 127 -ast-stats-2 +ast-stats POST EXPANSION AST STATS +ast-stats Name Accumulated Size Count Item Size +ast-stats ---------------------------------------------------------------- +ast-stats Crate 40 (NN.N%) 1 40 +ast-stats GenericArgs 40 (NN.N%) 1 40 +ast-stats - AngleBracketed 40 (NN.N%) 1 +ast-stats ExprField 48 (NN.N%) 1 48 +ast-stats WherePredicate 72 (NN.N%) 1 72 +ast-stats - BoundPredicate 72 (NN.N%) 1 +ast-stats ForeignItem 80 (NN.N%) 1 80 +ast-stats - Fn 80 (NN.N%) 1 +ast-stats Arm 96 (NN.N%) 2 48 +ast-stats Local 96 (NN.N%) 1 96 +ast-stats FnDecl 120 (NN.N%) 5 24 +ast-stats InlineAsm 120 (NN.N%) 1 120 +ast-stats Attribute 128 (NN.N%) 4 32 +ast-stats - DocComment 32 (NN.N%) 1 +ast-stats - Normal 96 (NN.N%) 3 +ast-stats Param 160 (NN.N%) 4 40 +ast-stats Stmt 160 (NN.N%) 5 32 +ast-stats - Let 32 (NN.N%) 1 +ast-stats - Semi 32 (NN.N%) 1 +ast-stats - Expr 96 (NN.N%) 3 +ast-stats Block 192 (NN.N%) 6 32 +ast-stats FieldDef 208 (NN.N%) 2 104 +ast-stats Variant 208 (NN.N%) 2 104 +ast-stats AssocItem 320 (NN.N%) 4 80 +ast-stats - Fn 160 (NN.N%) 2 +ast-stats - Type 160 (NN.N%) 2 +ast-stats GenericBound 352 (NN.N%) 4 88 +ast-stats - Trait 352 (NN.N%) 4 +ast-stats GenericParam 480 (NN.N%) 5 96 +ast-stats Pat 504 (NN.N%) 7 72 +ast-stats - Struct 72 (NN.N%) 1 +ast-stats - Wild 72 (NN.N%) 1 +ast-stats - Ident 360 (NN.N%) 5 +ast-stats Expr 648 (NN.N%) 9 72 +ast-stats - InlineAsm 72 (NN.N%) 1 +ast-stats - Match 72 (NN.N%) 1 +ast-stats - Path 72 (NN.N%) 1 +ast-stats - Struct 72 (NN.N%) 1 +ast-stats - Lit 144 (NN.N%) 2 +ast-stats - Block 216 (NN.N%) 3 +ast-stats PathSegment 864 (NN.N%) 36 24 +ast-stats Ty 896 (NN.N%) 14 64 +ast-stats - Ptr 64 (NN.N%) 1 +ast-stats - Ref 64 (NN.N%) 1 +ast-stats - ImplicitSelf 128 (NN.N%) 2 +ast-stats - Path 640 (NN.N%) 10 +ast-stats Item 1_584 (NN.N%) 11 144 +ast-stats - Enum 144 (NN.N%) 1 +ast-stats - ExternCrate 144 (NN.N%) 1 +ast-stats - ForeignMod 144 (NN.N%) 1 +ast-stats - Impl 144 (NN.N%) 1 +ast-stats - Trait 144 (NN.N%) 1 +ast-stats - Fn 288 (NN.N%) 2 +ast-stats - Use 576 (NN.N%) 4 +ast-stats ---------------------------------------------------------------- +ast-stats Total 7_416 127 +ast-stats hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size hir-stats ---------------------------------------------------------------- -- cgit 1.4.1-3-g733a5 From 8a0fdbd4071eee08034d9ae8c83d13666a6a872e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 3 Jun 2025 07:54:47 +0000 Subject: Move coroutine_by_move_body_def_id into the big check_crate body owner loop --- compiler/rustc_hir_analysis/src/lib.rs | 9 +++++++-- compiler/rustc_interface/src/passes.rs | 7 ------- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'compiler/rustc_interface/src') diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index a64c24f5455..39a3f427c0b 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -194,10 +194,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) { let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(()); }); - // Make sure we evaluate all static and (non-associated) const items, even if unused. - // If any of these fail to evaluate, we do not want this crate to pass compilation. tcx.par_hir_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); + // Make sure we evaluate all static and (non-associated) const items, even if unused. + // If any of these fail to evaluate, we do not want this crate to pass compilation. match def_kind { DefKind::Static { .. } => { tcx.ensure_ok().eval_static_initializer(item_def_id); @@ -217,6 +217,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) { if !matches!(def_kind, DefKind::AnonConst) { tcx.ensure_ok().typeck(item_def_id); } + // Ensure we generate the new `DefId` before finishing `check_crate`. + // Afterwards we freeze the list of `DefId`s. + if tcx.needs_coroutine_by_move_body_def_id(item_def_id.to_def_id()) { + tcx.ensure_done().coroutine_by_move_body_def_id(item_def_id); + } }); if tcx.features().rustc_attrs() { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 5bc7559d29a..b1db5d25760 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -981,13 +981,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { }); rustc_hir_analysis::check_crate(tcx); - sess.time("MIR_coroutine_by_move_body", || { - tcx.par_hir_body_owners(|def_id| { - if tcx.needs_coroutine_by_move_body_def_id(def_id.to_def_id()) { - tcx.ensure_done().coroutine_by_move_body_def_id(def_id); - } - }); - }); // Freeze definitions as we don't add new ones at this point. // We need to wait until now since we synthesize a by-move body // for all coroutine-closures. -- cgit 1.4.1-3-g733a5 From dff8ee5b01b7251937860da41afd55958c13456a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 5 Jun 2025 16:53:12 +0000 Subject: Replace all uses of sysroot_candidates with get_or_default_sysroot Before this change we had two different ways to attempt to locate the sysroot which are inconsistently used: * get_or_default_sysroot which tries to locate based on the 0th cli argument and if that doesn't work falls back to locating it using the librustc_driver.so location and returns a single path., * sysroot_candidates which takes the former and additionally does another attempt at locating using librustc_driver.so except without linux multiarch handling and then returns both paths., The latter was originally introduced to be able to locate the codegen backend back when cg_llvm was dynamically linked even for a custom driver when the --sysroot passed in does not contain a copy of cg_llvm. Back then get_or_default_sysroot did not attempt to locate the sysroot based on the location of librustc_driver.so yet. Because that is now done, the only case where removing sysroot_candidates can break things is if you have a custom driver inside what looks like a sysroot including the lib/rustlib directory, but which is missing some parts of the full sysroot like eg rust-lld. --- compiler/rustc_error_messages/src/lib.rs | 4 ++-- compiler/rustc_interface/src/interface.rs | 4 ++-- compiler/rustc_interface/src/util.rs | 11 +++++----- compiler/rustc_session/src/filesearch.rs | 36 ++++++------------------------- compiler/rustc_session/src/session.rs | 6 +----- 5 files changed, 17 insertions(+), 44 deletions(-) (limited to 'compiler/rustc_interface/src') diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 3c6df147b1b..a1f787b00d9 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -107,7 +107,7 @@ impl From> for TranslationBundleError { #[instrument(level = "trace")] pub fn fluent_bundle( sysroot: PathBuf, - sysroot_candidates: Vec, + default_sysroot: PathBuf, requested_locale: Option, additional_ftl_path: Option<&Path>, with_directionality_markers: bool, @@ -141,7 +141,7 @@ pub fn fluent_bundle( // If the user requests the default locale then don't try to load anything. if let Some(requested_locale) = requested_locale { let mut found_resources = false; - for mut sysroot in Some(sysroot).into_iter().chain(sysroot_candidates.into_iter()) { + for mut sysroot in [sysroot, default_sysroot] { sysroot.push("share"); sysroot.push("locale"); sysroot.push(requested_locale.to_string()); diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index cf494f8d686..068b8c6d044 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -18,7 +18,7 @@ use rustc_parse::parser::attr::AllowLeadingUnsafe; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; -use rustc_session::filesearch::sysroot_candidates; +use rustc_session::filesearch::get_or_default_sysroot; use rustc_session::parse::ParseSess; use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint}; use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs}; @@ -443,7 +443,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let bundle = match rustc_errors::fluent_bundle( config.opts.sysroot.clone(), - sysroot_candidates().to_vec(), + get_or_default_sysroot(), config.opts.unstable_opts.translate_lang.clone(), config.opts.unstable_opts.translate_additional_ftl.as_deref(), config.opts.unstable_opts.translate_directionality_markers, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 087b11fdf9d..f769c6156ae 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -2,7 +2,7 @@ use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, OnceLock}; -use std::{env, iter, thread}; +use std::{env, thread}; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; @@ -12,7 +12,6 @@ use rustc_metadata::{DylibError, load_symbol_from_dylib}; use rustc_middle::ty::CurrentGcx; use rustc_parse::validate_attr; use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, host_tuple}; -use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer}; use rustc_session::output::{CRATE_TYPES, categorize_crate_type}; use rustc_session::{EarlyDiagCtxt, Session, filesearch}; @@ -346,7 +345,7 @@ pub fn rustc_path<'a>() -> Option<&'a Path> { } fn get_rustc_path_inner(bin_path: &str) -> Option { - sysroot_candidates().iter().find_map(|sysroot| { + Some(filesearch::get_or_default_sysroot()).iter().find_map(|sysroot| { let candidate = sysroot.join(bin_path).join(if cfg!(target_os = "windows") { "rustc.exe" } else { @@ -374,10 +373,10 @@ fn get_codegen_sysroot( ); let target = host_tuple(); - let sysroot_candidates = sysroot_candidates(); + let sysroot_candidates = filesearch::sysroot_with_fallback(&sysroot); - let sysroot = iter::once(sysroot) - .chain(sysroot_candidates.iter().map(<_>::as_ref)) + let sysroot = sysroot_candidates + .iter() .map(|sysroot| { filesearch::make_target_lib_path(sysroot, target).with_file_name("codegen-backends") }) diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 1fd74c914b2..def2cc97f06 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -182,35 +182,13 @@ fn current_dll_path() -> Result { Err("current_dll_path is not supported on WASI".to_string()) } -pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> { - let mut sysroot_candidates: SmallVec<[PathBuf; 2]> = smallvec![get_or_default_sysroot()]; - if let Ok(dll) = current_dll_path() { - // use `parent` twice to chop off the file name and then also the - // directory containing the dll which should be either `lib` or `bin`. - if let Some(path) = dll.parent().and_then(|p| p.parent()) { - // The original `path` pointed at the `rustc_driver` crate's dll. - // Now that dll should only be in one of two locations. The first is - // in the compiler's libdir, for example `$sysroot/lib/*.dll`. The - // other is the target's libdir, for example - // `$sysroot/lib/rustlib/$target/lib/*.dll`. - // - // We don't know which, so let's assume that if our `path` above - // ends in `$target` we *could* be in the target libdir, and always - // assume that we may be in the main libdir. - sysroot_candidates.push(path.to_owned()); - - if path.ends_with(crate::config::host_tuple()) { - sysroot_candidates.extend( - path.parent() // chop off `$target` - .and_then(|p| p.parent()) // chop off `rustlib` - .and_then(|p| p.parent()) // chop off `lib` - .map(|s| s.to_owned()), - ); - } - } +pub fn sysroot_with_fallback(sysroot: &Path) -> SmallVec<[PathBuf; 2]> { + let mut candidates = smallvec![sysroot.to_owned()]; + let default_sysroot = get_or_default_sysroot(); + if default_sysroot != sysroot { + candidates.push(default_sysroot); } - - sysroot_candidates + candidates } /// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none. @@ -236,7 +214,7 @@ pub fn get_or_default_sysroot() -> PathBuf { dll.display() ))?; - // if `dir` points target's dir, move up to the sysroot + // if `dir` points to target's dir, move up to the sysroot let mut sysroot_dir = if dir.ends_with(crate::config::host_tuple()) { dir.parent() // chop off `$target` .and_then(|p| p.parent()) // chop off `rustlib` diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 010ae42c280..6b85e0abc86 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -458,13 +458,9 @@ impl Session { /// directories are also returned, for example if `--sysroot` is used but tools are missing /// (#125246): we also add the bin directories to the sysroot where rustc is located. pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec { - let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_tuple()); - let fallback_sysroot_paths = filesearch::sysroot_candidates() + let search_paths = filesearch::sysroot_with_fallback(&self.sysroot) .into_iter() - // Ignore sysroot candidate if it was the same as the sysroot path we just used. - .filter(|sysroot| *sysroot != self.sysroot) .map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_tuple())); - let search_paths = std::iter::once(bin_path).chain(fallback_sysroot_paths); if self_contained { // The self-contained tools are expected to be e.g. in `bin/self-contained` in the -- cgit 1.4.1-3-g733a5 From e4c4c4c677f00a35aef0cfbe5e5ab3b30eafda4c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 6 Jun 2025 14:20:48 +0000 Subject: Fix review comments --- Cargo.lock | 1 + compiler/rustc_error_messages/Cargo.toml | 1 + compiler/rustc_error_messages/src/lib.rs | 6 +++--- compiler/rustc_interface/src/interface.rs | 5 ++--- compiler/rustc_interface/src/util.rs | 12 ++++-------- 5 files changed, 11 insertions(+), 14 deletions(-) (limited to 'compiler/rustc_interface/src') diff --git a/Cargo.lock b/Cargo.lock index 43f5f40925b..b9258fb1855 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3640,6 +3640,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "smallvec", "tracing", "unic-langid", ] diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml index 0951859fa53..5dc582b9c3a 100644 --- a/compiler/rustc_error_messages/Cargo.toml +++ b/compiler/rustc_error_messages/Cargo.toml @@ -16,6 +16,7 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } +smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" unic-langid = { version = "0.9.0", features = ["macros"] } # tidy-alphabetical-end diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index a1f787b00d9..1d3b5b20751 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -21,6 +21,7 @@ use intl_memoizer::concurrent::IntlLangMemoizer; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_macros::{Decodable, Encodable}; use rustc_span::Span; +use smallvec::SmallVec; use tracing::{instrument, trace}; pub use unic_langid::{LanguageIdentifier, langid}; @@ -106,8 +107,7 @@ impl From> for TranslationBundleError { /// (overriding any conflicting messages). #[instrument(level = "trace")] pub fn fluent_bundle( - sysroot: PathBuf, - default_sysroot: PathBuf, + sysroot_candidates: SmallVec<[PathBuf; 2]>, requested_locale: Option, additional_ftl_path: Option<&Path>, with_directionality_markers: bool, @@ -141,7 +141,7 @@ pub fn fluent_bundle( // If the user requests the default locale then don't try to load anything. if let Some(requested_locale) = requested_locale { let mut found_resources = false; - for mut sysroot in [sysroot, default_sysroot] { + for mut sysroot in sysroot_candidates { sysroot.push("share"); sysroot.push("locale"); sysroot.push(requested_locale.to_string()); diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 068b8c6d044..e824e9d4aa9 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -18,7 +18,7 @@ use rustc_parse::parser::attr::AllowLeadingUnsafe; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; -use rustc_session::filesearch::get_or_default_sysroot; +use rustc_session::filesearch::sysroot_with_fallback; use rustc_session::parse::ParseSess; use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint}; use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs}; @@ -442,8 +442,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let bundle = match rustc_errors::fluent_bundle( - config.opts.sysroot.clone(), - get_or_default_sysroot(), + sysroot_with_fallback(&config.opts.sysroot), config.opts.unstable_opts.translate_lang.clone(), config.opts.unstable_opts.translate_additional_ftl.as_deref(), config.opts.unstable_opts.translate_directionality_markers, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index f769c6156ae..8bdc24d47d9 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -345,14 +345,10 @@ pub fn rustc_path<'a>() -> Option<&'a Path> { } fn get_rustc_path_inner(bin_path: &str) -> Option { - Some(filesearch::get_or_default_sysroot()).iter().find_map(|sysroot| { - let candidate = sysroot.join(bin_path).join(if cfg!(target_os = "windows") { - "rustc.exe" - } else { - "rustc" - }); - candidate.exists().then_some(candidate) - }) + let candidate = filesearch::get_or_default_sysroot() + .join(bin_path) + .join(if cfg!(target_os = "windows") { "rustc.exe" } else { "rustc" }); + candidate.exists().then_some(candidate) } #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable -- cgit 1.4.1-3-g733a5