diff options
Diffstat (limited to 'compiler/rustc_mir_transform/src')
| -rw-r--r-- | compiler/rustc_mir_transform/src/coverage/mod.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/coverage/spans.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/errors.rs | 8 |
4 files changed, 30 insertions, 44 deletions
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 709d1fdc21a..c5a3391286a 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -68,32 +68,21 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { struct Instrumentor<'a, 'tcx> { tcx: TyCtxt<'tcx>, mir_body: &'a mut mir::Body<'tcx>, - fn_sig_span: Span, - body_span: Span, - function_source_hash: u64, + hir_info: ExtractedHirInfo, basic_coverage_blocks: CoverageGraph, coverage_counters: CoverageCounters, } impl<'a, 'tcx> Instrumentor<'a, 'tcx> { fn new(tcx: TyCtxt<'tcx>, mir_body: &'a mut mir::Body<'tcx>) -> Self { - let hir_info @ ExtractedHirInfo { function_source_hash, fn_sig_span, body_span } = - extract_hir_info(tcx, mir_body.source.def_id().expect_local()); + let hir_info = extract_hir_info(tcx, mir_body.source.def_id().expect_local()); debug!(?hir_info, "instrumenting {:?}", mir_body.source.def_id()); let basic_coverage_blocks = CoverageGraph::from_mir(mir_body); let coverage_counters = CoverageCounters::new(&basic_coverage_blocks); - Self { - tcx, - mir_body, - fn_sig_span, - body_span, - function_source_hash, - basic_coverage_blocks, - coverage_counters, - } + Self { tcx, mir_body, hir_info, basic_coverage_blocks, coverage_counters } } fn inject_counters(&'a mut self) { @@ -101,8 +90,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { // Compute coverage spans from the `CoverageGraph`. let Some(coverage_spans) = CoverageSpans::generate_coverage_spans( self.mir_body, - self.fn_sig_span, - self.body_span, + &self.hir_info, &self.basic_coverage_blocks, ) else { // No relevant spans were found in MIR, so skip instrumenting this function. @@ -121,7 +109,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let mappings = self.create_mappings_and_inject_coverage_statements(&coverage_spans); self.mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { - function_source_hash: self.function_source_hash, + function_source_hash: self.hir_info.function_source_hash, num_counters: self.coverage_counters.num_counters(), expressions: self.coverage_counters.take_expressions(), mappings, @@ -136,7 +124,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { coverage_spans: &CoverageSpans, ) -> Vec<Mapping> { let source_map = self.tcx.sess.source_map(); - let body_span = self.body_span; + let body_span = self.hir_info.body_span; let source_file = source_map.lookup_source_file(body_span.lo()); use rustc_session::RemapFileNameExt; @@ -311,6 +299,7 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { #[derive(Debug)] struct ExtractedHirInfo { function_source_hash: u64, + is_async_fn: bool, fn_sig_span: Span, body_span: Span, } @@ -324,6 +313,7 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir hir::map::associated_body(hir_node).expect("HIR node is a function with body"); let hir_body = tcx.hir().body(fn_body_id); + let is_async_fn = hir_node.fn_sig().is_some_and(|fn_sig| fn_sig.header.is_async()); let body_span = get_body_span(tcx, hir_body, def_id); // The actual signature span is only used if it has the same context and @@ -345,7 +335,7 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir let function_source_hash = hash_mir_source(tcx, hir_body); - ExtractedHirInfo { function_source_hash, fn_sig_span, body_span } + ExtractedHirInfo { function_source_hash, is_async_fn, fn_sig_span, body_span } } fn get_body_span<'tcx>( diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 462e54c386c..ae43a18ad4e 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -6,6 +6,7 @@ use rustc_middle::mir; use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol, DUMMY_SP}; use super::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; +use crate::coverage::ExtractedHirInfo; mod from_mir; @@ -21,14 +22,12 @@ impl CoverageSpans { /// Returns `None` if no coverage-relevant spans could be extracted. pub(super) fn generate_coverage_spans( mir_body: &mir::Body<'_>, - fn_sig_span: Span, - body_span: Span, + hir_info: &ExtractedHirInfo, basic_coverage_blocks: &CoverageGraph, ) -> Option<Self> { let coverage_spans = CoverageSpansGenerator::generate_coverage_spans( mir_body, - fn_sig_span, - body_span, + hir_info, basic_coverage_blocks, ); @@ -230,19 +229,17 @@ impl<'a> CoverageSpansGenerator<'a> { /// to be). pub(super) fn generate_coverage_spans( mir_body: &mir::Body<'_>, - fn_sig_span: Span, // Ensured to be same SourceFile and SyntaxContext as `body_span` - body_span: Span, + hir_info: &ExtractedHirInfo, basic_coverage_blocks: &'a CoverageGraph, ) -> Vec<CoverageSpan> { let sorted_spans = from_mir::mir_to_initial_sorted_coverage_spans( mir_body, - fn_sig_span, - body_span, + hir_info, basic_coverage_blocks, ); let coverage_spans = Self { - body_span, + body_span: hir_info.body_span, basic_coverage_blocks, sorted_spans_iter: sorted_spans.into_iter(), some_curr: None, diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index eab9a9c98f8..a9c4ea33d0e 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -7,13 +7,22 @@ use rustc_span::Span; use crate::coverage::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; use crate::coverage::spans::CoverageSpan; +use crate::coverage::ExtractedHirInfo; pub(super) fn mir_to_initial_sorted_coverage_spans( mir_body: &mir::Body<'_>, - fn_sig_span: Span, - body_span: Span, + hir_info: &ExtractedHirInfo, basic_coverage_blocks: &CoverageGraph, ) -> Vec<CoverageSpan> { + let &ExtractedHirInfo { is_async_fn, fn_sig_span, body_span, .. } = hir_info; + if is_async_fn { + // An async function desugars into a function that returns a future, + // with the user code wrapped in a closure. Any spans in the desugared + // outer function will be unhelpful, so just produce a single span + // associating the function signature with its entry BCB. + return vec![CoverageSpan::for_fn_sig(fn_sig_span)]; + } + let mut initial_spans = Vec::with_capacity(mir_body.basic_blocks.len() * 2); for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() { initial_spans.extend(bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data)); @@ -44,16 +53,6 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( .then_with(|| Ord::cmp(&a.is_closure, &b.is_closure).reverse()) }); - // The desugaring of an async function includes a closure containing the - // original function body, and a terminator that returns the `impl Future`. - // That terminator will cause a confusing coverage count for the function's - // closing brace, so discard everything after the body closure span. - if let Some(body_closure_index) = - initial_spans.iter().rposition(|covspan| covspan.is_closure && covspan.span == body_span) - { - initial_spans.truncate(body_closure_index + 1); - } - initial_spans } diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index fd4af31501c..17916e16daf 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use rustc_errors::{ Applicability, DecorateLint, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, - DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic, + DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, Level, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; @@ -62,10 +62,10 @@ pub(crate) struct RequiresUnsafe { // so we need to eagerly translate the label here, which isn't supported by the derive API // We could also exhaustively list out the primary messages for all unsafe violations, // but this would result in a lot of duplication. -impl<'sess> IntoDiagnostic<'sess> for RequiresUnsafe { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe { #[track_caller] - fn into_diagnostic(self, dcx: &'sess DiagCtxt) -> DiagnosticBuilder<'sess, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::mir_transform_requires_unsafe); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe); diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); diag.set_span(self.span); diag.span_label(self.span, self.details.label()); |
