Auto merge of #119166 - GuillaumeGomez:rollup-qfgj76w, r=GuillaumeGomez
Rollup of 3 pull requests Successful merges: - #119115 (Update documentation for `--env` compilation flag) - #119155 (coverage: Check for `async fn` explicitly, without needing a heuristic) - #119159 (Update LLVM submodule) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
92ad4b433a
@ -68,32 +68,21 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) {
|
||||
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 @@ fn inject_counters(&'a mut self) {
|
||||
// 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 @@ fn inject_counters(&'a mut self) {
|
||||
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 @@ fn create_mappings_and_inject_coverage_statements(
|
||||
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>(
|
||||
|
@ -6,6 +6,7 @@
|
||||
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,
|
||||
|
@ -7,13 +7,22 @@
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,11 @@ The tracking issue for this feature is: [#118372](https://github.com/rust-lang/r
|
||||
------------------------
|
||||
|
||||
This option flag allows to specify environment variables value at compile time to be
|
||||
used by `env!` and `option_env!` macros.
|
||||
used by `env!` and `option_env!` macros. It also impacts `tracked_env::var` function
|
||||
from the `proc_macro` crate.
|
||||
|
||||
This information will be stored in the dep-info files. For more information about
|
||||
dep-info files, take a look [here](https://doc.rust-lang.org/cargo/guide/build-cache.html#dep-info-files).
|
||||
|
||||
When retrieving an environment variable value, the one specified by `--env` will take
|
||||
precedence. For example, if you want have `PATH=a` in your environment and pass:
|
||||
@ -20,6 +24,21 @@ Then you will have:
|
||||
assert_eq!(env!("PATH"), "env");
|
||||
```
|
||||
|
||||
It will trigger a new compilation if any of the `--env` argument value is different.
|
||||
So if you first passed:
|
||||
|
||||
```bash
|
||||
--env A=B --env X=12
|
||||
```
|
||||
|
||||
and then on next compilation:
|
||||
|
||||
```bash
|
||||
--env A=B
|
||||
```
|
||||
|
||||
`X` value is different (not set) so the code will be re-compiled.
|
||||
|
||||
Please note that on Windows, environment variables are case insensitive but case
|
||||
preserving whereas `rustc`'s environment variables are case sensitive. For example,
|
||||
having `Path` in your environment (case insensitive) is different than using
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 2c4de6c2492d5530de3f19f41d8f88ba984c2fe2
|
||||
Subproject commit 606bc11367b475542bd6228163424ca43b4dbdbc
|
32
tests/coverage/async_block.cov-map
Normal file
32
tests/coverage/async_block.cov-map
Normal file
@ -0,0 +1,32 @@
|
||||
Function name: async_block::main
|
||||
Raw bytes (38): 0x[01, 01, 02, 01, 05, 03, 05, 06, 01, 05, 01, 00, 0b, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 13, 05, 00, 14, 01, 16, 05, 07, 0a, 02, 06, 06, 03, 01, 00, 02]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 2
|
||||
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
|
||||
- expression 1 operands: lhs = Expression(0, Add), rhs = Counter(1)
|
||||
Number of file 0 mappings: 6
|
||||
- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 11)
|
||||
- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10)
|
||||
- Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 19)
|
||||
= (c0 + c1)
|
||||
- Code(Counter(1)) at (prev + 0, 20) to (start + 1, 22)
|
||||
- Code(Counter(1)) at (prev + 7, 10) to (start + 2, 6)
|
||||
- Code(Expression(1, Sub)) at (prev + 3, 1) to (start + 0, 2)
|
||||
= ((c0 + c1) - c1)
|
||||
|
||||
Function name: async_block::main::{closure#0}
|
||||
Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 07, 1c, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 07, 03, 09, 00, 0a]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 2
|
||||
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
|
||||
- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
|
||||
Number of file 0 mappings: 4
|
||||
- Code(Counter(0)) at (prev + 7, 28) to (start + 1, 23)
|
||||
- Code(Counter(1)) at (prev + 1, 24) to (start + 2, 14)
|
||||
- Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14)
|
||||
= (c0 - c1)
|
||||
- Code(Expression(1, Add)) at (prev + 3, 9) to (start + 0, 10)
|
||||
= (c1 + (c0 - c1))
|
||||
|
37
tests/coverage/async_block.coverage
Normal file
37
tests/coverage/async_block.coverage
Normal file
@ -0,0 +1,37 @@
|
||||
LL| |#![feature(coverage_attribute)]
|
||||
LL| |#![feature(noop_waker)]
|
||||
LL| |// edition: 2021
|
||||
LL| |
|
||||
LL| 1|fn main() {
|
||||
LL| 17| for i in 0..16 {
|
||||
^16
|
||||
LL| 16| let future = async {
|
||||
LL| 16| if i >= 12 {
|
||||
LL| 4| println!("big");
|
||||
LL| 12| } else {
|
||||
LL| 12| println!("small");
|
||||
LL| 12| }
|
||||
LL| 16| };
|
||||
LL| 16| executor::block_on(future);
|
||||
LL| 16| }
|
||||
LL| 1|}
|
||||
LL| |
|
||||
LL| |mod executor {
|
||||
LL| | use core::future::Future;
|
||||
LL| | use core::pin::pin;
|
||||
LL| | use core::task::{Context, Poll, Waker};
|
||||
LL| |
|
||||
LL| | #[coverage(off)]
|
||||
LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
|
||||
LL| | let mut future = pin!(future);
|
||||
LL| | let waker = Waker::noop();
|
||||
LL| | let mut context = Context::from_waker(&waker);
|
||||
LL| |
|
||||
LL| | loop {
|
||||
LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
|
||||
LL| | break val;
|
||||
LL| | }
|
||||
LL| | }
|
||||
LL| | }
|
||||
LL| |}
|
||||
|
35
tests/coverage/async_block.rs
Normal file
35
tests/coverage/async_block.rs
Normal file
@ -0,0 +1,35 @@
|
||||
#![feature(coverage_attribute)]
|
||||
#![feature(noop_waker)]
|
||||
// edition: 2021
|
||||
|
||||
fn main() {
|
||||
for i in 0..16 {
|
||||
let future = async {
|
||||
if i >= 12 {
|
||||
println!("big");
|
||||
} else {
|
||||
println!("small");
|
||||
}
|
||||
};
|
||||
executor::block_on(future);
|
||||
}
|
||||
}
|
||||
|
||||
mod executor {
|
||||
use core::future::Future;
|
||||
use core::pin::pin;
|
||||
use core::task::{Context, Poll, Waker};
|
||||
|
||||
#[coverage(off)]
|
||||
pub fn block_on<F: Future>(mut future: F) -> F::Output {
|
||||
let mut future = pin!(future);
|
||||
let waker = Waker::noop();
|
||||
let mut context = Context::from_waker(&waker);
|
||||
|
||||
loop {
|
||||
if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
|
||||
break val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user