|
1 |
| -use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB}; |
| 1 | +use std::cell::OnceCell; |
2 | 2 |
|
3 | 3 | use rustc_data_structures::graph::WithNumNodes;
|
4 | 4 | use rustc_index::IndexVec;
|
5 |
| -use rustc_middle::mir::{ |
6 |
| - self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, |
7 |
| - TerminatorKind, |
8 |
| -}; |
9 |
| -use rustc_span::source_map::original_sp; |
| 5 | +use rustc_middle::mir::{self, AggregateKind, BasicBlock, Rvalue, Statement, StatementKind}; |
10 | 6 | use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol};
|
11 | 7 |
|
12 |
| -use std::cell::OnceCell; |
| 8 | +use super::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; |
| 9 | + |
| 10 | +mod from_mir; |
13 | 11 |
|
14 | 12 | pub(super) struct CoverageSpans {
|
15 | 13 | /// Map from BCBs to their list of coverage spans.
|
@@ -311,41 +309,6 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
|
311 | 309 | coverage_spans.to_refined_spans()
|
312 | 310 | }
|
313 | 311 |
|
314 |
| - fn mir_to_initial_sorted_coverage_spans(&self) -> Vec<CoverageSpan> { |
315 |
| - let mut initial_spans = |
316 |
| - Vec::<CoverageSpan>::with_capacity(self.mir_body.basic_blocks.len() * 2); |
317 |
| - for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() { |
318 |
| - initial_spans.extend(self.bcb_to_initial_coverage_spans(bcb, bcb_data)); |
319 |
| - } |
320 |
| - |
321 |
| - if initial_spans.is_empty() { |
322 |
| - // This can happen if, for example, the function is unreachable (contains only a |
323 |
| - // `BasicBlock`(s) with an `Unreachable` terminator). |
324 |
| - return initial_spans; |
325 |
| - } |
326 |
| - |
327 |
| - initial_spans.push(CoverageSpan::for_fn_sig(self.fn_sig_span)); |
328 |
| - |
329 |
| - initial_spans.sort_by(|a, b| { |
330 |
| - // First sort by span start. |
331 |
| - Ord::cmp(&a.span.lo(), &b.span.lo()) |
332 |
| - // If span starts are the same, sort by span end in reverse order. |
333 |
| - // This ensures that if spans A and B are adjacent in the list, |
334 |
| - // and they overlap but are not equal, then either: |
335 |
| - // - Span A extends further left, or |
336 |
| - // - Both have the same start and span A extends further right |
337 |
| - .then_with(|| Ord::cmp(&a.span.hi(), &b.span.hi()).reverse()) |
338 |
| - // If both spans are equal, sort the BCBs in dominator order, |
339 |
| - // so that dominating BCBs come before other BCBs they dominate. |
340 |
| - .then_with(|| self.basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb)) |
341 |
| - // If two spans are otherwise identical, put closure spans first, |
342 |
| - // as this seems to be what the refinement step expects. |
343 |
| - .then_with(|| Ord::cmp(&a.is_closure, &b.is_closure).reverse()) |
344 |
| - }); |
345 |
| - |
346 |
| - initial_spans |
347 |
| - } |
348 |
| - |
349 | 312 | /// Iterate through the sorted `CoverageSpan`s, and return the refined list of merged and
|
350 | 313 | /// de-duplicated `CoverageSpan`s.
|
351 | 314 | fn to_refined_spans(mut self) -> Vec<CoverageSpan> {
|
@@ -485,48 +448,6 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
|
485 | 448 | }
|
486 | 449 | }
|
487 | 450 |
|
488 |
| - // Generate a set of `CoverageSpan`s from the filtered set of `Statement`s and `Terminator`s of |
489 |
| - // the `BasicBlock`(s) in the given `BasicCoverageBlockData`. One `CoverageSpan` is generated |
490 |
| - // for each `Statement` and `Terminator`. (Note that subsequent stages of coverage analysis will |
491 |
| - // merge some `CoverageSpan`s, at which point a `CoverageSpan` may represent multiple |
492 |
| - // `Statement`s and/or `Terminator`s.) |
493 |
| - fn bcb_to_initial_coverage_spans( |
494 |
| - &self, |
495 |
| - bcb: BasicCoverageBlock, |
496 |
| - bcb_data: &'a BasicCoverageBlockData, |
497 |
| - ) -> Vec<CoverageSpan> { |
498 |
| - bcb_data |
499 |
| - .basic_blocks |
500 |
| - .iter() |
501 |
| - .flat_map(|&bb| { |
502 |
| - let data = &self.mir_body[bb]; |
503 |
| - data.statements |
504 |
| - .iter() |
505 |
| - .enumerate() |
506 |
| - .filter_map(move |(index, statement)| { |
507 |
| - filtered_statement_span(statement).map(|span| { |
508 |
| - CoverageSpan::for_statement( |
509 |
| - statement, |
510 |
| - function_source_span(span, self.body_span), |
511 |
| - span, |
512 |
| - bcb, |
513 |
| - bb, |
514 |
| - index, |
515 |
| - ) |
516 |
| - }) |
517 |
| - }) |
518 |
| - .chain(filtered_terminator_span(data.terminator()).map(|span| { |
519 |
| - CoverageSpan::for_terminator( |
520 |
| - function_source_span(span, self.body_span), |
521 |
| - span, |
522 |
| - bcb, |
523 |
| - bb, |
524 |
| - ) |
525 |
| - })) |
526 |
| - }) |
527 |
| - .collect() |
528 |
| - } |
529 |
| - |
530 | 451 | fn curr(&self) -> &CoverageSpan {
|
531 | 452 | self.some_curr
|
532 | 453 | .as_ref()
|
@@ -774,104 +695,3 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
|
774 | 695 | self.basic_coverage_blocks.dominates(dom_covspan.bcb, covspan.bcb)
|
775 | 696 | }
|
776 | 697 | }
|
777 |
| - |
778 |
| -/// If the MIR `Statement` has a span contributive to computing coverage spans, |
779 |
| -/// return it; otherwise return `None`. |
780 |
| -fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> { |
781 |
| - match statement.kind { |
782 |
| - // These statements have spans that are often outside the scope of the executed source code |
783 |
| - // for their parent `BasicBlock`. |
784 |
| - StatementKind::StorageLive(_) |
785 |
| - | StatementKind::StorageDead(_) |
786 |
| - // Coverage should not be encountered, but don't inject coverage coverage |
787 |
| - | StatementKind::Coverage(_) |
788 |
| - // Ignore `ConstEvalCounter`s |
789 |
| - | StatementKind::ConstEvalCounter |
790 |
| - // Ignore `Nop`s |
791 |
| - | StatementKind::Nop => None, |
792 |
| - |
793 |
| - // FIXME(#78546): MIR InstrumentCoverage - Can the source_info.span for `FakeRead` |
794 |
| - // statements be more consistent? |
795 |
| - // |
796 |
| - // FakeReadCause::ForGuardBinding, in this example: |
797 |
| - // match somenum { |
798 |
| - // x if x < 1 => { ... } |
799 |
| - // }... |
800 |
| - // The BasicBlock within the match arm code included one of these statements, but the span |
801 |
| - // for it covered the `1` in this source. The actual statements have nothing to do with that |
802 |
| - // source span: |
803 |
| - // FakeRead(ForGuardBinding, _4); |
804 |
| - // where `_4` is: |
805 |
| - // _4 = &_1; (at the span for the first `x`) |
806 |
| - // and `_1` is the `Place` for `somenum`. |
807 |
| - // |
808 |
| - // If and when the Issue is resolved, remove this special case match pattern: |
809 |
| - StatementKind::FakeRead(box (FakeReadCause::ForGuardBinding, _)) => None, |
810 |
| - |
811 |
| - // Retain spans from all other statements |
812 |
| - StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding` |
813 |
| - | StatementKind::Intrinsic(..) |
814 |
| - | StatementKind::Assign(_) |
815 |
| - | StatementKind::SetDiscriminant { .. } |
816 |
| - | StatementKind::Deinit(..) |
817 |
| - | StatementKind::Retag(_, _) |
818 |
| - | StatementKind::PlaceMention(..) |
819 |
| - | StatementKind::AscribeUserType(_, _) => { |
820 |
| - Some(statement.source_info.span) |
821 |
| - } |
822 |
| - } |
823 |
| -} |
824 |
| - |
825 |
| -/// If the MIR `Terminator` has a span contributive to computing coverage spans, |
826 |
| -/// return it; otherwise return `None`. |
827 |
| -fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> { |
828 |
| - match terminator.kind { |
829 |
| - // These terminators have spans that don't positively contribute to computing a reasonable |
830 |
| - // span of actually executed source code. (For example, SwitchInt terminators extracted from |
831 |
| - // an `if condition { block }` has a span that includes the executed block, if true, |
832 |
| - // but for coverage, the code region executed, up to *and* through the SwitchInt, |
833 |
| - // actually stops before the if's block.) |
834 |
| - TerminatorKind::Unreachable // Unreachable blocks are not connected to the MIR CFG |
835 |
| - | TerminatorKind::Assert { .. } |
836 |
| - | TerminatorKind::Drop { .. } |
837 |
| - | TerminatorKind::SwitchInt { .. } |
838 |
| - // For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`. |
839 |
| - | TerminatorKind::FalseEdge { .. } |
840 |
| - | TerminatorKind::Goto { .. } => None, |
841 |
| - |
842 |
| - // Call `func` operand can have a more specific span when part of a chain of calls |
843 |
| - | TerminatorKind::Call { ref func, .. } => { |
844 |
| - let mut span = terminator.source_info.span; |
845 |
| - if let mir::Operand::Constant(box constant) = func { |
846 |
| - if constant.span.lo() > span.lo() { |
847 |
| - span = span.with_lo(constant.span.lo()); |
848 |
| - } |
849 |
| - } |
850 |
| - Some(span) |
851 |
| - } |
852 |
| - |
853 |
| - // Retain spans from all other terminators |
854 |
| - TerminatorKind::UnwindResume |
855 |
| - | TerminatorKind::UnwindTerminate(_) |
856 |
| - | TerminatorKind::Return |
857 |
| - | TerminatorKind::Yield { .. } |
858 |
| - | TerminatorKind::GeneratorDrop |
859 |
| - | TerminatorKind::FalseUnwind { .. } |
860 |
| - | TerminatorKind::InlineAsm { .. } => { |
861 |
| - Some(terminator.source_info.span) |
862 |
| - } |
863 |
| - } |
864 |
| -} |
865 |
| - |
866 |
| -/// Returns an extrapolated span (pre-expansion[^1]) corresponding to a range |
867 |
| -/// within the function's body source. This span is guaranteed to be contained |
868 |
| -/// within, or equal to, the `body_span`. If the extrapolated span is not |
869 |
| -/// contained within the `body_span`, the `body_span` is returned. |
870 |
| -/// |
871 |
| -/// [^1]Expansions result from Rust syntax including macros, syntactic sugar, |
872 |
| -/// etc.). |
873 |
| -#[inline] |
874 |
| -fn function_source_span(span: Span, body_span: Span) -> Span { |
875 |
| - let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt()); |
876 |
| - if body_span.contains(original_span) { original_span } else { body_span } |
877 |
| -} |
0 commit comments