From 1367104cb22ba5e9f8bc95c7bc719a12dc80d2c6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Aug 2023 11:52:37 +1000 Subject: [PATCH 1/3] Add tool `src/tools/coverage-dump` for use by some new coverage tests --- Cargo.lock | 18 ++ Cargo.toml | 1 + src/bootstrap/builder.rs | 3 +- src/bootstrap/tool.rs | 1 + src/tools/coverage-dump/Cargo.toml | 14 + src/tools/coverage-dump/README.md | 8 + src/tools/coverage-dump/src/covfun.rs | 296 ++++++++++++++++++++ src/tools/coverage-dump/src/main.rs | 17 ++ src/tools/coverage-dump/src/parser.rs | 80 ++++++ src/tools/coverage-dump/src/parser/tests.rs | 38 +++ src/tools/coverage-dump/src/prf_names.rs | 87 ++++++ 11 files changed, 562 insertions(+), 1 deletion(-) create mode 100644 src/tools/coverage-dump/Cargo.toml create mode 100644 src/tools/coverage-dump/README.md create mode 100644 src/tools/coverage-dump/src/covfun.rs create mode 100644 src/tools/coverage-dump/src/main.rs create mode 100644 src/tools/coverage-dump/src/parser.rs create mode 100644 src/tools/coverage-dump/src/parser/tests.rs create mode 100644 src/tools/coverage-dump/src/prf_names.rs diff --git a/Cargo.lock b/Cargo.lock index bdbafb8623bb8..35a9fdccf9cdc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -722,6 +722,18 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +[[package]] +name = "coverage-dump" +version = "0.1.0" +dependencies = [ + "anyhow", + "leb128", + "md-5", + "miniz_oxide", + "regex", + "rustc-demangle", +] + [[package]] name = "coverage_test_macros" version = "0.0.0" @@ -2041,6 +2053,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + [[package]] name = "levenshtein" version = "1.0.5" diff --git a/Cargo.toml b/Cargo.toml index d2e84d5426f9f..9b11ae8744b4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ members = [ "src/tools/generate-windows-sys", "src/tools/rustdoc-gui-test", "src/tools/opt-dist", + "src/tools/coverage-dump", ] exclude = [ diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b366619285338..73c0a192cef94 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -703,7 +703,8 @@ impl<'a> Builder<'a> { llvm::Lld, llvm::CrtBeginEnd, tool::RustdocGUITest, - tool::OptimizedDist + tool::OptimizedDist, + tool::CoverageDump, ), Kind::Check | Kind::Clippy | Kind::Fix => describe!( check::Std, diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 07ff3da6b4aa5..f094dd9d7c90b 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -306,6 +306,7 @@ bootstrap_tool!( GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys"; RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test"; OptimizedDist, "src/tools/opt-dist", "opt-dist"; + CoverageDump, "src/tools/coverage-dump", "coverage-dump"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] diff --git a/src/tools/coverage-dump/Cargo.toml b/src/tools/coverage-dump/Cargo.toml new file mode 100644 index 0000000000000..7f14286b5d0c4 --- /dev/null +++ b/src/tools/coverage-dump/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "coverage-dump" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.71" +leb128 = "0.2.5" +md5 = { package = "md-5" , version = "0.10.5" } +miniz_oxide = "0.7.1" +regex = "1.8.4" +rustc-demangle = "0.1.23" diff --git a/src/tools/coverage-dump/README.md b/src/tools/coverage-dump/README.md new file mode 100644 index 0000000000000..e2625d5adf27e --- /dev/null +++ b/src/tools/coverage-dump/README.md @@ -0,0 +1,8 @@ +This tool extracts coverage mapping information from an LLVM IR assembly file +(`.ll`), and prints it in a more human-readable form that can be used for +snapshot tests. + +The output format is mostly arbitrary, so it's OK to change the output as long +as any affected tests are also re-blessed. However, the output should be +consistent across different executions on different platforms, so avoid +printing any information that is platform-specific or non-deterministic. diff --git a/src/tools/coverage-dump/src/covfun.rs b/src/tools/coverage-dump/src/covfun.rs new file mode 100644 index 0000000000000..3a5866dea3e05 --- /dev/null +++ b/src/tools/coverage-dump/src/covfun.rs @@ -0,0 +1,296 @@ +use crate::parser::{unescape_llvm_string_contents, Parser}; +use anyhow::{anyhow, Context}; +use regex::Regex; +use std::collections::HashMap; +use std::fmt::{self, Debug, Write as _}; +use std::sync::OnceLock; + +pub(crate) fn dump_covfun_mappings( + llvm_ir: &str, + function_names: &HashMap, +) -> anyhow::Result<()> { + // Extract function coverage entries from the LLVM IR assembly, and associate + // each entry with its (demangled) name. + let mut covfun_entries = llvm_ir + .lines() + .filter_map(covfun_line_data) + .map(|line_data| (function_names.get(&line_data.name_hash).map(String::as_str), line_data)) + .collect::>(); + covfun_entries.sort_by(|a, b| { + // Sort entries primarily by name, to help make the order consistent + // across platforms and relatively insensitive to changes. + // (Sadly we can't use `sort_by_key` because we would need to return references.) + Ord::cmp(&a.0, &b.0) + .then_with(|| Ord::cmp(&a.1.is_used, &b.1.is_used)) + .then_with(|| Ord::cmp(a.1.payload.as_slice(), b.1.payload.as_slice())) + }); + + for (name, line_data) in &covfun_entries { + let name = name.unwrap_or("(unknown)"); + let unused = if line_data.is_used { "" } else { " (unused)" }; + println!("Function name: {name}{unused}"); + + let payload: &[u8] = &line_data.payload; + println!("Raw bytes ({len}): 0x{payload:02x?}", len = payload.len()); + + let mut parser = Parser::new(payload); + + let num_files = parser.read_uleb128_u32()?; + println!("Number of files: {num_files}"); + + for i in 0..num_files { + let global_file_id = parser.read_uleb128_u32()?; + println!("- file {i} => global file {global_file_id}"); + } + + let num_expressions = parser.read_uleb128_u32()?; + println!("Number of expressions: {num_expressions}"); + + let mut expression_resolver = ExpressionResolver::new(); + for i in 0..num_expressions { + let lhs = parser.read_simple_term()?; + let rhs = parser.read_simple_term()?; + println!("- expression {i} operands: lhs = {lhs:?}, rhs = {rhs:?}"); + expression_resolver.push_operands(lhs, rhs); + } + + for i in 0..num_files { + let num_mappings = parser.read_uleb128_u32()?; + println!("Number of file {i} mappings: {num_mappings}"); + + for _ in 0..num_mappings { + let (kind, region) = parser.read_mapping_kind_and_region()?; + println!("- {kind:?} at {region:?}"); + + match kind { + // Also print expression mappings in resolved form. + MappingKind::Code(term @ CovTerm::Expression { .. }) + | MappingKind::Gap(term @ CovTerm::Expression { .. }) => { + println!(" = {}", expression_resolver.format_term(term)); + } + // If the mapping is a branch region, print both of its arms + // in resolved form (even if they aren't expressions). + MappingKind::Branch { r#true, r#false } => { + println!(" true = {}", expression_resolver.format_term(r#true)); + println!(" false = {}", expression_resolver.format_term(r#false)); + } + _ => (), + } + } + } + + parser.ensure_empty()?; + println!(); + } + Ok(()) +} + +struct CovfunLineData { + name_hash: u64, + is_used: bool, + payload: Vec, +} + +/// Checks a line of LLVM IR assembly to see if it contains an `__llvm_covfun` +/// entry, and if so extracts relevant data in a `CovfunLineData`. +fn covfun_line_data(line: &str) -> Option { + let re = { + // We cheat a little bit and match variable names `@__covrec_[HASH]u` + // rather than the section name, because the section name is harder to + // extract and differs across Linux/Windows/macOS. We also extract the + // symbol name hash from the variable name rather than the data, since + // it's easier and both should match. + static RE: OnceLock = OnceLock::new(); + RE.get_or_init(|| { + Regex::new( + r#"^@__covrec_(?[0-9A-Z]+)(?u)? = .*\[[0-9]+ x i8\] c"(?[^"]*)".*$"#, + ) + .unwrap() + }) + }; + + let captures = re.captures(line)?; + let name_hash = u64::from_str_radix(&captures["name_hash"], 16).unwrap(); + let is_used = captures.name("is_used").is_some(); + let payload = unescape_llvm_string_contents(&captures["payload"]); + + Some(CovfunLineData { name_hash, is_used, payload }) +} + +// Extra parser methods only needed when parsing `covfun` payloads. +impl<'a> Parser<'a> { + fn read_simple_term(&mut self) -> anyhow::Result { + let raw_term = self.read_uleb128_u32()?; + CovTerm::decode(raw_term).context("decoding term") + } + + fn read_mapping_kind_and_region(&mut self) -> anyhow::Result<(MappingKind, MappingRegion)> { + let mut kind = self.read_raw_mapping_kind()?; + let mut region = self.read_raw_mapping_region()?; + + const HIGH_BIT: u32 = 1u32 << 31; + if region.end_column & HIGH_BIT != 0 { + region.end_column &= !HIGH_BIT; + kind = match kind { + MappingKind::Code(term) => MappingKind::Gap(term), + // LLVM's coverage mapping reader will actually handle this + // case without complaint, but the result is almost certainly + // a meaningless implementation artifact. + _ => return Err(anyhow!("unexpected base kind for gap region: {kind:?}")), + } + } + + Ok((kind, region)) + } + + fn read_raw_mapping_kind(&mut self) -> anyhow::Result { + let raw_mapping_kind = self.read_uleb128_u32()?; + if let Some(term) = CovTerm::decode(raw_mapping_kind) { + return Ok(MappingKind::Code(term)); + } + + assert_eq!(raw_mapping_kind & 0b11, 0); + assert_ne!(raw_mapping_kind, 0); + + let (high, is_expansion) = (raw_mapping_kind >> 3, raw_mapping_kind & 0b100 != 0); + if is_expansion { + Ok(MappingKind::Expansion(high)) + } else { + match high { + 0 => unreachable!("zero kind should have already been handled as a code mapping"), + 2 => Ok(MappingKind::Skip), + 4 => { + let r#true = self.read_simple_term()?; + let r#false = self.read_simple_term()?; + Ok(MappingKind::Branch { r#true, r#false }) + } + _ => Err(anyhow!("unknown mapping kind: {raw_mapping_kind:#x}")), + } + } + } + + fn read_raw_mapping_region(&mut self) -> anyhow::Result { + let start_line_offset = self.read_uleb128_u32()?; + let start_column = self.read_uleb128_u32()?; + let end_line_offset = self.read_uleb128_u32()?; + let end_column = self.read_uleb128_u32()?; + Ok(MappingRegion { start_line_offset, start_column, end_line_offset, end_column }) + } +} + +/// Enum that can hold a constant zero value, the ID of an physical coverage +/// counter, or the ID (and operation) of a coverage-counter expression. +/// +/// Terms are used as the operands of coverage-counter expressions, as the arms +/// of branch mappings, and as the value of code/gap mappings. +#[derive(Clone, Copy, Debug)] +pub(crate) enum CovTerm { + Zero, + Counter(u32), + Expression(u32, Op), +} + +/// Operator (addition or subtraction) used by an expression. +#[derive(Clone, Copy, Debug)] +pub(crate) enum Op { + Sub, + Add, +} + +impl CovTerm { + pub(crate) fn decode(input: u32) -> Option { + let (high, tag) = (input >> 2, input & 0b11); + match tag { + 0b00 if high == 0 => Some(Self::Zero), + 0b01 => Some(Self::Counter(high)), + 0b10 => Some(Self::Expression(high, Op::Sub)), + 0b11 => Some(Self::Expression(high, Op::Add)), + // When reading expression operands or branch arms, the LLVM coverage + // mapping reader will always interpret a `0b00` tag as a zero + // term, even when the high bits are non-zero. + // We treat that case as failure instead, so that this code can be + // shared by the full mapping-kind reader as well. + _ => None, + } + } +} + +#[derive(Debug)] +enum MappingKind { + Code(CovTerm), + Gap(CovTerm), + Expansion(u32), + Skip, + // Using raw identifiers here makes the dump output a little bit nicer + // (via the derived Debug), at the expense of making this tool's source + // code a little bit uglier. + Branch { r#true: CovTerm, r#false: CovTerm }, +} + +struct MappingRegion { + /// Offset of this region's start line, relative to the *start line* of + /// the *previous mapping* (or 0). Line numbers are 1-based. + start_line_offset: u32, + /// This region's start column, absolute and 1-based. + start_column: u32, + /// Offset of this region's end line, relative to the *this mapping's* + /// start line. Line numbers are 1-based. + end_line_offset: u32, + /// This region's end column, absolute, 1-based, and exclusive. + /// + /// If the highest bit is set, that bit is cleared and the associated + /// mapping becomes a gap region mapping. + end_column: u32, +} + +impl Debug for MappingRegion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "(prev + {}, {}) to (start + {}, {})", + self.start_line_offset, self.start_column, self.end_line_offset, self.end_column + ) + } +} + +/// Helper type that prints expressions in a "resolved" form, so that +/// developers reading the dump don't need to resolve expressions by hand. +struct ExpressionResolver { + operands: Vec<(CovTerm, CovTerm)>, +} + +impl ExpressionResolver { + fn new() -> Self { + Self { operands: Vec::new() } + } + + fn push_operands(&mut self, lhs: CovTerm, rhs: CovTerm) { + self.operands.push((lhs, rhs)); + } + + fn format_term(&self, term: CovTerm) -> String { + let mut output = String::new(); + self.write_term(&mut output, term); + output + } + + fn write_term(&self, output: &mut String, term: CovTerm) { + match term { + CovTerm::Zero => output.push_str("Zero"), + CovTerm::Counter(id) => write!(output, "c{id}").unwrap(), + CovTerm::Expression(id, op) => { + let (lhs, rhs) = self.operands[id as usize]; + let op = match op { + Op::Sub => "-", + Op::Add => "+", + }; + + output.push('('); + self.write_term(output, lhs); + write!(output, " {op} ").unwrap(); + self.write_term(output, rhs); + output.push(')'); + } + } + } +} diff --git a/src/tools/coverage-dump/src/main.rs b/src/tools/coverage-dump/src/main.rs new file mode 100644 index 0000000000000..93fed1799e041 --- /dev/null +++ b/src/tools/coverage-dump/src/main.rs @@ -0,0 +1,17 @@ +mod covfun; +mod parser; +mod prf_names; + +fn main() -> anyhow::Result<()> { + use anyhow::Context as _; + + let args = std::env::args().collect::>(); + + let llvm_ir_path = args.get(1).context("LLVM IR file not specified")?; + let llvm_ir = std::fs::read_to_string(llvm_ir_path).context("couldn't read LLVM IR file")?; + + let function_names = crate::prf_names::make_function_names_table(&llvm_ir)?; + crate::covfun::dump_covfun_mappings(&llvm_ir, &function_names)?; + + Ok(()) +} diff --git a/src/tools/coverage-dump/src/parser.rs b/src/tools/coverage-dump/src/parser.rs new file mode 100644 index 0000000000000..eefac1a4f94c1 --- /dev/null +++ b/src/tools/coverage-dump/src/parser.rs @@ -0,0 +1,80 @@ +#[cfg(test)] +mod tests; + +use anyhow::ensure; +use regex::bytes; +use std::sync::OnceLock; + +/// Given the raw contents of a string literal in LLVM IR assembly, decodes any +/// backslash escapes and returns a vector containing the resulting byte string. +pub(crate) fn unescape_llvm_string_contents(contents: &str) -> Vec { + let escape_re = { + static RE: OnceLock = OnceLock::new(); + // LLVM IR supports two string escapes: `\\` and `\xx`. + RE.get_or_init(|| bytes::Regex::new(r"\\\\|\\([0-9A-Za-z]{2})").unwrap()) + }; + + fn u8_from_hex_digits(digits: &[u8]) -> u8 { + // We know that the input contains exactly 2 hex digits, so these calls + // should never fail. + assert_eq!(digits.len(), 2); + let digits = std::str::from_utf8(digits).unwrap(); + u8::from_str_radix(digits, 16).unwrap() + } + + escape_re + .replace_all(contents.as_bytes(), |captures: &bytes::Captures<'_>| { + let byte = match captures.get(1) { + None => b'\\', + Some(hex_digits) => u8_from_hex_digits(hex_digits.as_bytes()), + }; + [byte] + }) + .into_owned() +} + +pub(crate) struct Parser<'a> { + rest: &'a [u8], +} + +impl<'a> Parser<'a> { + pub(crate) fn new(input: &'a [u8]) -> Self { + Self { rest: input } + } + + pub(crate) fn ensure_empty(self) -> anyhow::Result<()> { + ensure!(self.rest.is_empty(), "unparsed bytes: 0x{:02x?}", self.rest); + Ok(()) + } + + pub(crate) fn read_n_bytes(&mut self, n: usize) -> anyhow::Result<&'a [u8]> { + ensure!(n <= self.rest.len()); + + let (bytes, rest) = self.rest.split_at(n); + self.rest = rest; + Ok(bytes) + } + + pub(crate) fn read_uleb128_u32(&mut self) -> anyhow::Result { + self.read_uleb128_u64_and_convert() + } + + pub(crate) fn read_uleb128_usize(&mut self) -> anyhow::Result { + self.read_uleb128_u64_and_convert() + } + + fn read_uleb128_u64_and_convert(&mut self) -> anyhow::Result + where + T: TryFrom + 'static, + T::Error: std::error::Error + Send + Sync, + { + let mut temp_rest = self.rest; + let raw_value: u64 = leb128::read::unsigned(&mut temp_rest)?; + let converted_value = T::try_from(raw_value)?; + + // Only update `self.rest` if the above steps succeeded, so that the + // parser position can be used for error reporting if desired. + self.rest = temp_rest; + Ok(converted_value) + } +} diff --git a/src/tools/coverage-dump/src/parser/tests.rs b/src/tools/coverage-dump/src/parser/tests.rs new file mode 100644 index 0000000000000..a673606b9c4c8 --- /dev/null +++ b/src/tools/coverage-dump/src/parser/tests.rs @@ -0,0 +1,38 @@ +use super::unescape_llvm_string_contents; + +// WARNING: These tests don't necessarily run in CI, and were mainly used to +// help track down problems when originally developing this tool. +// (The tool is still tested indirectly by snapshot tests that rely on it.) + +// Tests for `unescape_llvm_string_contents`: + +#[test] +fn unescape_empty() { + assert_eq!(unescape_llvm_string_contents(""), &[]); +} + +#[test] +fn unescape_noop() { + let input = "The quick brown fox jumps over the lazy dog."; + assert_eq!(unescape_llvm_string_contents(input), input.as_bytes()); +} + +#[test] +fn unescape_backslash() { + let input = r"\\Hello\\world\\"; + assert_eq!(unescape_llvm_string_contents(input), r"\Hello\world\".as_bytes()); +} + +#[test] +fn unescape_hex() { + let input = r"\01\02\03\04\0a\0b\0C\0D\fd\fE\FF"; + let expected: &[u8] = &[0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d, 0xfd, 0xfe, 0xff]; + assert_eq!(unescape_llvm_string_contents(input), expected); +} + +#[test] +fn unescape_mixed() { + let input = r"\\01.\5c\5c"; + let expected: &[u8] = br"\01.\\"; + assert_eq!(unescape_llvm_string_contents(input), expected); +} diff --git a/src/tools/coverage-dump/src/prf_names.rs b/src/tools/coverage-dump/src/prf_names.rs new file mode 100644 index 0000000000000..d3f7b819e4837 --- /dev/null +++ b/src/tools/coverage-dump/src/prf_names.rs @@ -0,0 +1,87 @@ +use crate::parser::{unescape_llvm_string_contents, Parser}; +use anyhow::{anyhow, ensure}; +use regex::Regex; +use std::collections::HashMap; +use std::sync::OnceLock; + +/// Scans through the contents of an LLVM IR assembly file to find `__llvm_prf_names` +/// entries, decodes them, and creates a table that maps name hash values to +/// (demangled) function names. +pub(crate) fn make_function_names_table(llvm_ir: &str) -> anyhow::Result> { + fn prf_names_payload(line: &str) -> Option<&str> { + let re = { + // We cheat a little bit and match the variable name `@__llvm_prf_nm` + // rather than the section name, because the section name is harder + // to extract and differs across Linux/Windows/macOS. + static RE: OnceLock = OnceLock::new(); + RE.get_or_init(|| { + Regex::new(r#"^@__llvm_prf_nm =.*\[[0-9]+ x i8\] c"([^"]*)".*$"#).unwrap() + }) + }; + + let payload = re.captures(line)?.get(1).unwrap().as_str(); + Some(payload) + } + + /// LLVM's profiler/coverage metadata often uses an MD5 hash truncated to + /// 64 bits as a way to associate data stored in different tables/sections. + fn truncated_md5(bytes: &[u8]) -> u64 { + use md5::{Digest, Md5}; + let mut hasher = Md5::new(); + hasher.update(bytes); + let hash: [u8; 8] = hasher.finalize().as_slice()[..8].try_into().unwrap(); + // The truncated hash is explicitly little-endian, regardless of host + // or target platform. (See `MD5Result::low` in LLVM's `MD5.h`.) + u64::from_le_bytes(hash) + } + + fn demangle_if_able(symbol_name_bytes: &[u8]) -> anyhow::Result { + // In practice, raw symbol names should always be ASCII. + let symbol_name_str = std::str::from_utf8(symbol_name_bytes)?; + match rustc_demangle::try_demangle(symbol_name_str) { + Ok(d) => Ok(format!("{d:#}")), + // If demangling failed, don't treat it as an error. This lets us + // run the dump tool against non-Rust coverage maps produced by + // `clang`, for testing purposes. + Err(_) => Ok(format!("(couldn't demangle) {symbol_name_str}")), + } + } + + let mut map = HashMap::new(); + + for payload in llvm_ir.lines().filter_map(prf_names_payload).map(unescape_llvm_string_contents) + { + let mut parser = Parser::new(&payload); + let uncompressed_len = parser.read_uleb128_usize()?; + let compressed_len = parser.read_uleb128_usize()?; + + let uncompressed_bytes_vec; + let uncompressed_bytes: &[u8] = if compressed_len == 0 { + // The symbol name bytes are uncompressed, so read them directly. + parser.read_n_bytes(uncompressed_len)? + } else { + // The symbol name bytes are compressed, so read and decompress them. + let compressed_bytes = parser.read_n_bytes(compressed_len)?; + + uncompressed_bytes_vec = miniz_oxide::inflate::decompress_to_vec_zlib_with_limit( + compressed_bytes, + uncompressed_len, + ) + .map_err(|e| anyhow!("{e:?}"))?; + ensure!(uncompressed_bytes_vec.len() == uncompressed_len); + + &uncompressed_bytes_vec + }; + + // Symbol names in the payload are separated by `0x01` bytes. + for raw_name in uncompressed_bytes.split(|&b| b == 0x01) { + let hash = truncated_md5(raw_name); + let demangled = demangle_if_able(raw_name)?; + map.insert(hash, demangled); + } + + parser.ensure_empty()?; + } + + Ok(map) +} From 004db4728bc6ccc62416f93ba6473b144def7fe8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 14 Aug 2023 13:00:28 +1000 Subject: [PATCH 2/3] Add test suite `coverage-map` to test coverage mappings emitted by LLVM We compile each test file to LLVM IR assembly, and then pass that IR to a dedicated program that can decode LLVM coverage maps and print them in a more human-readable format. We can then check that output against known-good snapshots. This test suite has some advantages over the existing `run-coverage` tests: - We can test coverage instrumentation without needing to run target binaries. - We can observe subtle improvements/regressions in the underlying coverage mappings that don't make a visible difference to coverage reports. --- src/bootstrap/builder.rs | 1 + src/bootstrap/test.rs | 14 +++ src/tools/compiletest/src/common.rs | 6 + src/tools/compiletest/src/lib.rs | 2 + src/tools/compiletest/src/runtest.rs | 71 ++++++++++- tests/coverage-map/if.cov-map | 15 +++ tests/coverage-map/if.rs | 9 ++ tests/coverage-map/long_and_wide.cov-map | 32 +++++ tests/coverage-map/long_and_wide.rs | 150 +++++++++++++++++++++++ tests/coverage-map/trivial.cov-map | 8 ++ tests/coverage-map/trivial.rs | 3 + 11 files changed, 306 insertions(+), 5 deletions(-) create mode 100644 tests/coverage-map/if.cov-map create mode 100644 tests/coverage-map/if.rs create mode 100644 tests/coverage-map/long_and_wide.cov-map create mode 100644 tests/coverage-map/long_and_wide.rs create mode 100644 tests/coverage-map/trivial.cov-map create mode 100644 tests/coverage-map/trivial.rs diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 73c0a192cef94..a24a6a4636d48 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -726,6 +726,7 @@ impl<'a> Builder<'a> { test::Tidy, test::Ui, test::RunPassValgrind, + test::CoverageMap, test::RunCoverage, test::MirOpt, test::Codegen, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index d1018978f78c9..d78e0deda69f0 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1340,6 +1340,12 @@ host_test!(RunMakeFullDeps { default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" }); +default_test!(CoverageMap { + path: "tests/coverage-map", + mode: "coverage-map", + suite: "coverage-map" +}); + host_test!(RunCoverage { path: "tests/run-coverage", mode: "run-coverage", suite: "run-coverage" }); host_test!(RunCoverageRustdoc { path: "tests/run-coverage-rustdoc", @@ -1545,6 +1551,14 @@ note: if you're sure you want to do this, please open an issue as to why. In the .arg(builder.ensure(tool::JsonDocLint { compiler: json_compiler, target })); } + if mode == "coverage-map" { + let coverage_dump = builder.ensure(tool::CoverageDump { + compiler: compiler.with_stage(0), + target: compiler.host, + }); + cmd.arg("--coverage-dump-path").arg(coverage_dump); + } + if mode == "run-make" || mode == "run-coverage" { let rust_demangler = builder .ensure(tool::RustDemangler { diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 7c17e92d0dfe2..b91d5a958bb62 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -66,6 +66,7 @@ string_enum! { JsDocTest => "js-doc-test", MirOpt => "mir-opt", Assembly => "assembly", + CoverageMap => "coverage-map", RunCoverage => "run-coverage", } } @@ -161,6 +162,9 @@ pub struct Config { /// The rust-demangler executable. pub rust_demangler_path: Option, + /// The coverage-dump executable. + pub coverage_dump_path: Option, + /// The Python executable to use for LLDB and htmldocck. pub python: String, @@ -639,6 +643,7 @@ pub const UI_EXTENSIONS: &[&str] = &[ UI_STDERR_32, UI_STDERR_16, UI_COVERAGE, + UI_COVERAGE_MAP, ]; pub const UI_STDERR: &str = "stderr"; pub const UI_STDOUT: &str = "stdout"; @@ -649,6 +654,7 @@ pub const UI_STDERR_64: &str = "64bit.stderr"; pub const UI_STDERR_32: &str = "32bit.stderr"; pub const UI_STDERR_16: &str = "16bit.stderr"; pub const UI_COVERAGE: &str = "coverage"; +pub const UI_COVERAGE_MAP: &str = "cov-map"; /// Absolute path to the directory where all output for all tests in the given /// `relative_dir` group should reside. Example: diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 1a765477fe501..619ff9b322114 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -48,6 +48,7 @@ pub fn parse_config(args: Vec) -> Config { .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH") .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH") .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH") + .optopt("", "coverage-dump-path", "path to coverage-dump to use in tests", "PATH") .reqopt("", "python", "path to python to use for doc tests", "PATH") .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH") .optopt("", "jsondoclint-path", "path to jsondoclint to use for doc tests", "PATH") @@ -218,6 +219,7 @@ pub fn parse_config(args: Vec) -> Config { rustc_path: opt_path(matches, "rustc-path"), rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from), rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from), + coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from), python: matches.opt_str("python").unwrap(), jsondocck_path: matches.opt_str("jsondocck-path"), jsondoclint_path: matches.opt_str("jsondoclint-path"), diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index dd4c59fdff513..670441aacbd08 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -6,8 +6,8 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJs use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc}; use crate::common::{CompareMode, FailMode, PassMode}; use crate::common::{Config, TestPaths}; -use crate::common::{Pretty, RunCoverage, RunPassValgrind}; -use crate::common::{UI_COVERAGE, UI_RUN_STDERR, UI_RUN_STDOUT}; +use crate::common::{CoverageMap, Pretty, RunCoverage, RunPassValgrind}; +use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP, UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::compute_diff::{write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; @@ -254,6 +254,7 @@ impl<'test> TestCx<'test> { MirOpt => self.run_mir_opt_test(), Assembly => self.run_assembly_test(), JsDocTest => self.run_js_doc_test(), + CoverageMap => self.run_coverage_map_test(), RunCoverage => self.run_coverage_test(), } } @@ -467,6 +468,46 @@ impl<'test> TestCx<'test> { } } + fn run_coverage_map_test(&self) { + let Some(coverage_dump_path) = &self.config.coverage_dump_path else { + self.fatal("missing --coverage-dump"); + }; + + let proc_res = self.compile_test_and_save_ir(); + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + drop(proc_res); + + let llvm_ir_path = self.output_base_name().with_extension("ll"); + + let mut dump_command = Command::new(coverage_dump_path); + dump_command.arg(llvm_ir_path); + let proc_res = self.run_command_to_procres(&mut dump_command); + if !proc_res.status.success() { + self.fatal_proc_rec("coverage-dump failed!", &proc_res); + } + + let kind = UI_COVERAGE_MAP; + + let expected_coverage_dump = self.load_expected_output(kind); + let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]); + + let coverage_dump_errors = self.compare_output( + kind, + &actual_coverage_dump, + &expected_coverage_dump, + self.props.compare_output_lines_by_subset, + ); + + if coverage_dump_errors > 0 { + self.fatal_proc_rec( + &format!("{coverage_dump_errors} errors occurred comparing coverage output."), + &proc_res, + ); + } + } + fn run_coverage_test(&self) { let should_run = self.run_if_enabled(); let proc_res = self.compile_test(should_run, Emit::None); @@ -650,6 +691,10 @@ impl<'test> TestCx<'test> { let mut cmd = Command::new(tool_path); configure_cmd_fn(&mut cmd); + self.run_command_to_procres(&mut cmd) + } + + fn run_command_to_procres(&self, cmd: &mut Command) -> ProcRes { let output = cmd.output().unwrap_or_else(|_| panic!("failed to exec `{cmd:?}`")); let proc_res = ProcRes { @@ -2321,9 +2366,11 @@ impl<'test> TestCx<'test> { } } DebugInfo => { /* debuginfo tests must be unoptimized */ } - RunCoverage => { - // Coverage reports are affected by optimization level, and - // the current snapshots assume no optimization by default. + CoverageMap | RunCoverage => { + // Coverage mappings and coverage reports are affected by + // optimization level, so they ignore the optimize-tests + // setting and set an optimization level in their mode's + // compile flags (below) or in per-test `compile-flags`. } _ => { rustc.arg("-O"); @@ -2392,8 +2439,22 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } + CoverageMap => { + rustc.arg("-Cinstrument-coverage"); + // These tests only compile to MIR, so they don't need the + // profiler runtime to be present. + rustc.arg("-Zno-profiler-runtime"); + // Coverage mappings are sensitive to MIR optimizations, and + // the current snapshots assume `opt-level=2` unless overridden + // by `compile-flags`. + rustc.arg("-Copt-level=2"); + } RunCoverage => { rustc.arg("-Cinstrument-coverage"); + // Coverage reports are sometimes sensitive to optimizations, + // and the current snapshots assume no optimization unless + // overridden by `compile-flags`. + rustc.arg("-Copt-level=0"); } RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson | RunMake | CodegenUnits | JsDocTest | Assembly => { diff --git a/tests/coverage-map/if.cov-map b/tests/coverage-map/if.cov-map new file mode 100644 index 0000000000000..3cedb5ffbecb1 --- /dev/null +++ b/tests/coverage-map/if.cov-map @@ -0,0 +1,15 @@ +Function name: if::main +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 01, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) +- Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c1 + (c0 - c1)) + diff --git a/tests/coverage-map/if.rs b/tests/coverage-map/if.rs new file mode 100644 index 0000000000000..ed3f69bdc98d2 --- /dev/null +++ b/tests/coverage-map/if.rs @@ -0,0 +1,9 @@ +// compile-flags: --edition=2021 + +fn main() { + let cond = std::env::args().len() == 1; + if cond { + println!("true"); + } + println!("done"); +} diff --git a/tests/coverage-map/long_and_wide.cov-map b/tests/coverage-map/long_and_wide.cov-map new file mode 100644 index 0000000000000..97aebf9b18ab0 --- /dev/null +++ b/tests/coverage-map/long_and_wide.cov-map @@ -0,0 +1,32 @@ +Function name: long_and_wide::far_function +Raw bytes (10): 0x[01, 01, 00, 01, 01, 96, 01, 01, 00, 15] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 150, 1) to (start + 0, 21) + +Function name: long_and_wide::long_function +Raw bytes (10): 0x[01, 01, 00, 01, 01, 10, 01, 84, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 16, 1) to (start + 132, 2) + +Function name: long_and_wide::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 04, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 7, 1) to (start + 4, 2) + +Function name: long_and_wide::wide_function +Raw bytes (10): 0x[01, 01, 00, 01, 01, 0e, 01, 00, 8b, 01] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 139) + diff --git a/tests/coverage-map/long_and_wide.rs b/tests/coverage-map/long_and_wide.rs new file mode 100644 index 0000000000000..a7cbcd4802791 --- /dev/null +++ b/tests/coverage-map/long_and_wide.rs @@ -0,0 +1,150 @@ +// compile-flags: --edition=2021 +// ignore-tidy-linelength + +// This file deliberately contains line and column numbers larger than 127, +// to verify that `coverage-dump`'s ULEB128 parser can handle them. + +fn main() { + wide_function(); + long_function(); + far_function(); +} + +#[rustfmt::skip] +fn wide_function() { /* */ (); } + +fn long_function() { + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // +} + +fn far_function() {} diff --git a/tests/coverage-map/trivial.cov-map b/tests/coverage-map/trivial.cov-map new file mode 100644 index 0000000000000..874e294a1c498 --- /dev/null +++ b/tests/coverage-map/trivial.cov-map @@ -0,0 +1,8 @@ +Function name: trivial::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 00, 0d] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 13) + diff --git a/tests/coverage-map/trivial.rs b/tests/coverage-map/trivial.rs new file mode 100644 index 0000000000000..d0a9b44fb3605 --- /dev/null +++ b/tests/coverage-map/trivial.rs @@ -0,0 +1,3 @@ +// compile-flags: --edition=2021 + +fn main() {} From 3141177995f52fc3cbb64d66cf0a98ea0f754fca Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 14 Aug 2023 21:29:41 +1000 Subject: [PATCH 3/3] Copy most of `tests/run-coverage` into `tests/coverage-map/status-quo` The output of these tests is too complicated to comfortably verify by hand, but we can still use them to observe changes to the underlying mappings produced by codegen/LLVM. If these tests fail due to non-coverage changes (e.g. in HIR-to-MIR lowering or MIR optimizations), it should usually be OK to just `--bless` them, as long as the `run-coverage` test suite still works. --- tests/coverage-map/README.md | 13 + tests/coverage-map/status-quo/abort.cov-map | 57 +++ tests/coverage-map/status-quo/abort.rs | 66 ++++ tests/coverage-map/status-quo/assert.cov-map | 40 +++ tests/coverage-map/status-quo/assert.rs | 32 ++ tests/coverage-map/status-quo/async.cov-map | 340 ++++++++++++++++++ tests/coverage-map/status-quo/async.rs | 128 +++++++ tests/coverage-map/status-quo/async2.cov-map | 136 +++++++ tests/coverage-map/status-quo/async2.rs | 57 +++ tests/coverage-map/status-quo/closure.cov-map | 324 +++++++++++++++++ tests/coverage-map/status-quo/closure.rs | 220 ++++++++++++ .../status-quo/closure_macro.cov-map | 40 +++ .../coverage-map/status-quo/closure_macro.rs | 40 +++ .../status-quo/closure_macro_async.cov-map | 48 +++ .../status-quo/closure_macro_async.rs | 77 ++++ .../status-quo/conditions.cov-map | 261 ++++++++++++++ tests/coverage-map/status-quo/conditions.rs | 86 +++++ .../coverage-map/status-quo/continue.cov-map | 85 +++++ tests/coverage-map/status-quo/continue.rs | 69 ++++ .../coverage-map/status-quo/dead_code.cov-map | 37 ++ tests/coverage-map/status-quo/dead_code.rs | 37 ++ .../status-quo/drop_trait.cov-map | 21 ++ tests/coverage-map/status-quo/drop_trait.rs | 33 ++ .../coverage-map/status-quo/generator.cov-map | 58 +++ tests/coverage-map/status-quo/generator.rs | 30 ++ .../coverage-map/status-quo/generics.cov-map | 45 +++ tests/coverage-map/status-quo/generics.rs | 44 +++ tests/coverage-map/status-quo/if.cov-map | 15 + tests/coverage-map/status-quo/if.rs | 28 ++ tests/coverage-map/status-quo/if_else.cov-map | 25 ++ tests/coverage-map/status-quo/if_else.rs | 40 +++ .../status-quo/inline-dead.cov-map | 45 +++ tests/coverage-map/status-quo/inline-dead.rs | 27 ++ tests/coverage-map/status-quo/inline.cov-map | 82 +++++ tests/coverage-map/status-quo/inline.rs | 51 +++ .../status-quo/inner_items.cov-map | 49 +++ tests/coverage-map/status-quo/inner_items.rs | 57 +++ .../status-quo/issue-83601.cov-map | 28 ++ tests/coverage-map/status-quo/issue-83601.rs | 14 + .../status-quo/issue-84561.cov-map | 233 ++++++++++++ tests/coverage-map/status-quo/issue-84561.rs | 182 ++++++++++ .../status-quo/issue-93054.cov-map | 24 ++ tests/coverage-map/status-quo/issue-93054.rs | 30 ++ .../status-quo/lazy_boolean.cov-map | 223 ++++++++++++ tests/coverage-map/status-quo/lazy_boolean.rs | 61 ++++ .../status-quo/loop_break_value.cov-map | 8 + .../status-quo/loop_break_value.rs | 13 + .../status-quo/loops_branches.cov-map | 193 ++++++++++ .../coverage-map/status-quo/loops_branches.rs | 60 ++++ .../status-quo/match_or_pattern.cov-map | 83 +++++ .../status-quo/match_or_pattern.rs | 43 +++ .../status-quo/nested_loops.cov-map | 51 +++ tests/coverage-map/status-quo/nested_loops.rs | 25 ++ .../status-quo/no_cov_crate.cov-map | 78 ++++ tests/coverage-map/status-quo/no_cov_crate.rs | 88 +++++ .../coverage-map/status-quo/overflow.cov-map | 43 +++ tests/coverage-map/status-quo/overflow.rs | 63 ++++ .../status-quo/panic_unwind.cov-map | 40 +++ tests/coverage-map/status-quo/panic_unwind.rs | 31 ++ .../status-quo/partial_eq.cov-map | 64 ++++ tests/coverage-map/status-quo/partial_eq.rs | 46 +++ .../status-quo/simple_loop.cov-map | 28 ++ tests/coverage-map/status-quo/simple_loop.rs | 35 ++ .../status-quo/simple_match.cov-map | 36 ++ tests/coverage-map/status-quo/simple_match.rs | 43 +++ .../status-quo/sort_groups.cov-map | 68 ++++ tests/coverage-map/status-quo/sort_groups.rs | 23 ++ .../status-quo/test_harness.cov-map | 24 ++ tests/coverage-map/status-quo/test_harness.rs | 10 + .../status-quo/tight_inf_loop.cov-map | 12 + .../coverage-map/status-quo/tight_inf_loop.rs | 5 + .../status-quo/try_error_result.cov-map | 226 ++++++++++++ .../status-quo/try_error_result.rs | 118 ++++++ tests/coverage-map/status-quo/unused.cov-map | 94 +++++ tests/coverage-map/status-quo/unused.rs | 41 +++ tests/coverage-map/status-quo/while.cov-map | 15 + tests/coverage-map/status-quo/while.rs | 5 + .../status-quo/while_early_ret.cov-map | 26 ++ .../status-quo/while_early_ret.rs | 42 +++ tests/coverage-map/status-quo/yield.cov-map | 72 ++++ tests/coverage-map/status-quo/yield.rs | 37 ++ 81 files changed, 5527 insertions(+) create mode 100644 tests/coverage-map/README.md create mode 100644 tests/coverage-map/status-quo/abort.cov-map create mode 100644 tests/coverage-map/status-quo/abort.rs create mode 100644 tests/coverage-map/status-quo/assert.cov-map create mode 100644 tests/coverage-map/status-quo/assert.rs create mode 100644 tests/coverage-map/status-quo/async.cov-map create mode 100644 tests/coverage-map/status-quo/async.rs create mode 100644 tests/coverage-map/status-quo/async2.cov-map create mode 100644 tests/coverage-map/status-quo/async2.rs create mode 100644 tests/coverage-map/status-quo/closure.cov-map create mode 100644 tests/coverage-map/status-quo/closure.rs create mode 100644 tests/coverage-map/status-quo/closure_macro.cov-map create mode 100644 tests/coverage-map/status-quo/closure_macro.rs create mode 100644 tests/coverage-map/status-quo/closure_macro_async.cov-map create mode 100644 tests/coverage-map/status-quo/closure_macro_async.rs create mode 100644 tests/coverage-map/status-quo/conditions.cov-map create mode 100644 tests/coverage-map/status-quo/conditions.rs create mode 100644 tests/coverage-map/status-quo/continue.cov-map create mode 100644 tests/coverage-map/status-quo/continue.rs create mode 100644 tests/coverage-map/status-quo/dead_code.cov-map create mode 100644 tests/coverage-map/status-quo/dead_code.rs create mode 100644 tests/coverage-map/status-quo/drop_trait.cov-map create mode 100644 tests/coverage-map/status-quo/drop_trait.rs create mode 100644 tests/coverage-map/status-quo/generator.cov-map create mode 100644 tests/coverage-map/status-quo/generator.rs create mode 100644 tests/coverage-map/status-quo/generics.cov-map create mode 100644 tests/coverage-map/status-quo/generics.rs create mode 100644 tests/coverage-map/status-quo/if.cov-map create mode 100644 tests/coverage-map/status-quo/if.rs create mode 100644 tests/coverage-map/status-quo/if_else.cov-map create mode 100644 tests/coverage-map/status-quo/if_else.rs create mode 100644 tests/coverage-map/status-quo/inline-dead.cov-map create mode 100644 tests/coverage-map/status-quo/inline-dead.rs create mode 100644 tests/coverage-map/status-quo/inline.cov-map create mode 100644 tests/coverage-map/status-quo/inline.rs create mode 100644 tests/coverage-map/status-quo/inner_items.cov-map create mode 100644 tests/coverage-map/status-quo/inner_items.rs create mode 100644 tests/coverage-map/status-quo/issue-83601.cov-map create mode 100644 tests/coverage-map/status-quo/issue-83601.rs create mode 100644 tests/coverage-map/status-quo/issue-84561.cov-map create mode 100644 tests/coverage-map/status-quo/issue-84561.rs create mode 100644 tests/coverage-map/status-quo/issue-93054.cov-map create mode 100644 tests/coverage-map/status-quo/issue-93054.rs create mode 100644 tests/coverage-map/status-quo/lazy_boolean.cov-map create mode 100644 tests/coverage-map/status-quo/lazy_boolean.rs create mode 100644 tests/coverage-map/status-quo/loop_break_value.cov-map create mode 100644 tests/coverage-map/status-quo/loop_break_value.rs create mode 100644 tests/coverage-map/status-quo/loops_branches.cov-map create mode 100644 tests/coverage-map/status-quo/loops_branches.rs create mode 100644 tests/coverage-map/status-quo/match_or_pattern.cov-map create mode 100644 tests/coverage-map/status-quo/match_or_pattern.rs create mode 100644 tests/coverage-map/status-quo/nested_loops.cov-map create mode 100644 tests/coverage-map/status-quo/nested_loops.rs create mode 100644 tests/coverage-map/status-quo/no_cov_crate.cov-map create mode 100644 tests/coverage-map/status-quo/no_cov_crate.rs create mode 100644 tests/coverage-map/status-quo/overflow.cov-map create mode 100644 tests/coverage-map/status-quo/overflow.rs create mode 100644 tests/coverage-map/status-quo/panic_unwind.cov-map create mode 100644 tests/coverage-map/status-quo/panic_unwind.rs create mode 100644 tests/coverage-map/status-quo/partial_eq.cov-map create mode 100644 tests/coverage-map/status-quo/partial_eq.rs create mode 100644 tests/coverage-map/status-quo/simple_loop.cov-map create mode 100644 tests/coverage-map/status-quo/simple_loop.rs create mode 100644 tests/coverage-map/status-quo/simple_match.cov-map create mode 100644 tests/coverage-map/status-quo/simple_match.rs create mode 100644 tests/coverage-map/status-quo/sort_groups.cov-map create mode 100644 tests/coverage-map/status-quo/sort_groups.rs create mode 100644 tests/coverage-map/status-quo/test_harness.cov-map create mode 100644 tests/coverage-map/status-quo/test_harness.rs create mode 100644 tests/coverage-map/status-quo/tight_inf_loop.cov-map create mode 100644 tests/coverage-map/status-quo/tight_inf_loop.rs create mode 100644 tests/coverage-map/status-quo/try_error_result.cov-map create mode 100644 tests/coverage-map/status-quo/try_error_result.rs create mode 100644 tests/coverage-map/status-quo/unused.cov-map create mode 100644 tests/coverage-map/status-quo/unused.rs create mode 100644 tests/coverage-map/status-quo/while.cov-map create mode 100644 tests/coverage-map/status-quo/while.rs create mode 100644 tests/coverage-map/status-quo/while_early_ret.cov-map create mode 100644 tests/coverage-map/status-quo/while_early_ret.rs create mode 100644 tests/coverage-map/status-quo/yield.cov-map create mode 100644 tests/coverage-map/status-quo/yield.rs diff --git a/tests/coverage-map/README.md b/tests/coverage-map/README.md new file mode 100644 index 0000000000000..60d1352cd64f1 --- /dev/null +++ b/tests/coverage-map/README.md @@ -0,0 +1,13 @@ +The tests in `./status-quo` were copied from `tests/run-coverage` in order to +capture the current behavior of the instrumentor on non-trivial programs. +The actual mappings have not been closely inspected. + +## Maintenance note + +These tests can be sensitive to small changes in MIR spans or MIR control flow, +especially in HIR-to-MIR lowering or MIR optimizations. + +If you haven't touched the coverage code directly, and the `run-coverage` test +suite still works, then it should usually be OK to just `--bless` these +coverage mapping tests as necessary, without worrying too much about the exact +changes. diff --git a/tests/coverage-map/status-quo/abort.cov-map b/tests/coverage-map/status-quo/abort.cov-map new file mode 100644 index 0000000000000..45d3795eff8f3 --- /dev/null +++ b/tests/coverage-map/status-quo/abort.cov-map @@ -0,0 +1,57 @@ +Function name: abort::main +Raw bytes (105): 0x[01, 01, 12, 01, 47, 05, 09, 03, 0d, 42, 11, 03, 0d, 11, 3e, 42, 11, 03, 0d, 3b, 15, 11, 3e, 42, 11, 03, 0d, 15, 36, 3b, 15, 11, 3e, 42, 11, 03, 0d, 05, 09, 0d, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 42, 01, 0c, 00, 19, 11, 00, 1a, 02, 0a, 3e, 02, 0a, 00, 0b, 3b, 02, 0c, 00, 19, 15, 00, 1a, 00, 31, 36, 00, 31, 00, 32, 33, 04, 0c, 00, 19, 05, 00, 1a, 00, 31, 09, 00, 31, 00, 32, 47, 01, 09, 00, 17, 0d, 02, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 18 +- expression 0 operands: lhs = Counter(0), rhs = Expression(17, Add) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 3 operands: lhs = Expression(16, Sub), rhs = Counter(4) +- expression 4 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 5 operands: lhs = Counter(4), rhs = Expression(15, Sub) +- expression 6 operands: lhs = Expression(16, Sub), rhs = Counter(4) +- expression 7 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 8 operands: lhs = Expression(14, Add), rhs = Counter(5) +- expression 9 operands: lhs = Counter(4), rhs = Expression(15, Sub) +- expression 10 operands: lhs = Expression(16, Sub), rhs = Counter(4) +- expression 11 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 12 operands: lhs = Counter(5), rhs = Expression(13, Sub) +- expression 13 operands: lhs = Expression(14, Add), rhs = Counter(5) +- expression 14 operands: lhs = Counter(4), rhs = Expression(15, Sub) +- expression 15 operands: lhs = Expression(16, Sub), rhs = Counter(4) +- expression 16 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 17 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 13, 1) to (start + 1, 27) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24) + = (c0 + (c1 + c2)) +- Code(Expression(16, Sub)) at (prev + 1, 12) to (start + 0, 25) + = ((c0 + (c1 + c2)) - c3) +- Code(Counter(4)) at (prev + 0, 26) to (start + 2, 10) +- Code(Expression(15, Sub)) at (prev + 2, 10) to (start + 0, 11) + = (((c0 + (c1 + c2)) - c3) - c4) +- Code(Expression(14, Add)) at (prev + 2, 12) to (start + 0, 25) + = (c4 + (((c0 + (c1 + c2)) - c3) - c4)) +- Code(Counter(5)) at (prev + 0, 26) to (start + 0, 49) +- Code(Expression(13, Sub)) at (prev + 0, 49) to (start + 0, 50) + = ((c4 + (((c0 + (c1 + c2)) - c3) - c4)) - c5) +- Code(Expression(12, Add)) at (prev + 4, 12) to (start + 0, 25) + = (c5 + ((c4 + (((c0 + (c1 + c2)) - c3) - c4)) - c5)) +- Code(Counter(1)) at (prev + 0, 26) to (start + 0, 49) +- Code(Counter(2)) at (prev + 0, 49) to (start + 0, 50) +- Code(Expression(17, Add)) at (prev + 1, 9) to (start + 0, 23) + = (c1 + c2) +- Code(Counter(3)) at (prev + 2, 5) to (start + 1, 2) + +Function name: abort::might_abort +Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 24, 02, 02, 0c, 03, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20) +- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 36) +- Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) + = (c0 - c1) + diff --git a/tests/coverage-map/status-quo/abort.rs b/tests/coverage-map/status-quo/abort.rs new file mode 100644 index 0000000000000..98264bdc1afe5 --- /dev/null +++ b/tests/coverage-map/status-quo/abort.rs @@ -0,0 +1,66 @@ +#![feature(c_unwind)] +#![allow(unused_assignments)] + +extern "C" fn might_abort(should_abort: bool) { + if should_abort { + println!("aborting..."); + panic!("panics and aborts"); + } else { + println!("Don't Panic"); + } +} + +fn main() -> Result<(), u8> { + let mut countdown = 10; + while countdown > 0 { + if countdown < 5 { + might_abort(false); + } + // See discussion (below the `Notes` section) on coverage results for the closing brace. + if countdown < 5 { might_abort(false); } // Counts for different regions on one line. + // For the following example, the closing brace is the last character on the line. + // This shows the character after the closing brace is highlighted, even if that next + // character is a newline. + if countdown < 5 { might_abort(false); } + countdown -= 1; + } + Ok(()) +} + +// Notes: +// 1. Compare this program and its coverage results to those of the similar tests +// `panic_unwind.rs` and `try_error_result.rs`. +// 2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`. +// 3. The test does not invoke the abort. By executing to a successful completion, the coverage +// results show where the program did and did not execute. +// 4. If the program actually aborted, the coverage counters would not be saved (which "works as +// intended"). Coverage results would show no executed coverage regions. +// 6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status +// (on Linux at least). + +/* + +Expect the following coverage results: + +```text + 16| 11| while countdown > 0 { + 17| 10| if countdown < 5 { + 18| 4| might_abort(false); + 19| 6| } +``` + +This is actually correct. + +The condition `countdown < 5` executed 10 times (10 loop iterations). + +It evaluated to `true` 4 times, and executed the `might_abort()` call. + +It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit +`else`, the coverage implementation injects a counter, at the character immediately after the `if`s +closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the +non-true condition. + +As another example of why this is important, say the condition was `countdown < 50`, which is always +`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called. +The closing brace would have a count of `0`, highlighting the missed coverage. +*/ diff --git a/tests/coverage-map/status-quo/assert.cov-map b/tests/coverage-map/status-quo/assert.cov-map new file mode 100644 index 0000000000000..dd413123de729 --- /dev/null +++ b/tests/coverage-map/status-quo/assert.cov-map @@ -0,0 +1,40 @@ +Function name: assert::main +Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 09, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 02, 0a, 12, 02, 13, 00, 20, 09, 00, 21, 02, 0a, 0d, 02, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 8 +- expression 0 operands: lhs = Counter(0), rhs = Expression(6, Add) +- expression 1 operands: lhs = Counter(1), rhs = Expression(7, Add) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(4) +- expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(1) +- expression 5 operands: lhs = Expression(0, Add), rhs = Counter(4) +- expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add) +- expression 7 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 9, 1) to (start + 1, 27) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24) + = (c0 + (c1 + (c2 + c3))) +- Code(Expression(5, Sub)) at (prev + 1, 12) to (start + 0, 26) + = ((c0 + (c1 + (c2 + c3))) - c4) +- Code(Counter(1)) at (prev + 0, 27) to (start + 2, 10) +- Code(Expression(4, Sub)) at (prev + 2, 19) to (start + 0, 32) + = (((c0 + (c1 + (c2 + c3))) - c4) - c1) +- Code(Counter(2)) at (prev + 0, 33) to (start + 2, 10) +- Code(Counter(3)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) + = (c1 + (c2 + c3)) +- Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) + +Function name: assert::might_fail_assert +Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 02, 0f, 02, 02, 25, 00, 3d, 05, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 4, 1) to (start + 2, 15) +- Code(Expression(0, Sub)) at (prev + 2, 37) to (start + 0, 61) + = (c0 - c1) +- Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) + diff --git a/tests/coverage-map/status-quo/assert.rs b/tests/coverage-map/status-quo/assert.rs new file mode 100644 index 0000000000000..85e6662a6adc8 --- /dev/null +++ b/tests/coverage-map/status-quo/assert.rs @@ -0,0 +1,32 @@ +#![allow(unused_assignments)] +// failure-status: 101 + +fn might_fail_assert(one_plus_one: u32) { + println!("does 1 + 1 = {}?", one_plus_one); + assert_eq!(1 + 1, one_plus_one, "the argument was wrong"); +} + +fn main() -> Result<(), u8> { + let mut countdown = 10; + while countdown > 0 { + if countdown == 1 { + might_fail_assert(3); + } else if countdown < 5 { + might_fail_assert(2); + } + countdown -= 1; + } + Ok(()) +} + +// Notes: +// 1. Compare this program and its coverage results to those of the very similar test +// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`. +// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or +// related `assert_*!()` macro. +// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce +// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to +// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails). +// 4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test +// (and in many other coverage tests). The `Assert` terminator is typically generated by the +// Rust compiler to check for runtime failures, such as numeric overflows. diff --git a/tests/coverage-map/status-quo/async.cov-map b/tests/coverage-map/status-quo/async.cov-map new file mode 100644 index 0000000000000..5f28252ef806e --- /dev/null +++ b/tests/coverage-map/status-quo/async.cov-map @@ -0,0 +1,340 @@ +Function name: async::c +Raw bytes (9): 0x[01, 01, 00, 01, 01, 05, 01, 00, 19] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 25) + +Function name: async::c::{closure#0} +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 05, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 07, 02, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 5, 25) to (start + 1, 14) +- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 2, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: async::d +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0d, 01, 00, 14] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 20) + +Function name: async::d::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0d, 14, 00, 19] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 13, 20) to (start + 0, 25) + +Function name: async::e (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 14] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 20) + +Function name: async::e::{closure#0} (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 14, 00, 19] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 15, 20) to (start + 0, 25) + +Function name: async::executor::block_on::> +Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 6e, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero +- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 110, 5) to (start + 10, 54) +- Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35) + = ((c0 + c1) - c1) +- Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73) + = (c0 + c1) +- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26) + = (((c0 + c1) - c1) + Zero) +- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15) +- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) + = (((c0 + c1) - c1) + Zero) + +Function name: async::executor::block_on::VTABLE::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 72, 11, 00, 33] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 114, 17) to (start + 0, 51) + +Function name: async::executor::block_on::VTABLE::{closure#1} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 73, 11, 00, 33] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 115, 17) to (start + 0, 51) + +Function name: async::executor::block_on::VTABLE::{closure#2} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 74, 11, 00, 33] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 116, 17) to (start + 0, 51) + +Function name: async::executor::block_on::VTABLE::{closure#3} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 75, 11, 00, 13] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 117, 17) to (start + 0, 19) + +Function name: async::f +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 00, 14] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 20) + +Function name: async::f::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 14, 00, 19] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 17, 20) to (start + 0, 25) + +Function name: async::foo (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 00, 1e] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 30) + +Function name: async::foo::{closure#0} (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 1e, 00, 2d] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 19, 30) to (start + 0, 45) + +Function name: async::g +Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 00, 17] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 23) + +Function name: async::g::{closure#0} (unused) +Raw bytes (69): 0x[01, 01, 00, 0d, 00, 15, 17, 01, 0c, 00, 02, 09, 00, 0a, 01, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 13 +- Code(Zero) at (prev + 21, 23) to (start + 1, 12) +- Code(Zero) at (prev + 2, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17) +- Code(Zero) at (prev + 0, 18) to (start + 0, 23) +- Code(Zero) at (prev + 0, 27) to (start + 0, 28) +- Code(Zero) at (prev + 0, 32) to (start + 0, 34) +- Code(Zero) at (prev + 1, 9) to (start + 0, 10) +- Code(Zero) at (prev + 0, 14) to (start + 0, 17) +- Code(Zero) at (prev + 0, 18) to (start + 0, 23) +- Code(Zero) at (prev + 0, 27) to (start + 0, 28) +- Code(Zero) at (prev + 0, 32) to (start + 0, 34) +- Code(Zero) at (prev + 1, 14) to (start + 0, 16) +- Code(Zero) at (prev + 2, 1) to (start + 0, 2) + +Function name: async::h +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 00, 16] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 29, 1) to (start + 0, 22) + +Function name: async::h::{closure#0} (unused) +Raw bytes (44): 0x[01, 01, 00, 08, 00, 1d, 16, 03, 0c, 00, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 8 +- Code(Zero) at (prev + 29, 22) to (start + 3, 12) +- Code(Zero) at (prev + 4, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19) +- Code(Zero) at (prev + 0, 20) to (start + 0, 25) +- Code(Zero) at (prev + 0, 26) to (start + 0, 27) +- Code(Zero) at (prev + 0, 32) to (start + 0, 34) +- Code(Zero) at (prev + 1, 14) to (start + 0, 16) +- Code(Zero) at (prev + 2, 1) to (start + 0, 2) + +Function name: async::i +Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 01, 00, 13] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 38, 1) to (start + 0, 19) + +Function name: async::i::{closure#0} +Raw bytes (84): 0x[01, 01, 05, 01, 00, 0d, 00, 1d, 00, 19, 13, 1d, 21, 0e, 01, 26, 13, 04, 0c, 0d, 05, 09, 00, 0a, 03, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 07, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 0b, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 0f, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 1 operands: lhs = Counter(3), rhs = Zero +- expression 2 operands: lhs = Counter(7), rhs = Zero +- expression 3 operands: lhs = Counter(6), rhs = Expression(4, Add) +- expression 4 operands: lhs = Counter(7), rhs = Counter(8) +Number of file 0 mappings: 14 +- Code(Counter(0)) at (prev + 38, 19) to (start + 4, 12) +- Code(Counter(3)) at (prev + 5, 9) to (start + 0, 10) +- Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 18) + = (c0 + Zero) +- Code(Counter(1)) at (prev + 0, 19) to (start + 0, 24) +- Code(Counter(2)) at (prev + 0, 28) to (start + 0, 33) +- Code(Expression(1, Add)) at (prev + 0, 39) to (start + 0, 42) + = (c3 + Zero) +- Code(Counter(5)) at (prev + 0, 43) to (start + 0, 48) +- Code(Counter(7)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(4)) at (prev + 0, 14) to (start + 0, 17) +- Code(Counter(9)) at (prev + 0, 18) to (start + 0, 23) +- Code(Counter(10)) at (prev + 0, 27) to (start + 0, 32) +- Code(Expression(2, Add)) at (prev + 0, 36) to (start + 0, 38) + = (c7 + Zero) +- Code(Counter(8)) at (prev + 1, 14) to (start + 0, 16) +- Code(Expression(3, Add)) at (prev + 2, 1) to (start + 0, 2) + = (c6 + (c7 + c8)) + +Function name: async::j +Raw bytes (59): 0x[01, 01, 05, 01, 00, 05, 00, 09, 00, 05, 13, 09, 0d, 09, 01, 31, 01, 13, 0c, 05, 14, 09, 00, 0a, 03, 00, 0e, 00, 1b, 07, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 0b, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 0f, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 1 operands: lhs = Counter(1), rhs = Zero +- expression 2 operands: lhs = Counter(2), rhs = Zero +- expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add) +- expression 4 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 49, 1) to (start + 19, 12) +- Code(Counter(1)) at (prev + 20, 9) to (start + 0, 10) +- Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 27) + = (c0 + Zero) +- Code(Expression(1, Add)) at (prev + 0, 31) to (start + 0, 39) + = (c1 + Zero) +- Code(Counter(2)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(4)) at (prev + 0, 14) to (start + 0, 26) +- Code(Expression(2, Add)) at (prev + 0, 30) to (start + 0, 32) + = (c2 + Zero) +- Code(Counter(3)) at (prev + 1, 14) to (start + 0, 16) +- Code(Expression(3, Add)) at (prev + 2, 1) to (start + 0, 2) + = (c1 + (c2 + c3)) + +Function name: async::j::c +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 33, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 0a, 0d, 00, 0e, 07, 02, 05, 00, 06] +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 + 51, 5) to (start + 1, 18) +- Code(Counter(1)) at (prev + 2, 13) to (start + 0, 14) +- Code(Expression(0, Sub)) at (prev + 10, 13) to (start + 0, 14) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 2, 5) to (start + 0, 6) + = (c1 + (c0 - c1)) + +Function name: async::j::d +Raw bytes (9): 0x[01, 01, 00, 01, 01, 42, 05, 00, 17] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 66, 5) to (start + 0, 23) + +Function name: async::j::f +Raw bytes (9): 0x[01, 01, 00, 01, 01, 43, 05, 00, 17] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 67, 5) to (start + 0, 23) + +Function name: async::k (unused) +Raw bytes (29): 0x[01, 01, 00, 05, 01, 4b, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 75, 1) to (start + 1, 12) +- Code(Zero) at (prev + 2, 14) to (start + 0, 16) +- Code(Zero) at (prev + 1, 14) to (start + 0, 16) +- Code(Zero) at (prev + 1, 14) to (start + 0, 16) +- Code(Zero) at (prev + 2, 1) to (start + 0, 2) + +Function name: async::l +Raw bytes (37): 0x[01, 01, 04, 01, 07, 09, 05, 09, 0f, 05, 02, 05, 01, 53, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) +- expression 1 operands: lhs = Counter(2), rhs = Counter(1) +- expression 2 operands: lhs = Counter(2), rhs = Expression(3, Add) +- expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 83, 1) to (start + 1, 12) +- Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 16) + = (c0 - (c2 + c1)) +- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 16) +- Code(Counter(2)) at (prev + 1, 14) to (start + 0, 16) +- Code(Expression(2, Add)) at (prev + 2, 1) to (start + 0, 2) + = (c2 + (c1 + (c0 - (c2 + c1)))) + +Function name: async::m +Raw bytes (9): 0x[01, 01, 00, 01, 01, 5b, 01, 00, 19] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 91, 1) to (start + 0, 25) + +Function name: async::m::{closure#0} (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 5b, 19, 00, 22] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 91, 25) to (start + 0, 34) + +Function name: async::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 5d, 01, 08, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 93, 1) to (start + 8, 2) + diff --git a/tests/coverage-map/status-quo/async.rs b/tests/coverage-map/status-quo/async.rs new file mode 100644 index 0000000000000..efd9e62d64e1d --- /dev/null +++ b/tests/coverage-map/status-quo/async.rs @@ -0,0 +1,128 @@ +#![allow(unused_assignments, dead_code)] + +// compile-flags: --edition=2018 -C opt-level=1 + +async fn c(x: u8) -> u8 { + if x == 8 { + 1 + } else { + 0 + } +} + +async fn d() -> u8 { 1 } + +async fn e() -> u8 { 1 } // unused function; executor does not block on `g()` + +async fn f() -> u8 { 1 } + +async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()` + +pub async fn g(x: u8) { + match x { + y if e().await == y => (), + y if f().await == y => (), + _ => (), + } +} + +async fn h(x: usize) { // The function signature is counted when called, but the body is not + // executed (not awaited) so the open brace has a `0` count (at least when + // displayed with `llvm-cov show` in color-mode). + match x { + y if foo().await[y] => (), + _ => (), + } +} + +async fn i(x: u8) { // line coverage is 1, but there are 2 regions: + // (a) the function signature, counted when the function is called; and + // (b) the open brace for the function body, counted once when the body is + // executed asynchronously. + match x { + y if c(x).await == y + 1 => { d().await; } + y if f().await == y + 1 => (), + _ => (), + } +} + +fn j(x: u8) { + // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`. + fn c(x: u8) -> u8 { + if x == 8 { + 1 // This line appears covered, but the 1-character expression span covering the `1` + // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because + // `fn j()` executes the open brace for the function body, followed by the function's + // first executable statement, `match x`. Inner function declarations are not + // "visible" to the MIR for `j()`, so the code region counts all lines between the + // open brace and the first statement as executed, which is, in a sense, true. + // `llvm-cov show` overcomes this kind of situation by showing the actual counts + // of the enclosed coverages, (that is, the `1` expression was not executed, and + // accurately displays a `0`). + } else { + 0 + } + } + fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed + fn f() -> u8 { 1 } + match x { + y if c(x) == y + 1 => { d(); } + y if f() == y + 1 => (), + _ => (), + } +} + +fn k(x: u8) { // unused function + match x { + 1 => (), + 2 => (), + _ => (), + } +} + +fn l(x: u8) { + match x { + 1 => (), + 2 => (), + _ => (), + } +} + +async fn m(x: u8) -> u8 { x - 1 } + +fn main() { + let _ = g(10); + let _ = h(9); + let mut future = Box::pin(i(8)); + j(7); + l(6); + let _ = m(5); + executor::block_on(future.as_mut()); +} + +mod executor { + use core::{ + future::Future, + pin::Pin, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, + }; + + pub fn block_on(mut future: F) -> F::Output { + let mut future = unsafe { Pin::new_unchecked(&mut future) }; + use std::hint::unreachable_unchecked; + static VTABLE: RawWakerVTable = RawWakerVTable::new( + |_| unsafe { unreachable_unchecked() }, // clone + |_| unsafe { unreachable_unchecked() }, // wake + |_| unsafe { unreachable_unchecked() }, // wake_by_ref + |_| (), + ); + let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; + let mut context = Context::from_waker(&waker); + + loop { + if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + break val; + } + } + } +} diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage-map/status-quo/async2.cov-map new file mode 100644 index 0000000000000..fe74dcd88403f --- /dev/null +++ b/tests/coverage-map/status-quo/async2.cov-map @@ -0,0 +1,136 @@ +Function name: async2::async_func +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 00, 17] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 23) + +Function name: async2::async_func::{closure#0} +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0b, 17, 03, 09, 05, 03, 0a, 02, 06, 02, 02, 06, 00, 07, 07, 01, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 11, 23) to (start + 3, 9) +- Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: async2::async_func_just_println +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 00, 24] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 36) + +Function name: async2::async_func_just_println::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 24, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 19, 36) to (start + 2, 2) + +Function name: async2::executor::block_on:: +Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 27, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero +- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 39, 5) to (start + 10, 54) +- Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35) + = ((c0 + c1) - c1) +- Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73) + = (c0 + c1) +- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26) + = (((c0 + c1) - c1) + Zero) +- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15) +- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) + = (((c0 + c1) - c1) + Zero) + +Function name: async2::executor::block_on:: +Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 27, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero +- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 39, 5) to (start + 10, 54) +- Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35) + = ((c0 + c1) - c1) +- Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73) + = (c0 + c1) +- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26) + = (((c0 + c1) - c1) + Zero) +- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15) +- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) + = (((c0 + c1) - c1) + Zero) + +Function name: async2::executor::block_on::VTABLE::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2b, 11, 00, 33] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 43, 17) to (start + 0, 51) + +Function name: async2::executor::block_on::VTABLE::{closure#1} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 11, 00, 33] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 44, 17) to (start + 0, 51) + +Function name: async2::executor::block_on::VTABLE::{closure#2} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2d, 11, 00, 33] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 45, 17) to (start + 0, 51) + +Function name: async2::executor::block_on::VTABLE::{closure#3} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2e, 11, 00, 13] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 46, 17) to (start + 0, 19) + +Function name: async2::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 07, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 23, 1) to (start + 7, 2) + +Function name: async2::non_async_func +Raw bytes (26): 0x[01, 01, 01, 05, 00, 04, 01, 03, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 03, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(1), rhs = Zero +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 3, 1) to (start + 3, 9) +- Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + Zero) + diff --git a/tests/coverage-map/status-quo/async2.rs b/tests/coverage-map/status-quo/async2.rs new file mode 100644 index 0000000000000..2884ff297affd --- /dev/null +++ b/tests/coverage-map/status-quo/async2.rs @@ -0,0 +1,57 @@ +// compile-flags: --edition=2018 + +fn non_async_func() { + println!("non_async_func was covered"); + let b = true; + if b { + println!("non_async_func println in block"); + } +} + +async fn async_func() { + println!("async_func was covered"); + let b = true; + if b { + println!("async_func println in block"); + } +} + +async fn async_func_just_println() { + println!("async_func_just_println was covered"); +} + +fn main() { + println!("codecovsample::main"); + + non_async_func(); + + executor::block_on(async_func()); + executor::block_on(async_func_just_println()); +} + +mod executor { + use core::{ + future::Future, + pin::Pin, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, + }; + + pub fn block_on(mut future: F) -> F::Output { + let mut future = unsafe { Pin::new_unchecked(&mut future) }; + use std::hint::unreachable_unchecked; + static VTABLE: RawWakerVTable = RawWakerVTable::new( + |_| unsafe { unreachable_unchecked() }, // clone + |_| unsafe { unreachable_unchecked() }, // wake + |_| unsafe { unreachable_unchecked() }, // wake_by_ref + |_| (), + ); + let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; + let mut context = Context::from_waker(&waker); + + loop { + if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + break val; + } + } + } +} diff --git a/tests/coverage-map/status-quo/closure.cov-map b/tests/coverage-map/status-quo/closure.cov-map new file mode 100644 index 0000000000000..f3a32f091a91b --- /dev/null +++ b/tests/coverage-map/status-quo/closure.cov-map @@ -0,0 +1,324 @@ +Function name: closure::main +Raw bytes (170): 0x[01, 01, 17, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 05, 05, 5a, 01, 05, 18, 01, 08, 01, 0f, 0d, 03, 16, 0e, 06, 0a, 07, 10, 05, 13, 0d, 0b, 1a, 0e, 08, 09, 0f, 10, 05, 0e, 09, 13, 16, 05, 0d, 18, 17, 19, 09, 01, 21, 1b, 04, 09, 00, 29, 1f, 01, 09, 00, 2d, 23, 01, 09, 00, 24, 27, 05, 09, 00, 24, 2b, 02, 09, 00, 21, 2f, 04, 09, 00, 21, 33, 04, 09, 00, 28, 37, 09, 09, 00, 32, 3b, 04, 09, 00, 33, 3f, 07, 09, 00, 4b, 43, 08, 09, 01, 09, 47, 0a, 09, 01, 09, 4b, 08, 09, 01, 09, 4f, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 5a, 04, 06, 00, 07, 57, 01, 05, 03, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 23 +- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 1 operands: lhs = Counter(0), rhs = Zero +- expression 2 operands: lhs = Counter(0), rhs = Zero +- expression 3 operands: lhs = Counter(0), rhs = Zero +- expression 4 operands: lhs = Counter(0), rhs = Zero +- expression 5 operands: lhs = Counter(0), rhs = Zero +- expression 6 operands: lhs = Counter(0), rhs = Zero +- expression 7 operands: lhs = Counter(0), rhs = Zero +- expression 8 operands: lhs = Counter(0), rhs = Zero +- expression 9 operands: lhs = Counter(0), rhs = Zero +- expression 10 operands: lhs = Counter(0), rhs = Zero +- expression 11 operands: lhs = Counter(0), rhs = Zero +- expression 12 operands: lhs = Counter(0), rhs = Zero +- expression 13 operands: lhs = Counter(0), rhs = Zero +- expression 14 operands: lhs = Counter(0), rhs = Zero +- expression 15 operands: lhs = Counter(0), rhs = Zero +- expression 16 operands: lhs = Counter(0), rhs = Zero +- expression 17 operands: lhs = Counter(0), rhs = Zero +- expression 18 operands: lhs = Counter(0), rhs = Zero +- expression 19 operands: lhs = Counter(0), rhs = Zero +- expression 20 operands: lhs = Counter(0), rhs = Counter(1) +- expression 21 operands: lhs = Counter(1), rhs = Expression(22, Sub) +- expression 22 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 24 +- Code(Counter(0)) at (prev + 8, 1) to (start + 15, 13) +- Code(Expression(0, Add)) at (prev + 22, 14) to (start + 6, 10) + = (c0 + Zero) +- Code(Expression(1, Add)) at (prev + 16, 5) to (start + 19, 13) + = (c0 + Zero) +- Code(Expression(2, Add)) at (prev + 26, 14) to (start + 8, 9) + = (c0 + Zero) +- Code(Expression(3, Add)) at (prev + 16, 5) to (start + 14, 9) + = (c0 + Zero) +- Code(Expression(4, Add)) at (prev + 22, 5) to (start + 13, 24) + = (c0 + Zero) +- Code(Expression(5, Add)) at (prev + 25, 9) to (start + 1, 33) + = (c0 + Zero) +- Code(Expression(6, Add)) at (prev + 4, 9) to (start + 0, 41) + = (c0 + Zero) +- Code(Expression(7, Add)) at (prev + 1, 9) to (start + 0, 45) + = (c0 + Zero) +- Code(Expression(8, Add)) at (prev + 1, 9) to (start + 0, 36) + = (c0 + Zero) +- Code(Expression(9, Add)) at (prev + 5, 9) to (start + 0, 36) + = (c0 + Zero) +- Code(Expression(10, Add)) at (prev + 2, 9) to (start + 0, 33) + = (c0 + Zero) +- Code(Expression(11, Add)) at (prev + 4, 9) to (start + 0, 33) + = (c0 + Zero) +- Code(Expression(12, Add)) at (prev + 4, 9) to (start + 0, 40) + = (c0 + Zero) +- Code(Expression(13, Add)) at (prev + 9, 9) to (start + 0, 50) + = (c0 + Zero) +- Code(Expression(14, Add)) at (prev + 4, 9) to (start + 0, 51) + = (c0 + Zero) +- Code(Expression(15, Add)) at (prev + 7, 9) to (start + 0, 75) + = (c0 + Zero) +- Code(Expression(16, Add)) at (prev + 8, 9) to (start + 1, 9) + = (c0 + Zero) +- Code(Expression(17, Add)) at (prev + 10, 9) to (start + 1, 9) + = (c0 + Zero) +- Code(Expression(18, Add)) at (prev + 8, 9) to (start + 1, 9) + = (c0 + Zero) +- Code(Expression(19, Add)) at (prev + 10, 8) to (start + 0, 16) + = (c0 + Zero) +- Code(Counter(1)) at (prev + 0, 17) to (start + 4, 6) +- Code(Expression(22, Sub)) at (prev + 4, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(21, Add)) at (prev + 1, 5) to (start + 3, 2) + = (c1 + (c0 - c1)) + +Function name: closure::main::{closure#0} +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 27, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] +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 + 39, 5) to (start + 2, 20) +- Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) +- Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 9) to (start + 1, 6) + = (c1 + (c0 - c1)) + +Function name: closure::main::{closure#10} (unused) +Raw bytes (10): 0x[01, 01, 00, 01, 01, 9a, 01, 07, 00, 21] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 154, 7) to (start + 0, 33) + +Function name: closure::main::{closure#11} (unused) +Raw bytes (10): 0x[01, 01, 00, 01, 01, 9e, 01, 07, 00, 21] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 158, 7) to (start + 0, 33) + +Function name: closure::main::{closure#12} (unused) +Raw bytes (10): 0x[01, 01, 00, 01, 01, a6, 01, 01, 00, 17] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 166, 1) to (start + 0, 23) + +Function name: closure::main::{closure#13} (unused) +Raw bytes (10): 0x[01, 01, 00, 01, 01, ab, 01, 0d, 02, 0e] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 171, 13) to (start + 2, 14) + +Function name: closure::main::{closure#14} +Raw bytes (38): 0x[01, 01, 04, 05, 0a, 01, 05, 01, 05, 03, 00, 05, 03, b2, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 0f, 01, 0d, 00, 0e] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Expression(0, Add), rhs = Zero +Number of file 0 mappings: 5 +- Code(Expression(0, Add)) at (prev + 178, 13) to (start + 0, 21) + = (c1 + (c0 - c1)) +- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27) +- Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37) +- Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51) + = (c0 - c1) +- Code(Expression(3, Add)) at (prev + 1, 13) to (start + 0, 14) + = ((c1 + (c0 - c1)) + Zero) + +Function name: closure::main::{closure#15} +Raw bytes (45): 0x[01, 01, 05, 05, 0e, 01, 05, 01, 00, 01, 05, 03, 00, 06, 01, ba, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 0b, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0e, 00, 2f, 00, 33, 13, 02, 09, 00, 0a] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Counter(1), rhs = Expression(3, Sub) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +- expression 2 operands: lhs = Counter(0), rhs = Zero +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +- expression 4 operands: lhs = Expression(0, Add), rhs = Zero +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 186, 9) to (start + 0, 10) +- Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 21) + = (c1 + (c0 - c1)) +- Code(Expression(2, Add)) at (prev + 1, 17) to (start + 1, 27) + = (c0 + Zero) +- Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37) +- Code(Expression(3, Sub)) at (prev + 0, 47) to (start + 0, 51) + = (c0 - c1) +- Code(Expression(4, Add)) at (prev + 2, 9) to (start + 0, 10) + = ((c1 + (c0 - c1)) + Zero) + +Function name: closure::main::{closure#16} +Raw bytes (38): 0x[01, 01, 04, 05, 0a, 01, 05, 01, 05, 03, 00, 05, 03, c4, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 0f, 01, 0d, 00, 0e] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Expression(0, Add), rhs = Zero +Number of file 0 mappings: 5 +- Code(Expression(0, Add)) at (prev + 196, 13) to (start + 0, 21) + = (c1 + (c0 - c1)) +- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27) +- Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37) +- Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51) + = (c0 - c1) +- Code(Expression(3, Add)) at (prev + 1, 13) to (start + 0, 14) + = ((c1 + (c0 - c1)) + Zero) + +Function name: closure::main::{closure#17} +Raw bytes (45): 0x[01, 01, 05, 05, 0e, 01, 05, 01, 00, 01, 05, 03, 00, 06, 01, cc, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 0b, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0e, 00, 2f, 00, 33, 13, 02, 09, 00, 0a] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Counter(1), rhs = Expression(3, Sub) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +- expression 2 operands: lhs = Counter(0), rhs = Zero +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +- expression 4 operands: lhs = Expression(0, Add), rhs = Zero +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 204, 9) to (start + 0, 10) +- Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 21) + = (c1 + (c0 - c1)) +- Code(Expression(2, Add)) at (prev + 1, 17) to (start + 1, 27) + = (c0 + Zero) +- Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37) +- Code(Expression(3, Sub)) at (prev + 0, 47) to (start + 0, 51) + = (c0 - c1) +- Code(Expression(4, Add)) at (prev + 2, 9) to (start + 0, 10) + = ((c1 + (c0 - c1)) + Zero) + +Function name: closure::main::{closure#18} +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 18, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] +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 + 24, 13) to (start + 2, 28) +- Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) +- Code(Expression(0, Sub)) at (prev + 2, 18) to (start + 0, 19) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 17) to (start + 1, 14) + = (c1 + (c0 - c1)) + +Function name: closure::main::{closure#19} +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 42, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] +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 + 66, 13) to (start + 2, 28) +- Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) +- Code(Expression(0, Sub)) at (prev + 2, 18) to (start + 0, 19) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 17) to (start + 1, 14) + = (c1 + (c0 - c1)) + +Function name: closure::main::{closure#1} +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 51, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] +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 + 81, 5) to (start + 2, 20) +- Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) +- Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 9) to (start + 1, 6) + = (c1 + (c0 - c1)) + +Function name: closure::main::{closure#2} +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 67, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] +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 + 103, 5) to (start + 2, 20) +- Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) +- Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 9) to (start + 1, 6) + = (c1 + (c0 - c1)) + +Function name: closure::main::{closure#3} (unused) +Raw bytes (25): 0x[01, 01, 00, 04, 01, 80, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 128, 5) to (start + 1, 20) +- Code(Zero) at (prev + 1, 21) to (start + 2, 10) +- Code(Zero) at (prev + 2, 10) to (start + 0, 11) +- Code(Zero) at (prev + 1, 9) to (start + 1, 6) + +Function name: closure::main::{closure#4} (unused) +Raw bytes (10): 0x[01, 01, 00, 01, 01, 88, 01, 35, 00, 43] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 136, 53) to (start + 0, 67) + +Function name: closure::main::{closure#5} +Raw bytes (10): 0x[01, 01, 00, 01, 01, 8b, 01, 3d, 00, 4f] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 139, 61) to (start + 0, 79) + +Function name: closure::main::{closure#6} +Raw bytes (10): 0x[01, 01, 00, 01, 01, 8c, 01, 41, 00, 57] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 140, 65) to (start + 0, 87) + +Function name: closure::main::{closure#7} (unused) +Raw bytes (10): 0x[01, 01, 00, 01, 01, 8d, 01, 3b, 00, 51] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 141, 59) to (start + 0, 81) + +Function name: closure::main::{closure#8} (unused) +Raw bytes (10): 0x[01, 01, 00, 01, 01, 92, 01, 3b, 00, 55] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 146, 59) to (start + 0, 85) + +Function name: closure::main::{closure#9} (unused) +Raw bytes (10): 0x[01, 01, 00, 01, 01, 94, 01, 38, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 148, 56) to (start + 2, 6) + diff --git a/tests/coverage-map/status-quo/closure.rs b/tests/coverage-map/status-quo/closure.rs new file mode 100644 index 0000000000000..16a2c4e33bd48 --- /dev/null +++ b/tests/coverage-map/status-quo/closure.rs @@ -0,0 +1,220 @@ +#![allow(unused_assignments, unused_variables)] +// compile-flags: -C opt-level=2 + +// This test used to be sensitive to certain coverage-specific hacks in +// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by +// . + +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + let is_false = !is_true; + + let mut some_string = Some(String::from("the string content")); + println!( + "The string or alt: {}" + , + some_string + . + unwrap_or_else + ( + || + { + let mut countdown = 0; + if is_false { + countdown = 10; + } + "alt string 1".to_owned() + } + ) + ); + + some_string = Some(String::from("the string content")); + let + a + = + || + { + let mut countdown = 0; + if is_false { + countdown = 10; + } + "alt string 2".to_owned() + }; + println!( + "The string or alt: {}" + , + some_string + . + unwrap_or_else + ( + a + ) + ); + + some_string = None; + println!( + "The string or alt: {}" + , + some_string + . + unwrap_or_else + ( + || + { + let mut countdown = 0; + if is_false { + countdown = 10; + } + "alt string 3".to_owned() + } + ) + ); + + some_string = None; + let + a + = + || + { + let mut countdown = 0; + if is_false { + countdown = 10; + } + "alt string 4".to_owned() + }; + println!( + "The string or alt: {}" + , + some_string + . + unwrap_or_else + ( + a + ) + ); + + let + quote_closure + = + |val| + { + let mut countdown = 0; + if is_false { + countdown = 10; + } + format!("'{}'", val) + }; + println!( + "Repeated, quoted string: {:?}" + , + std::iter::repeat("repeat me") + .take(5) + .map + ( + quote_closure + ) + .collect::>() + ); + + let + _unused_closure + = + | + mut countdown + | + { + if is_false { + countdown = 10; + } + "closure should be unused".to_owned() + }; + + let mut countdown = 10; + let _short_unused_closure = | _unused_arg: u8 | countdown += 1; + + + let short_used_covered_closure_macro = | used_arg: u8 | println!("called"); + let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called"); + let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called"); + + + + + let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") }; + + let _shortish_unused_closure = | _unused_arg: u8 | { + println!("not called") + }; + + let _as_short_unused_closure = | + _unused_arg: u8 + | { println!("not called") }; + + let _almost_as_short_unused_closure = | + _unused_arg: u8 + | { println!("not called") } + ; + + + + + + let _short_unused_closure_line_break_no_block = | _unused_arg: u8 | +println!("not called") + ; + + let _short_unused_closure_line_break_no_block2 = + | _unused_arg: u8 | + println!( + "not called" + ) + ; + + let short_used_not_covered_closure_line_break_no_block_embedded_branch = + | _unused_arg: u8 | + println!( + "not called: {}", + if is_true { "check" } else { "me" } + ) + ; + + let short_used_not_covered_closure_line_break_block_embedded_branch = + | _unused_arg: u8 | + { + println!( + "not called: {}", + if is_true { "check" } else { "me" } + ) + } + ; + + let short_used_covered_closure_line_break_no_block_embedded_branch = + | _unused_arg: u8 | + println!( + "not called: {}", + if is_true { "check" } else { "me" } + ) + ; + + let short_used_covered_closure_line_break_block_embedded_branch = + | _unused_arg: u8 | + { + println!( + "not called: {}", + if is_true { "check" } else { "me" } + ) + } + ; + + if is_false { + short_used_not_covered_closure_macro(0); + short_used_not_covered_closure_line_break_no_block_embedded_branch(0); + short_used_not_covered_closure_line_break_block_embedded_branch(0); + } + short_used_covered_closure_macro(0); + short_used_covered_closure_line_break_no_block_embedded_branch(0); + short_used_covered_closure_line_break_block_embedded_branch(0); +} diff --git a/tests/coverage-map/status-quo/closure_macro.cov-map b/tests/coverage-map/status-quo/closure_macro.cov-map new file mode 100644 index 0000000000000..ac017eb446818 --- /dev/null +++ b/tests/coverage-map/status-quo/closure_macro.cov-map @@ -0,0 +1,40 @@ +Function name: closure_macro::load_configuration_files +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) + +Function name: closure_macro::main +Raw bytes (49): 0x[01, 01, 05, 01, 05, 02, 00, 05, 00, 02, 00, 05, 02, 07, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 07, 00, 12, 00, 13, 0b, 00, 54, 00, 55, 0f, 02, 09, 02, 0b, 13, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(0, Sub), rhs = Zero +- expression 2 operands: lhs = Counter(1), rhs = Zero +- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero +- expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) + = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- Code(Expression(1, Add)) at (prev + 0, 18) to (start + 0, 19) + = ((c0 - c1) + Zero) +- Code(Expression(2, Add)) at (prev + 0, 84) to (start + 0, 85) + = (c1 + Zero) +- Code(Expression(3, Add)) at (prev + 2, 9) to (start + 2, 11) + = ((c0 - c1) + Zero) +- Code(Expression(4, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: closure_macro::main::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 12, 00, 54] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 35, 18) to (start + 0, 84) + diff --git a/tests/coverage-map/status-quo/closure_macro.rs b/tests/coverage-map/status-quo/closure_macro.rs new file mode 100644 index 0000000000000..5e3b00d1ef54b --- /dev/null +++ b/tests/coverage-map/status-quo/closure_macro.rs @@ -0,0 +1,40 @@ +// compile-flags: --edition=2018 +#![feature(no_coverage)] + +macro_rules! bail { + ($msg:literal $(,)?) => { + if $msg.len() > 0 { + println!("no msg"); + } else { + println!($msg); + } + return Err(String::from($msg)); + }; +} + +macro_rules! on_error { + ($value:expr, $error_message:expr) => { + $value.or_else(|e| { // FIXME(85000): no coverage in closure macros + let message = format!($error_message, e); + if message.len() > 0 { + println!("{}", message); + Ok(String::from("ok")) + } else { + bail!("error"); + } + }) + }; +} + +fn load_configuration_files() -> Result { + Ok(String::from("config")) +} + +pub fn main() -> Result<(), String> { + println!("Starting service"); + let config = on_error!(load_configuration_files(), "Error loading configs: {}")?; + + let startup_delay_duration = String::from("arg"); + let _ = (config, startup_delay_duration); + Ok(()) +} diff --git a/tests/coverage-map/status-quo/closure_macro_async.cov-map b/tests/coverage-map/status-quo/closure_macro_async.cov-map new file mode 100644 index 0000000000000..c9a142e5aebcd --- /dev/null +++ b/tests/coverage-map/status-quo/closure_macro_async.cov-map @@ -0,0 +1,48 @@ +Function name: closure_macro_async::load_configuration_files +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) + +Function name: closure_macro_async::test +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 00, 2b] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 43) + +Function name: closure_macro_async::test::{closure#0} +Raw bytes (49): 0x[01, 01, 05, 01, 05, 02, 00, 05, 00, 02, 00, 05, 02, 07, 01, 21, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 07, 00, 12, 00, 13, 0b, 00, 54, 00, 55, 0f, 02, 09, 02, 0b, 13, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(0, Sub), rhs = Zero +- expression 2 operands: lhs = Counter(1), rhs = Zero +- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero +- expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 33, 43) to (start + 1, 33) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) + = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- Code(Expression(1, Add)) at (prev + 0, 18) to (start + 0, 19) + = ((c0 - c1) + Zero) +- Code(Expression(2, Add)) at (prev + 0, 84) to (start + 0, 85) + = (c1 + Zero) +- Code(Expression(3, Add)) at (prev + 2, 9) to (start + 2, 11) + = ((c0 - c1) + Zero) +- Code(Expression(4, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: closure_macro_async::test::{closure#0}::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 12, 00, 54] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 35, 18) to (start + 0, 84) + diff --git a/tests/coverage-map/status-quo/closure_macro_async.rs b/tests/coverage-map/status-quo/closure_macro_async.rs new file mode 100644 index 0000000000000..3d6bdb38a2ab1 --- /dev/null +++ b/tests/coverage-map/status-quo/closure_macro_async.rs @@ -0,0 +1,77 @@ +// compile-flags: --edition=2018 +#![feature(no_coverage)] + +macro_rules! bail { + ($msg:literal $(,)?) => { + if $msg.len() > 0 { + println!("no msg"); + } else { + println!($msg); + } + return Err(String::from($msg)); + }; +} + +macro_rules! on_error { + ($value:expr, $error_message:expr) => { + $value.or_else(|e| { // FIXME(85000): no coverage in closure macros + let message = format!($error_message, e); + if message.len() > 0 { + println!("{}", message); + Ok(String::from("ok")) + } else { + bail!("error"); + } + }) + }; +} + +fn load_configuration_files() -> Result { + Ok(String::from("config")) +} + +pub async fn test() -> Result<(), String> { + println!("Starting service"); + let config = on_error!(load_configuration_files(), "Error loading configs: {}")?; + + let startup_delay_duration = String::from("arg"); + let _ = (config, startup_delay_duration); + Ok(()) +} + +#[no_coverage] +fn main() { + executor::block_on(test()).unwrap(); +} + +mod executor { + use core::{ + future::Future, + pin::Pin, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, + }; + + #[no_coverage] + pub fn block_on(mut future: F) -> F::Output { + let mut future = unsafe { Pin::new_unchecked(&mut future) }; + use std::hint::unreachable_unchecked; + static VTABLE: RawWakerVTable = RawWakerVTable::new( + #[no_coverage] + |_| unsafe { unreachable_unchecked() }, // clone + #[no_coverage] + |_| unsafe { unreachable_unchecked() }, // wake + #[no_coverage] + |_| unsafe { unreachable_unchecked() }, // wake_by_ref + #[no_coverage] + |_| (), + ); + let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; + let mut context = Context::from_waker(&waker); + + loop { + if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + break val; + } + } + } +} diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage-map/status-quo/conditions.cov-map new file mode 100644 index 0000000000000..d82b8389b4d0b --- /dev/null +++ b/tests/coverage-map/status-quo/conditions.cov-map @@ -0,0 +1,261 @@ +Function name: conditions::main +Raw bytes (793): 0x[01, 01, 90, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, bf, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, ba, 04, 0d, bf, 04, 09, 05, 00, 03, 00, 45, 00, 87, 01, 49, 45, 00, 82, 01, 31, 87, 01, 49, 45, 00, 7e, 4d, 82, 01, 31, 87, 01, 49, 45, 00, 7a, 51, 7e, 4d, 82, 01, 31, 87, 01, 49, 45, 00, ab, 01, 55, 4d, 51, a7, 01, 59, ab, 01, 55, 4d, 51, 49, a3, 01, a7, 01, 59, ab, 01, 55, 4d, 51, 61, 00, e7, 01, 65, 61, 00, e2, 01, 2d, e7, 01, 65, 61, 00, de, 01, 69, e2, 01, 2d, e7, 01, 65, 61, 00, da, 01, 6d, de, 01, 69, e2, 01, 2d, e7, 01, 65, 61, 00, 8f, 02, 71, 69, 6d, 8b, 02, 75, 8f, 02, 71, 69, 6d, 83, 02, 00, 65, 87, 02, 8b, 02, 75, 8f, 02, 71, 69, 6d, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, 79, 00, db, 02, 7d, 79, 00, d6, 02, 29, db, 02, 7d, 79, 00, d2, 02, 81, 01, d6, 02, 29, db, 02, 7d, 79, 00, ce, 02, 85, 01, d2, 02, 81, 01, d6, 02, 29, db, 02, 7d, 79, 00, fb, 03, 89, 01, 81, 01, 85, 01, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, 11, 9b, 04, 9f, 04, 21, a3, 04, 1d, 15, 19, ef, 03, 00, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, ea, 03, 25, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, e6, 03, 15, ea, 03, 25, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, e2, 03, 19, e6, 03, 15, ea, 03, 25, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, a3, 04, 1d, 15, 19, 9f, 04, 21, a3, 04, 1d, 15, 19, 97, 04, a7, 04, 11, 9b, 04, 9f, 04, 21, a3, 04, 1d, 15, 19, ab, 04, b6, 04, af, 04, b3, 04, 25, 29, 2d, 31, ba, 04, 0d, bf, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, bf, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, ba, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, b6, 04, 03, 09, 00, 0f, 4b, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 87, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 82, 01, 02, 0f, 00, 1c, 7e, 01, 0c, 00, 19, 7a, 00, 1d, 00, 2a, 76, 00, 2e, 00, 3c, a7, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, a3, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9f, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e7, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, e2, 01, 03, 11, 00, 1e, de, 01, 01, 10, 00, 1d, da, 01, 00, 21, 00, 2e, d6, 01, 00, 32, 00, 40, 8b, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 87, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, ff, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, ef, 03, 02, 09, 00, 0a, db, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d6, 02, 02, 0f, 00, 1c, d2, 02, 01, 0c, 00, 19, ce, 02, 00, 1d, 00, 2a, ca, 02, 00, 2e, 00, 3c, f7, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, f3, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 97, 04, 05, 09, 00, 0a, 83, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, ea, 03, 02, 0f, 00, 1c, e6, 03, 01, 0c, 00, 19, e2, 03, 00, 1d, 00, 2a, de, 03, 00, 2e, 00, 3c, 9f, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 9b, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 93, 04, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 144 +- expression 0 operands: lhs = Counter(2), rhs = Expression(12, Add) +- expression 1 operands: lhs = Expression(13, Add), rhs = Counter(16) +- expression 2 operands: lhs = Expression(14, Add), rhs = Counter(15) +- expression 3 operands: lhs = Counter(13), rhs = Counter(14) +- expression 4 operands: lhs = Counter(1), rhs = Zero +- expression 5 operands: lhs = Expression(143, Add), rhs = Counter(2) +- expression 6 operands: lhs = Counter(1), rhs = Zero +- expression 7 operands: lhs = Counter(3), rhs = Counter(13) +- expression 8 operands: lhs = Expression(9, Sub), rhs = Counter(14) +- expression 9 operands: lhs = Counter(3), rhs = Counter(13) +- expression 10 operands: lhs = Expression(14, Add), rhs = Counter(15) +- expression 11 operands: lhs = Counter(13), rhs = Counter(14) +- expression 12 operands: lhs = Expression(13, Add), rhs = Counter(16) +- expression 13 operands: lhs = Expression(14, Add), rhs = Counter(15) +- expression 14 operands: lhs = Counter(13), rhs = Counter(14) +- expression 15 operands: lhs = Expression(142, Sub), rhs = Counter(3) +- expression 16 operands: lhs = Expression(143, Add), rhs = Counter(2) +- expression 17 operands: lhs = Counter(1), rhs = Zero +- expression 18 operands: lhs = Expression(0, Add), rhs = Zero +- expression 19 operands: lhs = Counter(17), rhs = Zero +- expression 20 operands: lhs = Expression(33, Add), rhs = Counter(18) +- expression 21 operands: lhs = Counter(17), rhs = Zero +- expression 22 operands: lhs = Expression(32, Sub), rhs = Counter(12) +- expression 23 operands: lhs = Expression(33, Add), rhs = Counter(18) +- expression 24 operands: lhs = Counter(17), rhs = Zero +- expression 25 operands: lhs = Expression(31, Sub), rhs = Counter(19) +- expression 26 operands: lhs = Expression(32, Sub), rhs = Counter(12) +- expression 27 operands: lhs = Expression(33, Add), rhs = Counter(18) +- expression 28 operands: lhs = Counter(17), rhs = Zero +- expression 29 operands: lhs = Expression(30, Sub), rhs = Counter(20) +- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(19) +- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(12) +- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(18) +- expression 33 operands: lhs = Counter(17), rhs = Zero +- expression 34 operands: lhs = Expression(42, Add), rhs = Counter(21) +- expression 35 operands: lhs = Counter(19), rhs = Counter(20) +- expression 36 operands: lhs = Expression(41, Add), rhs = Counter(22) +- expression 37 operands: lhs = Expression(42, Add), rhs = Counter(21) +- expression 38 operands: lhs = Counter(19), rhs = Counter(20) +- expression 39 operands: lhs = Counter(18), rhs = Expression(40, Add) +- expression 40 operands: lhs = Expression(41, Add), rhs = Counter(22) +- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(21) +- expression 42 operands: lhs = Counter(19), rhs = Counter(20) +- expression 43 operands: lhs = Counter(24), rhs = Zero +- expression 44 operands: lhs = Expression(57, Add), rhs = Counter(25) +- expression 45 operands: lhs = Counter(24), rhs = Zero +- expression 46 operands: lhs = Expression(56, Sub), rhs = Counter(11) +- expression 47 operands: lhs = Expression(57, Add), rhs = Counter(25) +- expression 48 operands: lhs = Counter(24), rhs = Zero +- expression 49 operands: lhs = Expression(55, Sub), rhs = Counter(26) +- expression 50 operands: lhs = Expression(56, Sub), rhs = Counter(11) +- expression 51 operands: lhs = Expression(57, Add), rhs = Counter(25) +- expression 52 operands: lhs = Counter(24), rhs = Zero +- expression 53 operands: lhs = Expression(54, Sub), rhs = Counter(27) +- expression 54 operands: lhs = Expression(55, Sub), rhs = Counter(26) +- expression 55 operands: lhs = Expression(56, Sub), rhs = Counter(11) +- expression 56 operands: lhs = Expression(57, Add), rhs = Counter(25) +- expression 57 operands: lhs = Counter(24), rhs = Zero +- expression 58 operands: lhs = Expression(67, Add), rhs = Counter(28) +- expression 59 operands: lhs = Counter(26), rhs = Counter(27) +- expression 60 operands: lhs = Expression(66, Add), rhs = Counter(29) +- expression 61 operands: lhs = Expression(67, Add), rhs = Counter(28) +- expression 62 operands: lhs = Counter(26), rhs = Counter(27) +- expression 63 operands: lhs = Expression(64, Add), rhs = Zero +- expression 64 operands: lhs = Counter(25), rhs = Expression(65, Add) +- expression 65 operands: lhs = Expression(66, Add), rhs = Counter(29) +- expression 66 operands: lhs = Expression(67, Add), rhs = Counter(28) +- expression 67 operands: lhs = Counter(26), rhs = Counter(27) +- expression 68 operands: lhs = Counter(31), rhs = Expression(124, Add) +- expression 69 operands: lhs = Expression(125, Add), rhs = Counter(35) +- expression 70 operands: lhs = Expression(126, Add), rhs = Counter(34) +- expression 71 operands: lhs = Counter(32), rhs = Counter(33) +- expression 72 operands: lhs = Counter(30), rhs = Zero +- expression 73 operands: lhs = Expression(86, Add), rhs = Counter(31) +- expression 74 operands: lhs = Counter(30), rhs = Zero +- expression 75 operands: lhs = Expression(85, Sub), rhs = Counter(10) +- expression 76 operands: lhs = Expression(86, Add), rhs = Counter(31) +- expression 77 operands: lhs = Counter(30), rhs = Zero +- expression 78 operands: lhs = Expression(84, Sub), rhs = Counter(32) +- expression 79 operands: lhs = Expression(85, Sub), rhs = Counter(10) +- expression 80 operands: lhs = Expression(86, Add), rhs = Counter(31) +- expression 81 operands: lhs = Counter(30), rhs = Zero +- expression 82 operands: lhs = Expression(83, Sub), rhs = Counter(33) +- expression 83 operands: lhs = Expression(84, Sub), rhs = Counter(32) +- expression 84 operands: lhs = Expression(85, Sub), rhs = Counter(10) +- expression 85 operands: lhs = Expression(86, Add), rhs = Counter(31) +- expression 86 operands: lhs = Counter(30), rhs = Zero +- expression 87 operands: lhs = Expression(126, Add), rhs = Counter(34) +- expression 88 operands: lhs = Counter(32), rhs = Counter(33) +- expression 89 operands: lhs = Expression(125, Add), rhs = Counter(35) +- expression 90 operands: lhs = Expression(126, Add), rhs = Counter(34) +- expression 91 operands: lhs = Counter(32), rhs = Counter(33) +- expression 92 operands: lhs = Counter(4), rhs = Expression(134, Add) +- expression 93 operands: lhs = Expression(135, Add), rhs = Counter(8) +- expression 94 operands: lhs = Expression(136, Add), rhs = Counter(7) +- expression 95 operands: lhs = Counter(5), rhs = Counter(6) +- expression 96 operands: lhs = Expression(123, Add), rhs = Zero +- expression 97 operands: lhs = Counter(31), rhs = Expression(124, Add) +- expression 98 operands: lhs = Expression(125, Add), rhs = Counter(35) +- expression 99 operands: lhs = Expression(126, Add), rhs = Counter(34) +- expression 100 operands: lhs = Counter(32), rhs = Counter(33) +- expression 101 operands: lhs = Expression(123, Add), rhs = Counter(4) +- expression 102 operands: lhs = Counter(31), rhs = Expression(124, Add) +- expression 103 operands: lhs = Expression(125, Add), rhs = Counter(35) +- expression 104 operands: lhs = Expression(126, Add), rhs = Counter(34) +- expression 105 operands: lhs = Counter(32), rhs = Counter(33) +- expression 106 operands: lhs = Expression(122, Sub), rhs = Counter(9) +- expression 107 operands: lhs = Expression(123, Add), rhs = Counter(4) +- expression 108 operands: lhs = Counter(31), rhs = Expression(124, Add) +- expression 109 operands: lhs = Expression(125, Add), rhs = Counter(35) +- expression 110 operands: lhs = Expression(126, Add), rhs = Counter(34) +- expression 111 operands: lhs = Counter(32), rhs = Counter(33) +- expression 112 operands: lhs = Expression(121, Sub), rhs = Counter(5) +- expression 113 operands: lhs = Expression(122, Sub), rhs = Counter(9) +- expression 114 operands: lhs = Expression(123, Add), rhs = Counter(4) +- expression 115 operands: lhs = Counter(31), rhs = Expression(124, Add) +- expression 116 operands: lhs = Expression(125, Add), rhs = Counter(35) +- expression 117 operands: lhs = Expression(126, Add), rhs = Counter(34) +- expression 118 operands: lhs = Counter(32), rhs = Counter(33) +- expression 119 operands: lhs = Expression(120, Sub), rhs = Counter(6) +- expression 120 operands: lhs = Expression(121, Sub), rhs = Counter(5) +- expression 121 operands: lhs = Expression(122, Sub), rhs = Counter(9) +- expression 122 operands: lhs = Expression(123, Add), rhs = Counter(4) +- expression 123 operands: lhs = Counter(31), rhs = Expression(124, Add) +- expression 124 operands: lhs = Expression(125, Add), rhs = Counter(35) +- expression 125 operands: lhs = Expression(126, Add), rhs = Counter(34) +- expression 126 operands: lhs = Counter(32), rhs = Counter(33) +- expression 127 operands: lhs = Expression(136, Add), rhs = Counter(7) +- expression 128 operands: lhs = Counter(5), rhs = Counter(6) +- expression 129 operands: lhs = Expression(135, Add), rhs = Counter(8) +- expression 130 operands: lhs = Expression(136, Add), rhs = Counter(7) +- expression 131 operands: lhs = Counter(5), rhs = Counter(6) +- expression 132 operands: lhs = Expression(133, Add), rhs = Expression(137, Add) +- expression 133 operands: lhs = Counter(4), rhs = Expression(134, Add) +- expression 134 operands: lhs = Expression(135, Add), rhs = Counter(8) +- expression 135 operands: lhs = Expression(136, Add), rhs = Counter(7) +- expression 136 operands: lhs = Counter(5), rhs = Counter(6) +- expression 137 operands: lhs = Expression(138, Add), rhs = Expression(141, Sub) +- expression 138 operands: lhs = Expression(139, Add), rhs = Expression(140, Add) +- expression 139 operands: lhs = Counter(9), rhs = Counter(10) +- expression 140 operands: lhs = Counter(11), rhs = Counter(12) +- expression 141 operands: lhs = Expression(142, Sub), rhs = Counter(3) +- expression 142 operands: lhs = Expression(143, Add), rhs = Counter(2) +- expression 143 operands: lhs = Counter(1), rhs = Zero +Number of file 0 mappings: 68 +- Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) +- Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Add)) at (prev + 3, 9) to (start + 0, 10) + = (c2 + (((c13 + c14) + c15) + c16)) +- Code(Expression(143, Add)) at (prev + 0, 16) to (start + 0, 29) + = (c1 + Zero) +- Code(Counter(2)) at (prev + 1, 9) to (start + 1, 10) +- Code(Expression(142, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c1 + Zero) - c2) +- Code(Counter(3)) at (prev + 1, 12) to (start + 0, 25) +- Code(Expression(9, Sub)) at (prev + 0, 29) to (start + 0, 42) + = (c3 - c13) +- Code(Expression(8, Sub)) at (prev + 0, 46) to (start + 0, 60) + = ((c3 - c13) - c14) +- Code(Expression(13, Add)) at (prev + 0, 61) to (start + 2, 10) + = ((c13 + c14) + c15) +- Code(Counter(16)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(12, Add)) at (prev + 1, 9) to (start + 1, 18) + = (((c13 + c14) + c15) + c16) +- Code(Expression(141, Sub)) at (prev + 3, 9) to (start + 0, 15) + = (((c1 + Zero) - c2) - c3) +- Code(Expression(18, Add)) at (prev + 3, 9) to (start + 1, 12) + = ((c2 + (((c13 + c14) + c15) + c16)) + Zero) +- Code(Counter(17)) at (prev + 1, 13) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(33, Add)) at (prev + 2, 8) to (start + 0, 21) + = (c17 + Zero) +- Code(Counter(18)) at (prev + 0, 22) to (start + 2, 6) +- Code(Expression(32, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c17 + Zero) - c18) +- Code(Expression(31, Sub)) at (prev + 1, 12) to (start + 0, 25) + = (((c17 + Zero) - c18) - c12) +- Code(Expression(30, Sub)) at (prev + 0, 29) to (start + 0, 42) + = ((((c17 + Zero) - c18) - c12) - c19) +- Code(Expression(29, Sub)) at (prev + 0, 46) to (start + 0, 60) + = (((((c17 + Zero) - c18) - c12) - c19) - c20) +- Code(Expression(41, Add)) at (prev + 0, 61) to (start + 2, 10) + = ((c19 + c20) + c21) +- Code(Counter(22)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(40, Add)) at (prev + 1, 9) to (start + 0, 23) + = (((c19 + c20) + c21) + c22) +- Code(Counter(12)) at (prev + 2, 9) to (start + 0, 15) +- Code(Expression(39, Add)) at (prev + 3, 8) to (start + 0, 12) + = (c18 + (((c19 + c20) + c21) + c22)) +- Code(Counter(23)) at (prev + 1, 13) to (start + 1, 16) +- Code(Counter(24)) at (prev + 1, 17) to (start + 2, 10) +- Code(Zero) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(57, Add)) at (prev + 2, 12) to (start + 0, 25) + = (c24 + Zero) +- Code(Counter(25)) at (prev + 0, 26) to (start + 2, 10) +- Code(Expression(56, Sub)) at (prev + 3, 17) to (start + 0, 30) + = ((c24 + Zero) - c25) +- Code(Expression(55, Sub)) at (prev + 1, 16) to (start + 0, 29) + = (((c24 + Zero) - c25) - c11) +- Code(Expression(54, Sub)) at (prev + 0, 33) to (start + 0, 46) + = ((((c24 + Zero) - c25) - c11) - c26) +- Code(Expression(53, Sub)) at (prev + 0, 50) to (start + 0, 64) + = (((((c24 + Zero) - c25) - c11) - c26) - c27) +- Code(Expression(66, Add)) at (prev + 0, 65) to (start + 2, 14) + = ((c26 + c27) + c28) +- Code(Counter(29)) at (prev + 2, 14) to (start + 0, 15) +- Code(Expression(65, Add)) at (prev + 1, 13) to (start + 0, 27) + = (((c26 + c27) + c28) + c29) +- Code(Counter(11)) at (prev + 2, 13) to (start + 0, 19) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(63, Add)) at (prev + 2, 9) to (start + 1, 12) + = ((c25 + (((c26 + c27) + c28) + c29)) + Zero) +- Code(Counter(30)) at (prev + 1, 13) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(123, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c31 + (((c32 + c33) + c34) + c35)) +- Code(Expression(86, Add)) at (prev + 0, 16) to (start + 0, 29) + = (c30 + Zero) +- Code(Counter(31)) at (prev + 0, 30) to (start + 2, 6) +- Code(Expression(85, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c30 + Zero) - c31) +- Code(Expression(84, Sub)) at (prev + 1, 12) to (start + 0, 25) + = (((c30 + Zero) - c31) - c10) +- Code(Expression(83, Sub)) at (prev + 0, 29) to (start + 0, 42) + = ((((c30 + Zero) - c31) - c10) - c32) +- Code(Expression(82, Sub)) at (prev + 0, 46) to (start + 0, 60) + = (((((c30 + Zero) - c31) - c10) - c32) - c33) +- Code(Expression(125, Add)) at (prev + 0, 61) to (start + 2, 10) + = ((c32 + c33) + c34) +- Code(Counter(35)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(124, Add)) at (prev + 1, 9) to (start + 0, 23) + = (((c32 + c33) + c34) + c35) +- Code(Counter(10)) at (prev + 2, 13) to (start + 2, 15) +- Code(Expression(133, Add)) at (prev + 5, 9) to (start + 0, 10) + = (c4 + (((c5 + c6) + c7) + c8)) +- Code(Expression(96, Add)) at (prev + 0, 16) to (start + 0, 29) + = ((c31 + (((c32 + c33) + c34) + c35)) + Zero) +- Code(Counter(4)) at (prev + 0, 30) to (start + 2, 6) +- Code(Expression(122, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c31 + (((c32 + c33) + c34) + c35)) - c4) +- Code(Expression(121, Sub)) at (prev + 1, 12) to (start + 0, 25) + = (((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) +- Code(Expression(120, Sub)) at (prev + 0, 29) to (start + 0, 42) + = ((((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) - c5) +- Code(Expression(119, Sub)) at (prev + 0, 46) to (start + 0, 60) + = (((((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) - c5) - c6) +- Code(Expression(135, Add)) at (prev + 0, 61) to (start + 2, 10) + = ((c5 + c6) + c7) +- Code(Counter(8)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(134, Add)) at (prev + 1, 9) to (start + 0, 23) + = (((c5 + c6) + c7) + c8) +- Code(Counter(9)) at (prev + 2, 9) to (start + 0, 15) +- Code(Expression(132, Add)) at (prev + 2, 1) to (start + 0, 2) + = ((c4 + (((c5 + c6) + c7) + c8)) + (((c9 + c10) + (c11 + c12)) + (((c1 + Zero) - c2) - c3))) + diff --git a/tests/coverage-map/status-quo/conditions.rs b/tests/coverage-map/status-quo/conditions.rs new file mode 100644 index 0000000000000..fa7f2a116c21e --- /dev/null +++ b/tests/coverage-map/status-quo/conditions.rs @@ -0,0 +1,86 @@ +#![allow(unused_assignments, unused_variables)] + +fn main() { + let mut countdown = 0; + if true { + countdown = 10; + } + + const B: u32 = 100; + let x = if countdown > 7 { + countdown -= 4; + B + } else if countdown > 2 { + if countdown < 1 || countdown > 5 || countdown != 9 { + countdown = 0; + } + countdown -= 5; + countdown + } else { + return; + }; + + let mut countdown = 0; + if true { + countdown = 10; + } + + if countdown > 7 { + countdown -= 4; + } else if countdown > 2 { + if countdown < 1 || countdown > 5 || countdown != 9 { + countdown = 0; + } + countdown -= 5; + } else { + return; + } + + if true { + let mut countdown = 0; + if true { + countdown = 10; + } + + if countdown > 7 { + countdown -= 4; + } + else if countdown > 2 { + if countdown < 1 || countdown > 5 || countdown != 9 { + countdown = 0; + } + countdown -= 5; + } else { + return; + } + } + + let mut countdown = 0; + if true { + countdown = 1; + } + + let z = if countdown > 7 { + countdown -= 4; + } else if countdown > 2 { + if countdown < 1 || countdown > 5 || countdown != 9 { + countdown = 0; + } + countdown -= 5; + } else { + let should_be_reachable = countdown; + println!("reached"); + return; + }; + + let w = if countdown > 7 { + countdown -= 4; + } else if countdown > 2 { + if countdown < 1 || countdown > 5 || countdown != 9 { + countdown = 0; + } + countdown -= 5; + } else { + return; + }; +} diff --git a/tests/coverage-map/status-quo/continue.cov-map b/tests/coverage-map/status-quo/continue.cov-map new file mode 100644 index 0000000000000..c78cf293079ea --- /dev/null +++ b/tests/coverage-map/status-quo/continue.cov-map @@ -0,0 +1,85 @@ +Function name: continue::main +Raw bytes (216): 0x[01, 01, 1f, 01, 07, 05, 09, 03, 0d, 0d, 1f, 11, 15, 1b, 19, 0d, 1f, 11, 15, 15, 00, 19, 37, 1d, 21, 33, 25, 19, 37, 1d, 21, 1d, 00, 25, 4f, 29, 2d, 4b, 31, 25, 4f, 29, 2d, 31, 67, 35, 39, 5f, 3d, 31, 67, 35, 39, 35, 39, 3d, 41, 73, 45, 3d, 41, 41, 00, 49, 45, 1e, 01, 03, 01, 03, 12, 03, 04, 0e, 00, 13, 0a, 01, 0f, 00, 16, 05, 02, 11, 00, 19, 09, 02, 12, 04, 0e, 1b, 06, 0e, 00, 13, 16, 01, 0f, 00, 16, 15, 01, 16, 02, 0e, 11, 04, 11, 00, 19, 23, 03, 09, 00, 0e, 33, 02, 0e, 00, 13, 2e, 01, 0f, 00, 16, 1d, 01, 15, 02, 0e, 21, 04, 11, 00, 19, 3b, 03, 09, 00, 0e, 4b, 02, 0e, 00, 13, 46, 01, 0c, 00, 13, 29, 01, 0d, 00, 15, 2d, 01, 0a, 01, 0e, 5f, 03, 0e, 00, 13, 5a, 01, 0f, 00, 16, 39, 01, 16, 02, 0e, 35, 03, 12, 02, 0e, 67, 04, 09, 00, 0e, 73, 02, 0e, 00, 13, 6e, 01, 0f, 00, 16, 41, 01, 16, 02, 0e, 49, 04, 11, 00, 16, 77, 03, 09, 00, 0e, 7b, 02, 0d, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 31 +- expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 3 operands: lhs = Counter(3), rhs = Expression(7, Add) +- expression 4 operands: lhs = Counter(4), rhs = Counter(5) +- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(6) +- expression 6 operands: lhs = Counter(3), rhs = Expression(7, Add) +- expression 7 operands: lhs = Counter(4), rhs = Counter(5) +- expression 8 operands: lhs = Counter(5), rhs = Zero +- expression 9 operands: lhs = Counter(6), rhs = Expression(13, Add) +- expression 10 operands: lhs = Counter(7), rhs = Counter(8) +- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(9) +- expression 12 operands: lhs = Counter(6), rhs = Expression(13, Add) +- expression 13 operands: lhs = Counter(7), rhs = Counter(8) +- expression 14 operands: lhs = Counter(7), rhs = Zero +- expression 15 operands: lhs = Counter(9), rhs = Expression(19, Add) +- expression 16 operands: lhs = Counter(10), rhs = Counter(11) +- expression 17 operands: lhs = Expression(18, Add), rhs = Counter(12) +- expression 18 operands: lhs = Counter(9), rhs = Expression(19, Add) +- expression 19 operands: lhs = Counter(10), rhs = Counter(11) +- expression 20 operands: lhs = Counter(12), rhs = Expression(25, Add) +- expression 21 operands: lhs = Counter(13), rhs = Counter(14) +- expression 22 operands: lhs = Expression(23, Add), rhs = Counter(15) +- expression 23 operands: lhs = Counter(12), rhs = Expression(25, Add) +- expression 24 operands: lhs = Counter(13), rhs = Counter(14) +- expression 25 operands: lhs = Counter(13), rhs = Counter(14) +- expression 26 operands: lhs = Counter(15), rhs = Counter(16) +- expression 27 operands: lhs = Expression(28, Add), rhs = Counter(17) +- expression 28 operands: lhs = Counter(15), rhs = Counter(16) +- expression 29 operands: lhs = Counter(16), rhs = Zero +- expression 30 operands: lhs = Counter(18), rhs = Counter(17) +Number of file 0 mappings: 30 +- Code(Counter(0)) at (prev + 3, 1) to (start + 3, 18) +- Code(Expression(0, Add)) at (prev + 4, 14) to (start + 0, 19) + = (c0 + (c1 + c2)) +- Code(Expression(2, Sub)) at (prev + 1, 15) to (start + 0, 22) + = ((c0 + (c1 + c2)) - c3) +- Code(Counter(1)) at (prev + 2, 17) to (start + 0, 25) +- Code(Counter(2)) at (prev + 2, 18) to (start + 4, 14) +- Code(Expression(6, Add)) at (prev + 6, 14) to (start + 0, 19) + = (c3 + (c4 + c5)) +- Code(Expression(5, Sub)) at (prev + 1, 15) to (start + 0, 22) + = ((c3 + (c4 + c5)) - c6) +- Code(Counter(5)) at (prev + 1, 22) to (start + 2, 14) +- Code(Counter(4)) at (prev + 4, 17) to (start + 0, 25) +- Code(Expression(8, Add)) at (prev + 3, 9) to (start + 0, 14) + = (c5 + Zero) +- Code(Expression(12, Add)) at (prev + 2, 14) to (start + 0, 19) + = (c6 + (c7 + c8)) +- Code(Expression(11, Sub)) at (prev + 1, 15) to (start + 0, 22) + = ((c6 + (c7 + c8)) - c9) +- Code(Counter(7)) at (prev + 1, 21) to (start + 2, 14) +- Code(Counter(8)) at (prev + 4, 17) to (start + 0, 25) +- Code(Expression(14, Add)) at (prev + 3, 9) to (start + 0, 14) + = (c7 + Zero) +- Code(Expression(18, Add)) at (prev + 2, 14) to (start + 0, 19) + = (c9 + (c10 + c11)) +- Code(Expression(17, Sub)) at (prev + 1, 12) to (start + 0, 19) + = ((c9 + (c10 + c11)) - c12) +- Code(Counter(10)) at (prev + 1, 13) to (start + 0, 21) +- Code(Counter(11)) at (prev + 1, 10) to (start + 1, 14) +- Code(Expression(23, Add)) at (prev + 3, 14) to (start + 0, 19) + = (c12 + (c13 + c14)) +- Code(Expression(22, Sub)) at (prev + 1, 15) to (start + 0, 22) + = ((c12 + (c13 + c14)) - c15) +- Code(Counter(14)) at (prev + 1, 22) to (start + 2, 14) +- Code(Counter(13)) at (prev + 3, 18) to (start + 2, 14) +- Code(Expression(25, Add)) at (prev + 4, 9) to (start + 0, 14) + = (c13 + c14) +- Code(Expression(28, Add)) at (prev + 2, 14) to (start + 0, 19) + = (c15 + c16) +- Code(Expression(27, Sub)) at (prev + 1, 15) to (start + 0, 22) + = ((c15 + c16) - c17) +- Code(Counter(16)) at (prev + 1, 22) to (start + 2, 14) +- Code(Counter(18)) at (prev + 4, 17) to (start + 0, 22) +- Code(Expression(29, Add)) at (prev + 3, 9) to (start + 0, 14) + = (c16 + Zero) +- Code(Expression(30, Add)) at (prev + 2, 13) to (start + 1, 2) + = (c18 + c17) + diff --git a/tests/coverage-map/status-quo/continue.rs b/tests/coverage-map/status-quo/continue.rs new file mode 100644 index 0000000000000..624aa98341b80 --- /dev/null +++ b/tests/coverage-map/status-quo/continue.rs @@ -0,0 +1,69 @@ +#![allow(unused_assignments, unused_variables)] + +fn main() { + let is_true = std::env::args().len() == 1; + + let mut x = 0; + for _ in 0..10 { + match is_true { + true => { + continue; + } + _ => { + x = 1; + } + } + x = 3; + } + for _ in 0..10 { + match is_true { + false => { + x = 1; + } + _ => { + continue; + } + } + x = 3; + } + for _ in 0..10 { + match is_true { + true => { + x = 1; + } + _ => { + continue; + } + } + x = 3; + } + for _ in 0..10 { + if is_true { + continue; + } + x = 3; + } + for _ in 0..10 { + match is_true { + false => { + x = 1; + } + _ => { + let _ = x; + } + } + x = 3; + } + for _ in 0..10 { + match is_true { + false => { + x = 1; + } + _ => { + break; + } + } + x = 3; + } + let _ = x; +} diff --git a/tests/coverage-map/status-quo/dead_code.cov-map b/tests/coverage-map/status-quo/dead_code.cov-map new file mode 100644 index 0000000000000..8d5f88e63efba --- /dev/null +++ b/tests/coverage-map/status-quo/dead_code.cov-map @@ -0,0 +1,37 @@ +Function name: dead_code::main +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 1b, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 07, 01, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 27, 1) to (start + 7, 15) +- Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: dead_code::unused_fn (unused) +Raw bytes (24): 0x[01, 01, 00, 04, 01, 0f, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 15, 1) to (start + 7, 15) +- Code(Zero) at (prev + 7, 16) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) + +Function name: dead_code::unused_pub_fn_not_in_library (unused) +Raw bytes (24): 0x[01, 01, 00, 04, 01, 03, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) +- Code(Zero) at (prev + 7, 16) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) + diff --git a/tests/coverage-map/status-quo/dead_code.rs b/tests/coverage-map/status-quo/dead_code.rs new file mode 100644 index 0000000000000..3492712a6f98e --- /dev/null +++ b/tests/coverage-map/status-quo/dead_code.rs @@ -0,0 +1,37 @@ +#![allow(dead_code, unused_assignments, unused_variables)] + +pub fn unused_pub_fn_not_in_library() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut countdown = 0; + if is_true { + countdown = 10; + } +} + +fn unused_fn() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut countdown = 0; + if is_true { + countdown = 10; + } +} + +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut countdown = 0; + if is_true { + countdown = 10; + } +} diff --git a/tests/coverage-map/status-quo/drop_trait.cov-map b/tests/coverage-map/status-quo/drop_trait.cov-map new file mode 100644 index 0000000000000..203d1048b0547 --- /dev/null +++ b/tests/coverage-map/status-quo/drop_trait.cov-map @@ -0,0 +1,21 @@ +Function name: ::drop +Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 05, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 9, 5) to (start + 2, 6) + +Function name: drop_trait::main +Raw bytes (26): 0x[01, 01, 01, 05, 00, 04, 01, 0e, 01, 05, 0c, 05, 06, 09, 01, 16, 00, 02, 06, 04, 0b, 03, 05, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(1), rhs = Zero +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 14, 1) to (start + 5, 12) +- Code(Counter(1)) at (prev + 6, 9) to (start + 1, 22) +- Code(Zero) at (prev + 2, 6) to (start + 4, 11) +- Code(Expression(0, Add)) at (prev + 5, 1) to (start + 0, 2) + = (c1 + Zero) + diff --git a/tests/coverage-map/status-quo/drop_trait.rs b/tests/coverage-map/status-quo/drop_trait.rs new file mode 100644 index 0000000000000..7b062719c6b02 --- /dev/null +++ b/tests/coverage-map/status-quo/drop_trait.rs @@ -0,0 +1,33 @@ +#![allow(unused_assignments)] +// failure-status: 1 + +struct Firework { + strength: i32, +} + +impl Drop for Firework { + fn drop(&mut self) { + println!("BOOM times {}!!!", self.strength); + } +} + +fn main() -> Result<(), u8> { + let _firecracker = Firework { strength: 1 }; + + let _tnt = Firework { strength: 100 }; + + if true { + println!("Exiting with error..."); + return Err(1); + } + + let _ = Firework { strength: 1000 }; + + Ok(()) +} + +// Expected program output: +// Exiting with error... +// BOOM times 100!!! +// BOOM times 1!!! +// Error: 1 diff --git a/tests/coverage-map/status-quo/generator.cov-map b/tests/coverage-map/status-quo/generator.cov-map new file mode 100644 index 0000000000000..6e10b58a94118 --- /dev/null +++ b/tests/coverage-map/status-quo/generator.cov-map @@ -0,0 +1,58 @@ +Function name: generator::get_u32 +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0b, 01, 01, 0b, 05, 01, 0e, 00, 13, 02, 00, 1d, 00, 3c, 07, 01, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 11, 1) to (start + 1, 11) +- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 19) +- Code(Expression(0, Sub)) at (prev + 0, 29) to (start + 0, 60) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: generator::main +Raw bytes (71): 0x[01, 01, 0b, 01, 00, 05, 0b, 09, 0d, 11, 00, 11, 15, 2a, 19, 11, 15, 15, 19, 26, 00, 2a, 19, 11, 15, 09, 01, 0f, 01, 02, 19, 03, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 07, 01, 0e, 00, 35, 0f, 02, 0b, 00, 2e, 2a, 01, 22, 00, 27, 26, 00, 2c, 00, 2e, 1f, 01, 0e, 00, 35, 23, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 11 +- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 3 operands: lhs = Counter(4), rhs = Zero +- expression 4 operands: lhs = Counter(4), rhs = Counter(5) +- expression 5 operands: lhs = Expression(10, Sub), rhs = Counter(6) +- expression 6 operands: lhs = Counter(4), rhs = Counter(5) +- expression 7 operands: lhs = Counter(5), rhs = Counter(6) +- expression 8 operands: lhs = Expression(9, Sub), rhs = Zero +- expression 9 operands: lhs = Expression(10, Sub), rhs = Counter(6) +- expression 10 operands: lhs = Counter(4), rhs = Counter(5) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 25) +- Code(Expression(0, Add)) at (prev + 7, 11) to (start + 0, 46) + = (c0 + Zero) +- Code(Counter(4)) at (prev + 1, 43) to (start + 0, 45) +- Code(Expression(1, Add)) at (prev + 1, 14) to (start + 0, 53) + = (c1 + (c2 + c3)) +- Code(Expression(3, Add)) at (prev + 2, 11) to (start + 0, 46) + = (c4 + Zero) +- Code(Expression(10, Sub)) at (prev + 1, 34) to (start + 0, 39) + = (c4 - c5) +- Code(Expression(9, Sub)) at (prev + 0, 44) to (start + 0, 46) + = ((c4 - c5) - c6) +- Code(Expression(7, Add)) at (prev + 1, 14) to (start + 0, 53) + = (c5 + c6) +- Code(Expression(8, Add)) at (prev + 2, 1) to (start + 0, 2) + = (((c4 - c5) - c6) + Zero) + +Function name: generator::main::{closure#0} +Raw bytes (14): 0x[01, 01, 00, 02, 01, 11, 1c, 01, 1f, 05, 02, 10, 01, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 17, 28) to (start + 1, 31) +- Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) + diff --git a/tests/coverage-map/status-quo/generator.rs b/tests/coverage-map/status-quo/generator.rs new file mode 100644 index 0000000000000..4319991021e78 --- /dev/null +++ b/tests/coverage-map/status-quo/generator.rs @@ -0,0 +1,30 @@ +#![feature(generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +// The following implementation of a function called from a `yield` statement +// (apparently requiring the Result and the `String` type or constructor) +// creates conditions where the `generator::StateTransform` MIR transform will +// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic +// to handle this condition, and still report dead block coverage. +fn get_u32(val: bool) -> Result { + if val { Ok(1) } else { Err(String::from("some error")) } +} + +fn main() { + let is_true = std::env::args().len() == 1; + let mut generator = || { + yield get_u32(is_true); + return "foo"; + }; + + match Pin::new(&mut generator).resume(()) { + GeneratorState::Yielded(Ok(1)) => {} + _ => panic!("unexpected return from resume"), + } + match Pin::new(&mut generator).resume(()) { + GeneratorState::Complete("foo") => {} + _ => panic!("unexpected return from resume"), + } +} diff --git a/tests/coverage-map/status-quo/generics.cov-map b/tests/coverage-map/status-quo/generics.cov-map new file mode 100644 index 0000000000000..6079a433cd04e --- /dev/null +++ b/tests/coverage-map/status-quo/generics.cov-map @@ -0,0 +1,45 @@ +Function name: as core::ops::drop::Drop>::drop +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 05, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) + +Function name: >::set_strength +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 05, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) + +Function name: as core::ops::drop::Drop>::drop +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 05, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) + +Function name: >::set_strength +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 05, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) + +Function name: generics::main +Raw bytes (26): 0x[01, 01, 01, 05, 00, 04, 01, 16, 01, 08, 0c, 05, 09, 09, 01, 16, 00, 02, 06, 04, 0b, 03, 05, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(1), rhs = Zero +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 22, 1) to (start + 8, 12) +- Code(Counter(1)) at (prev + 9, 9) to (start + 1, 22) +- Code(Zero) at (prev + 2, 6) to (start + 4, 11) +- Code(Expression(0, Add)) at (prev + 5, 1) to (start + 0, 2) + = (c1 + Zero) + diff --git a/tests/coverage-map/status-quo/generics.rs b/tests/coverage-map/status-quo/generics.rs new file mode 100644 index 0000000000000..bf4c2d8d68532 --- /dev/null +++ b/tests/coverage-map/status-quo/generics.rs @@ -0,0 +1,44 @@ +#![allow(unused_assignments)] +// failure-status: 1 + +struct Firework where T: Copy + std::fmt::Display { + strength: T, +} + +impl Firework where T: Copy + std::fmt::Display { + #[inline(always)] + fn set_strength(&mut self, new_strength: T) { + self.strength = new_strength; + } +} + +impl Drop for Firework where T: Copy + std::fmt::Display { + #[inline(always)] + fn drop(&mut self) { + println!("BOOM times {}!!!", self.strength); + } +} + +fn main() -> Result<(), u8> { + let mut firecracker = Firework { strength: 1 }; + firecracker.set_strength(2); + + let mut tnt = Firework { strength: 100.1 }; + tnt.set_strength(200.1); + tnt.set_strength(300.3); + + if true { + println!("Exiting with error..."); + return Err(1); + } + + let _ = Firework { strength: 1000 }; + + Ok(()) +} + +// Expected program output: +// Exiting with error... +// BOOM times 100!!! +// BOOM times 1!!! +// Error: 1 diff --git a/tests/coverage-map/status-quo/if.cov-map b/tests/coverage-map/status-quo/if.cov-map new file mode 100644 index 0000000000000..391a69e0e821d --- /dev/null +++ b/tests/coverage-map/status-quo/if.cov-map @@ -0,0 +1,15 @@ +Function name: if::main +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 03, 01, 12, 10, 05, 13, 05, 05, 06, 02, 05, 06, 00, 07, 07, 01, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 3, 1) to (start + 18, 16) +- Code(Counter(1)) at (prev + 19, 5) to (start + 5, 6) +- Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + diff --git a/tests/coverage-map/status-quo/if.rs b/tests/coverage-map/status-quo/if.rs new file mode 100644 index 0000000000000..8ad5042ff7baf --- /dev/null +++ b/tests/coverage-map/status-quo/if.rs @@ -0,0 +1,28 @@ +#![allow(unused_assignments, unused_variables)] + +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let + is_true + = + std::env::args().len() + == + 1 + ; + let + mut + countdown + = + 0 + ; + if + is_true + { + countdown + = + 10 + ; + } +} diff --git a/tests/coverage-map/status-quo/if_else.cov-map b/tests/coverage-map/status-quo/if_else.cov-map new file mode 100644 index 0000000000000..da692ca3aa2a7 --- /dev/null +++ b/tests/coverage-map/status-quo/if_else.cov-map @@ -0,0 +1,25 @@ +Function name: if_else::main +Raw bytes (53): 0x[01, 01, 07, 01, 05, 05, 02, 1b, 09, 05, 02, 09, 16, 1b, 09, 05, 02, 07, 01, 03, 01, 08, 10, 05, 09, 05, 05, 06, 02, 08, 09, 02, 10, 1b, 06, 09, 00, 10, 09, 01, 05, 05, 06, 16, 07, 05, 05, 06, 13, 06, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 7 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Expression(6, Add), rhs = Counter(2) +- expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 4 operands: lhs = Counter(2), rhs = Expression(5, Sub) +- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(2) +- expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 3, 1) to (start + 8, 16) +- Code(Counter(1)) at (prev + 9, 5) to (start + 5, 6) +- Code(Expression(0, Sub)) at (prev + 8, 9) to (start + 2, 16) + = (c0 - c1) +- Code(Expression(6, Add)) at (prev + 6, 9) to (start + 0, 16) + = (c1 + (c0 - c1)) +- Code(Counter(2)) at (prev + 1, 5) to (start + 5, 6) +- Code(Expression(5, Sub)) at (prev + 7, 5) to (start + 5, 6) + = ((c1 + (c0 - c1)) - c2) +- Code(Expression(4, Add)) at (prev + 6, 1) to (start + 0, 2) + = (c2 + ((c1 + (c0 - c1)) - c2)) + diff --git a/tests/coverage-map/status-quo/if_else.rs b/tests/coverage-map/status-quo/if_else.rs new file mode 100644 index 0000000000000..3244e1e3afd2b --- /dev/null +++ b/tests/coverage-map/status-quo/if_else.rs @@ -0,0 +1,40 @@ +#![allow(unused_assignments, unused_variables)] + +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut countdown = 0; + if + is_true + { + countdown + = + 10 + ; + } + else // Note coverage region difference without semicolon + { + countdown + = + 100 + } + + if + is_true + { + countdown + = + 10 + ; + } + else + { + countdown + = + 100 + ; + } +} diff --git a/tests/coverage-map/status-quo/inline-dead.cov-map b/tests/coverage-map/status-quo/inline-dead.cov-map new file mode 100644 index 0000000000000..dec43d3e8bbdd --- /dev/null +++ b/tests/coverage-map/status-quo/inline-dead.cov-map @@ -0,0 +1,45 @@ +Function name: inline_dead::dead (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 19, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 25, 1) to (start + 2, 2) + +Function name: inline_dead::live:: +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 10, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 07, 02, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 9) +- Code(Zero) at (prev + 2, 9) to (start + 0, 15) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 2, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: inline_dead::main +Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 04, 01, 03, 0d, 03, 07, 06, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Zero +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13) +- Code(Expression(0, Add)) at (prev + 7, 6) to (start + 2, 2) + = (c0 + Zero) + +Function name: inline_dead::main::{closure#0} +Raw bytes (16): 0x[01, 01, 01, 01, 05, 02, 00, 09, 0d, 00, 0e, 03, 02, 05, 00, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 9, 13) to (start + 0, 14) +- Code(Expression(0, Add)) at (prev + 2, 5) to (start + 0, 6) + = (c0 + c1) + diff --git a/tests/coverage-map/status-quo/inline-dead.rs b/tests/coverage-map/status-quo/inline-dead.rs new file mode 100644 index 0000000000000..854fa06296752 --- /dev/null +++ b/tests/coverage-map/status-quo/inline-dead.rs @@ -0,0 +1,27 @@ +// Regression test for issue #98833. +// compile-flags: -Zinline-mir -Cdebug-assertions=off + +fn main() { + println!("{}", live::()); + + let f = |x: bool| { + debug_assert!( + x + ); + }; + f(false); +} + +#[inline] +fn live() -> u32 { + if B { + dead() + } else { + 0 + } +} + +#[inline] +fn dead() -> u32 { + 42 +} diff --git a/tests/coverage-map/status-quo/inline.cov-map b/tests/coverage-map/status-quo/inline.cov-map new file mode 100644 index 0000000000000..57ae85623fb75 --- /dev/null +++ b/tests/coverage-map/status-quo/inline.cov-map @@ -0,0 +1,82 @@ +Function name: inline::display:: +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 00, 03, 05, 05, 01, 29, 01, 00, 22, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 10, 07, 00, 11, 02, 06, 0a, 03, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 3 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Zero +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(1) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 34) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) +- Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 16) + = (c0 + c1) +- Code(Expression(1, Add)) at (prev + 0, 17) to (start + 2, 6) + = (c1 + Zero) +- Code(Expression(2, Sub)) at (prev + 3, 5) to (start + 1, 2) + = ((c0 + c1) - c1) + +Function name: inline::error +Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 49, 1) to (start + 2, 2) + +Function name: inline::length:: +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2) + +Function name: inline::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 05, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 5, 1) to (start + 2, 2) + +Function name: inline::permutate:: +Raw bytes (54): 0x[01, 01, 05, 01, 05, 02, 0d, 11, 00, 05, 13, 09, 0d, 08, 01, 0f, 01, 02, 0e, 05, 02, 0f, 02, 06, 02, 02, 0f, 00, 14, 11, 01, 0d, 00, 0e, 06, 00, 12, 00, 16, 0b, 00, 17, 04, 0a, 0d, 05, 0c, 02, 06, 0f, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(3) +- expression 2 operands: lhs = Counter(4), rhs = Zero +- expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add) +- expression 4 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 14) +- Code(Counter(1)) at (prev + 2, 15) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 15) to (start + 0, 20) + = (c0 - c1) +- Code(Counter(4)) at (prev + 1, 13) to (start + 0, 14) +- Code(Expression(1, Sub)) at (prev + 0, 18) to (start + 0, 22) + = ((c0 - c1) - c3) +- Code(Expression(2, Add)) at (prev + 0, 23) to (start + 4, 10) + = (c4 + Zero) +- Code(Counter(3)) at (prev + 5, 12) to (start + 2, 6) +- Code(Expression(3, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c1 + (c2 + c3)) + +Function name: inline::permutations:: +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 03, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 10, 1) to (start + 3, 2) + +Function name: inline::swap:: +Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 04, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 35, 1) to (start + 4, 2) + diff --git a/tests/coverage-map/status-quo/inline.rs b/tests/coverage-map/status-quo/inline.rs new file mode 100644 index 0000000000000..9cfab9ddbadf2 --- /dev/null +++ b/tests/coverage-map/status-quo/inline.rs @@ -0,0 +1,51 @@ +// compile-flags: -Zinline-mir + +use std::fmt::Display; + +fn main() { + permutations(&['a', 'b', 'c']); +} + +#[inline(always)] +fn permutations(xs: &[T]) { + let mut ys = xs.to_owned(); + permutate(&mut ys, 0); +} + +fn permutate(xs: &mut [T], k: usize) { + let n = length(xs); + if k == n { + display(xs); + } else if k < n { + for i in k..n { + swap(xs, i, k); + permutate(xs, k + 1); + swap(xs, i, k); + } + } else { + error(); + } +} + +fn length(xs: &[T]) -> usize { + xs.len() +} + +#[inline] +fn swap(xs: &mut [T], i: usize, j: usize) { + let t = xs[i]; + xs[i] = xs[j]; + xs[j] = t; +} + +fn display(xs: &[T]) { + for x in xs { + print!("{}", x); + } + println!(); +} + +#[inline(always)] +fn error() { + panic!("error"); +} diff --git a/tests/coverage-map/status-quo/inner_items.cov-map b/tests/coverage-map/status-quo/inner_items.cov-map new file mode 100644 index 0000000000000..3f39d74efbaca --- /dev/null +++ b/tests/coverage-map/status-quo/inner_items.cov-map @@ -0,0 +1,49 @@ +Function name: ::default_trait_func +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 09, 03, 0a] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 33, 9) to (start + 3, 10) + +Function name: ::trait_func +Raw bytes (9): 0x[01, 01, 00, 01, 01, 28, 09, 03, 0a] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 40, 9) to (start + 3, 10) + +Function name: inner_items::main +Raw bytes (53): 0x[01, 01, 07, 01, 05, 05, 02, 1b, 09, 05, 02, 09, 16, 1b, 09, 05, 02, 07, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 1b, 24, 08, 00, 0f, 09, 00, 10, 02, 06, 16, 02, 06, 00, 07, 13, 02, 09, 05, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 7 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Expression(6, Add), rhs = Counter(2) +- expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 4 operands: lhs = Counter(2), rhs = Expression(5, Sub) +- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(2) +- expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) +- Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(6, Add)) at (prev + 36, 8) to (start + 0, 15) + = (c1 + (c0 - c1)) +- Code(Counter(2)) at (prev + 0, 16) to (start + 2, 6) +- Code(Expression(5, Sub)) at (prev + 2, 6) to (start + 0, 7) + = ((c1 + (c0 - c1)) - c2) +- Code(Expression(4, Add)) at (prev + 2, 9) to (start + 5, 2) + = (c2 + ((c1 + (c0 - c1)) - c2)) + +Function name: inner_items::main::in_func +Raw bytes (9): 0x[01, 01, 00, 01, 01, 12, 05, 04, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 18, 5) to (start + 4, 6) + diff --git a/tests/coverage-map/status-quo/inner_items.rs b/tests/coverage-map/status-quo/inner_items.rs new file mode 100644 index 0000000000000..bcb62b3031cd9 --- /dev/null +++ b/tests/coverage-map/status-quo/inner_items.rs @@ -0,0 +1,57 @@ +#![allow(unused_assignments, unused_variables, dead_code)] + +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut countdown = 0; + if is_true { + countdown = 10; + } + + mod in_mod { + const IN_MOD_CONST: u32 = 1000; + } + + fn in_func(a: u32) { + let b = 1; + let c = a + b; + println!("c = {}", c) + } + + struct InStruct { + in_struct_field: u32, + } + + const IN_CONST: u32 = 1234; + + trait InTrait { + fn trait_func(&mut self, incr: u32); + + fn default_trait_func(&mut self) { + in_func(IN_CONST); + self.trait_func(IN_CONST); + } + } + + impl InTrait for InStruct { + fn trait_func(&mut self, incr: u32) { + self.in_struct_field += incr; + in_func(self.in_struct_field); + } + } + + type InType = String; + + if is_true { + in_func(countdown); + } + + let mut val = InStruct { + in_struct_field: 101, + }; + + val.default_trait_func(); +} diff --git a/tests/coverage-map/status-quo/issue-83601.cov-map b/tests/coverage-map/status-quo/issue-83601.cov-map new file mode 100644 index 0000000000000..f5db3a89750c7 --- /dev/null +++ b/tests/coverage-map/status-quo/issue-83601.cov-map @@ -0,0 +1,28 @@ +Function name: ::eq +Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 11, 00, 1a] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 3, 17) to (start + 0, 26) + +Function name: ::fmt +Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 0a, 00, 0f] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 3, 10) to (start + 0, 15) + +Function name: issue_83601::main +Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28) +- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2) + = (c1 - c2) + diff --git a/tests/coverage-map/status-quo/issue-83601.rs b/tests/coverage-map/status-quo/issue-83601.rs new file mode 100644 index 0000000000000..0b72a81947cc7 --- /dev/null +++ b/tests/coverage-map/status-quo/issue-83601.rs @@ -0,0 +1,14 @@ +// Shows that rust-lang/rust/83601 is resolved + +#[derive(Debug, PartialEq, Eq)] +struct Foo(u32); + +fn main() { + let bar = Foo(1); + assert_eq!(bar, Foo(1)); + let baz = Foo(0); + assert_ne!(baz, Foo(1)); + println!("{:?}", Foo(1)); + println!("{:?}", bar); + println!("{:?}", baz); +} diff --git a/tests/coverage-map/status-quo/issue-84561.cov-map b/tests/coverage-map/status-quo/issue-84561.cov-map new file mode 100644 index 0000000000000..fe098fd396c27 --- /dev/null +++ b/tests/coverage-map/status-quo/issue-84561.cov-map @@ -0,0 +1,233 @@ +Function name: ::eq +Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 0a, 00, 13, 00, 00, 0a, 00, 13] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 4, 10) to (start + 0, 19) +- Code(Zero) at (prev + 0, 10) to (start + 0, 19) + +Function name: ::fmt +Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 89, 01, 09, 00, 25, 05, 00, 25, 00, 26, 02, 01, 09, 00, 0f, 07, 01, 05, 00, 06] +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 + 137, 9) to (start + 0, 37) +- Code(Counter(1)) at (prev + 0, 37) to (start + 0, 38) +- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 0, 6) + = (c1 + (c0 - c1)) + +Function name: issue_84561::main +Raw bytes (10): 0x[01, 01, 00, 01, 01, b2, 01, 01, 04, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 178, 1) to (start + 4, 2) + +Function name: issue_84561::test1 +Raw bytes (78): 0x[01, 01, 0e, 05, 06, 01, 05, 09, 36, 03, 09, 0d, 2e, 33, 0d, 09, 36, 03, 09, 11, 26, 2b, 11, 0d, 2e, 33, 0d, 09, 36, 03, 09, 09, 01, 98, 01, 01, 01, 0b, 05, 01, 0c, 00, 1e, 03, 01, 05, 00, 0b, 09, 00, 0c, 00, 1e, 33, 01, 0d, 01, 0b, 0d, 01, 0c, 00, 1e, 2b, 01, 05, 03, 0b, 11, 03, 0c, 00, 1e, 23, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 14 +- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Sub) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +- expression 2 operands: lhs = Counter(2), rhs = Expression(13, Sub) +- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(2) +- expression 4 operands: lhs = Counter(3), rhs = Expression(11, Sub) +- expression 5 operands: lhs = Expression(12, Add), rhs = Counter(3) +- expression 6 operands: lhs = Counter(2), rhs = Expression(13, Sub) +- expression 7 operands: lhs = Expression(0, Add), rhs = Counter(2) +- expression 8 operands: lhs = Counter(4), rhs = Expression(9, Sub) +- expression 9 operands: lhs = Expression(10, Add), rhs = Counter(4) +- expression 10 operands: lhs = Counter(3), rhs = Expression(11, Sub) +- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(3) +- expression 12 operands: lhs = Counter(2), rhs = Expression(13, Sub) +- expression 13 operands: lhs = Expression(0, Add), rhs = Counter(2) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 152, 1) to (start + 1, 11) +- Code(Counter(1)) at (prev + 1, 12) to (start + 0, 30) +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 0, 11) + = (c1 + (c0 - c1)) +- Code(Counter(2)) at (prev + 0, 12) to (start + 0, 30) +- Code(Expression(12, Add)) at (prev + 1, 13) to (start + 1, 11) + = (c2 + ((c1 + (c0 - c1)) - c2)) +- Code(Counter(3)) at (prev + 1, 12) to (start + 0, 30) +- Code(Expression(10, Add)) at (prev + 1, 5) to (start + 3, 11) + = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) +- Code(Counter(4)) at (prev + 3, 12) to (start + 0, 30) +- Code(Expression(8, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) + +Function name: issue_84561::test2 +Raw bytes (24): 0x[01, 01, 02, 05, 06, 01, 05, 03, 01, ae, 01, 01, 01, 10, 05, 01, 11, 00, 23, 03, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Sub) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 174, 1) to (start + 1, 16) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 35) +- Code(Expression(0, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: issue_84561::test2::call_print +Raw bytes (10): 0x[01, 01, 00, 01, 01, a5, 01, 09, 02, 0a] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 165, 9) to (start + 2, 10) + +Function name: issue_84561::test3 +Raw bytes (437): 0x[01, 01, 41, 05, 09, 0d, 11, 15, 19, 12, 1d, 15, 19, 21, 25, 1e, 29, 21, 25, 31, 39, 3d, 41, 2e, 45, 3d, 41, 42, 49, 45, 4d, 3f, 51, 42, 49, 45, 4d, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 59, 92, 01, 55, 51, 59, 8f, 01, 5d, 92, 01, 55, 51, 59, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 59, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 59, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, 71, fe, 01, 82, 02, 71, 69, 6d, 69, 6d, 82, 02, 71, 69, 6d, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, ee, 01, 81, 01, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, 33, 01, 06, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 71, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 65 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Counter(3), rhs = Counter(4) +- expression 2 operands: lhs = Counter(5), rhs = Counter(6) +- expression 3 operands: lhs = Expression(4, Sub), rhs = Counter(7) +- expression 4 operands: lhs = Counter(5), rhs = Counter(6) +- expression 5 operands: lhs = Counter(8), rhs = Counter(9) +- expression 6 operands: lhs = Expression(7, Sub), rhs = Counter(10) +- expression 7 operands: lhs = Counter(8), rhs = Counter(9) +- expression 8 operands: lhs = Counter(12), rhs = Counter(14) +- expression 9 operands: lhs = Counter(15), rhs = Counter(16) +- expression 10 operands: lhs = Expression(11, Sub), rhs = Counter(17) +- expression 11 operands: lhs = Counter(15), rhs = Counter(16) +- expression 12 operands: lhs = Expression(16, Sub), rhs = Counter(18) +- expression 13 operands: lhs = Counter(17), rhs = Counter(19) +- expression 14 operands: lhs = Expression(15, Add), rhs = Counter(20) +- expression 15 operands: lhs = Expression(16, Sub), rhs = Counter(18) +- expression 16 operands: lhs = Counter(17), rhs = Counter(19) +- expression 17 operands: lhs = Counter(23), rhs = Expression(34, Sub) +- expression 18 operands: lhs = Expression(35, Add), rhs = Counter(23) +- expression 19 operands: lhs = Expression(36, Sub), rhs = Counter(21) +- expression 20 operands: lhs = Counter(20), rhs = Counter(22) +- expression 21 operands: lhs = Expression(36, Sub), rhs = Counter(21) +- expression 22 operands: lhs = Counter(20), rhs = Counter(22) +- expression 23 operands: lhs = Expression(35, Add), rhs = Counter(23) +- expression 24 operands: lhs = Expression(36, Sub), rhs = Counter(21) +- expression 25 operands: lhs = Counter(20), rhs = Counter(22) +- expression 26 operands: lhs = Expression(33, Add), rhs = Counter(24) +- expression 27 operands: lhs = Counter(23), rhs = Expression(34, Sub) +- expression 28 operands: lhs = Expression(35, Add), rhs = Counter(23) +- expression 29 operands: lhs = Expression(36, Sub), rhs = Counter(21) +- expression 30 operands: lhs = Counter(20), rhs = Counter(22) +- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(25) +- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(24) +- expression 33 operands: lhs = Counter(23), rhs = Expression(34, Sub) +- expression 34 operands: lhs = Expression(35, Add), rhs = Counter(23) +- expression 35 operands: lhs = Expression(36, Sub), rhs = Counter(21) +- expression 36 operands: lhs = Counter(20), rhs = Counter(22) +- expression 37 operands: lhs = Counter(29), rhs = Expression(61, Sub) +- expression 38 operands: lhs = Expression(62, Add), rhs = Counter(30) +- expression 39 operands: lhs = Counter(28), rhs = Expression(63, Sub) +- expression 40 operands: lhs = Expression(64, Sub), rhs = Counter(28) +- expression 41 operands: lhs = Counter(26), rhs = Counter(27) +- expression 42 operands: lhs = Counter(28), rhs = Expression(63, Sub) +- expression 43 operands: lhs = Expression(64, Sub), rhs = Counter(28) +- expression 44 operands: lhs = Counter(26), rhs = Counter(27) +- expression 45 operands: lhs = Counter(26), rhs = Counter(27) +- expression 46 operands: lhs = Expression(64, Sub), rhs = Counter(28) +- expression 47 operands: lhs = Counter(26), rhs = Counter(27) +- expression 48 operands: lhs = Expression(62, Add), rhs = Counter(30) +- expression 49 operands: lhs = Counter(28), rhs = Expression(63, Sub) +- expression 50 operands: lhs = Expression(64, Sub), rhs = Counter(28) +- expression 51 operands: lhs = Counter(26), rhs = Counter(27) +- expression 52 operands: lhs = Expression(60, Add), rhs = Counter(31) +- expression 53 operands: lhs = Counter(29), rhs = Expression(61, Sub) +- expression 54 operands: lhs = Expression(62, Add), rhs = Counter(30) +- expression 55 operands: lhs = Counter(28), rhs = Expression(63, Sub) +- expression 56 operands: lhs = Expression(64, Sub), rhs = Counter(28) +- expression 57 operands: lhs = Counter(26), rhs = Counter(27) +- expression 58 operands: lhs = Expression(59, Sub), rhs = Counter(32) +- expression 59 operands: lhs = Expression(60, Add), rhs = Counter(31) +- expression 60 operands: lhs = Counter(29), rhs = Expression(61, Sub) +- expression 61 operands: lhs = Expression(62, Add), rhs = Counter(30) +- expression 62 operands: lhs = Counter(28), rhs = Expression(63, Sub) +- expression 63 operands: lhs = Expression(64, Sub), rhs = Counter(28) +- expression 64 operands: lhs = Counter(26), rhs = Counter(27) +Number of file 0 mappings: 51 +- Code(Counter(0)) at (prev + 6, 1) to (start + 3, 28) +- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 4, 31) + = (c1 - c2) +- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31) +- Code(Expression(1, Sub)) at (prev + 1, 5) to (start + 0, 31) + = (c3 - c4) +- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28) +- Code(Expression(4, Sub)) at (prev + 2, 5) to (start + 0, 31) + = (c5 - c6) +- Code(Expression(3, Sub)) at (prev + 1, 5) to (start + 0, 15) + = ((c5 - c6) - c7) +- Code(Zero) at (prev + 0, 32) to (start + 0, 48) +- Code(Counter(8)) at (prev + 1, 5) to (start + 3, 15) +- Code(Zero) at (prev + 3, 32) to (start + 0, 48) +- Code(Zero) at (prev + 0, 51) to (start + 0, 65) +- Code(Zero) at (prev + 0, 75) to (start + 0, 90) +- Code(Expression(7, Sub)) at (prev + 1, 5) to (start + 0, 15) + = (c8 - c9) +- Code(Zero) at (prev + 5, 9) to (start + 3, 16) +- Code(Zero) at (prev + 5, 13) to (start + 0, 27) +- Code(Zero) at (prev + 2, 13) to (start + 0, 28) +- Code(Expression(6, Sub)) at (prev + 4, 9) to (start + 5, 6) + = ((c8 - c9) - c10) +- Code(Counter(12)) at (prev + 6, 5) to (start + 3, 6) +- Code(Expression(8, Sub)) at (prev + 4, 5) to (start + 3, 6) + = (c12 - c14) +- Code(Counter(15)) at (prev + 4, 9) to (start + 4, 6) +- Code(Expression(11, Sub)) at (prev + 5, 8) to (start + 0, 15) + = (c15 - c16) +- Code(Counter(17)) at (prev + 1, 9) to (start + 3, 10) +- Code(Expression(10, Sub)) at (prev + 5, 9) to (start + 3, 10) + = ((c15 - c16) - c17) +- Code(Expression(15, Add)) at (prev + 5, 8) to (start + 0, 15) + = ((c17 - c19) + c18) +- Code(Counter(20)) at (prev + 1, 9) to (start + 0, 19) +- Code(Zero) at (prev + 3, 13) to (start + 0, 29) +- Code(Expression(14, Sub)) at (prev + 3, 9) to (start + 0, 19) + = (((c17 - c19) + c18) - c20) +- Code(Zero) at (prev + 3, 13) to (start + 0, 29) +- Code(Expression(33, Add)) at (prev + 3, 5) to (start + 0, 15) + = (c23 + (((c20 - c22) + c21) - c23)) +- Code(Expression(35, Add)) at (prev + 1, 12) to (start + 0, 19) + = ((c20 - c22) + c21) +- Code(Counter(23)) at (prev + 1, 13) to (start + 0, 19) +- Code(Expression(34, Sub)) at (prev + 2, 13) to (start + 0, 19) + = (((c20 - c22) + c21) - c23) +- Code(Expression(32, Sub)) at (prev + 4, 5) to (start + 2, 19) + = ((c23 + (((c20 - c22) + c21) - c23)) - c24) +- Code(Counter(25)) at (prev + 3, 13) to (start + 0, 19) +- Code(Expression(31, Sub)) at (prev + 2, 13) to (start + 0, 19) + = (((c23 + (((c20 - c22) + c21) - c23)) - c24) - c25) +- Code(Expression(60, Add)) at (prev + 3, 5) to (start + 0, 15) + = (c29 + ((c28 + ((c26 - c27) - c28)) - c30)) +- Code(Counter(26)) at (prev + 1, 12) to (start + 0, 19) +- Code(Counter(27)) at (prev + 1, 13) to (start + 3, 14) +- Code(Counter(29)) at (prev + 4, 13) to (start + 0, 19) +- Code(Expression(62, Add)) at (prev + 2, 13) to (start + 0, 23) + = (c28 + ((c26 - c27) - c28)) +- Code(Expression(64, Sub)) at (prev + 1, 20) to (start + 0, 27) + = (c26 - c27) +- Code(Counter(28)) at (prev + 1, 21) to (start + 0, 27) +- Code(Expression(63, Sub)) at (prev + 2, 21) to (start + 0, 27) + = ((c26 - c27) - c28) +- Code(Expression(61, Sub)) at (prev + 4, 13) to (start + 0, 19) + = ((c28 + ((c26 - c27) - c28)) - c30) +- Code(Counter(31)) at (prev + 3, 9) to (start + 0, 25) +- Code(Expression(59, Sub)) at (prev + 2, 5) to (start + 0, 15) + = ((c29 + ((c28 + ((c26 - c27) - c28)) - c30)) - c31) +- Code(Expression(58, Sub)) at (prev + 3, 9) to (start + 0, 34) + = (((c29 + ((c28 + ((c26 - c27) - c28)) - c30)) - c31) - c32) +- Code(Zero) at (prev + 2, 5) to (start + 0, 15) +- Code(Zero) at (prev + 3, 9) to (start + 0, 44) +- Code(Zero) at (prev + 2, 1) to (start + 0, 2) + diff --git a/tests/coverage-map/status-quo/issue-84561.rs b/tests/coverage-map/status-quo/issue-84561.rs new file mode 100644 index 0000000000000..facf5b5b4cfbe --- /dev/null +++ b/tests/coverage-map/status-quo/issue-84561.rs @@ -0,0 +1,182 @@ +// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results. + +// failure-status: 101 +#[derive(PartialEq, Eq)] +struct Foo(u32); +fn test3() { + let is_true = std::env::args().len() == 1; + let bar = Foo(1); + assert_eq!(bar, Foo(1)); + let baz = Foo(0); + assert_ne!(baz, Foo(1)); + println!("{:?}", Foo(1)); + println!("{:?}", bar); + println!("{:?}", baz); + + assert_eq!(Foo(1), Foo(1)); + assert_ne!(Foo(0), Foo(1)); + assert_eq!(Foo(2), Foo(2)); + let bar = Foo(0); + assert_ne!(bar, Foo(3)); + assert_ne!(Foo(0), Foo(4)); + assert_eq!(Foo(3), Foo(3), "with a message"); + println!("{:?}", bar); + println!("{:?}", Foo(1)); + + assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" }); + assert_ne!( + Foo(0) + , + Foo(5) + , + "{}" + , + if + is_true + { + "true message" + } else { + "false message" + } + ); + + let is_true = std::env::args().len() == 1; + + assert_eq!( + Foo(1), + Foo(1) + ); + assert_ne!( + Foo(0), + Foo(1) + ); + assert_eq!( + Foo(2), + Foo(2) + ); + let bar = Foo(1); + assert_ne!( + bar, + Foo(3) + ); + if is_true { + assert_ne!( + Foo(0), + Foo(4) + ); + } else { + assert_eq!( + Foo(3), + Foo(3) + ); + } + if is_true { + assert_ne!( + Foo(0), + Foo(4), + "with a message" + ); + } else { + assert_eq!( + Foo(3), + Foo(3), + "with a message" + ); + } + assert_ne!( + if is_true { + Foo(0) + } else { + Foo(1) + }, + Foo(5) + ); + assert_ne!( + Foo(5), + if is_true { + Foo(0) + } else { + Foo(1) + } + ); + assert_ne!( + if is_true { + assert_eq!( + Foo(3), + Foo(3) + ); + Foo(0) + } else { + assert_ne!( + if is_true { + Foo(0) + } else { + Foo(1) + }, + Foo(5) + ); + Foo(1) + }, + Foo(5), + "with a message" + ); + assert_eq!( + Foo(1), + Foo(3), + "this assert should fail" + ); + assert_eq!( + Foo(3), + Foo(3), + "this assert should not be reached" + ); +} + +impl std::fmt::Debug for Foo { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "try and succeed")?; + Ok(()) + } +} + +static mut DEBUG_LEVEL_ENABLED: bool = false; + +macro_rules! debug { + ($($arg:tt)+) => ( + if unsafe { DEBUG_LEVEL_ENABLED } { + println!($($arg)+); + } + ); +} + +fn test1() { + debug!("debug is enabled"); + debug!("debug is enabled"); + let _ = 0; + debug!("debug is enabled"); + unsafe { + DEBUG_LEVEL_ENABLED = true; + } + debug!("debug is enabled"); +} + +macro_rules! call_debug { + ($($arg:tt)+) => ( + fn call_print(s: &str) { + print!("{}", s); + } + + call_print("called from call_debug: "); + debug!($($arg)+); + ); +} + +fn test2() { + call_debug!("debug is enabled"); +} + +fn main() { + test1(); + test2(); + test3(); +} diff --git a/tests/coverage-map/status-quo/issue-93054.cov-map b/tests/coverage-map/status-quo/issue-93054.cov-map new file mode 100644 index 0000000000000..52fe7f58d15d8 --- /dev/null +++ b/tests/coverage-map/status-quo/issue-93054.cov-map @@ -0,0 +1,24 @@ +Function name: issue_93054::foo2 (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 00, 1d] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 29) + +Function name: issue_93054::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 00, 0d] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 30, 1) to (start + 0, 13) + +Function name: issue_93054::make (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1a, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 2) + diff --git a/tests/coverage-map/status-quo/issue-93054.rs b/tests/coverage-map/status-quo/issue-93054.rs new file mode 100644 index 0000000000000..da546cfeef854 --- /dev/null +++ b/tests/coverage-map/status-quo/issue-93054.rs @@ -0,0 +1,30 @@ +#![allow(dead_code, unreachable_code)] + +// Regression test for #93054: Functions using uninhabited types often only have a single, +// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail. +// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them. + +// compile-flags: --edition=2021 + +enum Never {} + +impl Never { + fn foo(self) { + match self {} + make().map(|never| match never {}); + } + + fn bar(&self) { + match *self {} + } +} + +async fn foo2(never: Never) { + match never {} +} + +fn make() -> Option { + None +} + +fn main() {} diff --git a/tests/coverage-map/status-quo/lazy_boolean.cov-map b/tests/coverage-map/status-quo/lazy_boolean.cov-map new file mode 100644 index 0000000000000..b18a964043355 --- /dev/null +++ b/tests/coverage-map/status-quo/lazy_boolean.cov-map @@ -0,0 +1,223 @@ +Function name: lazy_boolean::main +Raw bytes (646): 0x[01, 01, a8, 01, 01, 05, 09, 9a, 05, 9f, 05, 09, 05, 02, 05, 02, 9f, 05, 09, 05, 02, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 97, 05, 00, 09, 9a, 05, 9f, 05, 09, 05, 02, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 8f, 05, 00, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 87, 05, 00, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, ff, 04, 00, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 21, ea, 04, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, e7, 04, 25, 21, ea, 04, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 25, e2, 04, e7, 04, 25, 21, ea, 04, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 97, 05, 02, 09, 00, 11, 9f, 05, 02, 0d, 00, 12, 9a, 05, 02, 0d, 00, 12, 8f, 05, 03, 09, 00, 11, 33, 02, 0d, 00, 12, 92, 05, 02, 0d, 00, 12, 87, 05, 02, 09, 00, 11, 6f, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ff, 04, 01, 09, 00, 11, ab, 01, 00, 14, 00, 19, 15, 00, 1d, 00, 22, cb, 01, 04, 09, 00, 10, fa, 04, 01, 05, 03, 06, 19, 03, 06, 00, 07, f7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, f2, 04, 05, 05, 03, 06, ef, 04, 05, 09, 00, 10, ea, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, e7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, e2, 04, 02, 0c, 02, 06, df, 04, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 168 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 2 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 5 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 7 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 8 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 9 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 10 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 11 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 12 operands: lhs = Expression(165, Add), rhs = Zero +- expression 13 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 14 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 15 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 16 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 17 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 18 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 19 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 20 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 21 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 22 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 23 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 24 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 25 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 26 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 27 operands: lhs = Expression(163, Add), rhs = Zero +- expression 28 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 29 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 30 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 31 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 32 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 33 operands: lhs = Counter(5), rhs = Expression(160, Sub) +- expression 34 operands: lhs = Expression(161, Add), rhs = Counter(5) +- expression 35 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 36 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 37 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 38 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 39 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 40 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 41 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 42 operands: lhs = Expression(161, Add), rhs = Zero +- expression 43 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 44 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 45 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 46 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 47 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 48 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 49 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 50 operands: lhs = Expression(159, Add), rhs = Zero +- expression 51 operands: lhs = Counter(5), rhs = Expression(160, Sub) +- expression 52 operands: lhs = Expression(161, Add), rhs = Counter(5) +- expression 53 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 54 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 55 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 56 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 57 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 58 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 59 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 60 operands: lhs = Expression(159, Add), rhs = Counter(6) +- expression 61 operands: lhs = Counter(5), rhs = Expression(160, Sub) +- expression 62 operands: lhs = Expression(161, Add), rhs = Counter(5) +- expression 63 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 64 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 65 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 66 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 67 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 68 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 69 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 70 operands: lhs = Counter(6), rhs = Expression(158, Sub) +- expression 71 operands: lhs = Expression(159, Add), rhs = Counter(6) +- expression 72 operands: lhs = Counter(5), rhs = Expression(160, Sub) +- expression 73 operands: lhs = Expression(161, Add), rhs = Counter(5) +- expression 74 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 75 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 76 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 77 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 78 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 79 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 80 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 81 operands: lhs = Expression(157, Add), rhs = Counter(7) +- expression 82 operands: lhs = Counter(6), rhs = Expression(158, Sub) +- expression 83 operands: lhs = Expression(159, Add), rhs = Counter(6) +- expression 84 operands: lhs = Counter(5), rhs = Expression(160, Sub) +- expression 85 operands: lhs = Expression(161, Add), rhs = Counter(5) +- expression 86 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 87 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 88 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 89 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 90 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 91 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 92 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 93 operands: lhs = Counter(7), rhs = Expression(156, Sub) +- expression 94 operands: lhs = Expression(157, Add), rhs = Counter(7) +- expression 95 operands: lhs = Counter(6), rhs = Expression(158, Sub) +- expression 96 operands: lhs = Expression(159, Add), rhs = Counter(6) +- expression 97 operands: lhs = Counter(5), rhs = Expression(160, Sub) +- expression 98 operands: lhs = Expression(161, Add), rhs = Counter(5) +- expression 99 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 100 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 101 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 102 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 103 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 104 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 105 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 106 operands: lhs = Expression(155, Add), rhs = Counter(8) +- expression 107 operands: lhs = Counter(7), rhs = Expression(156, Sub) +- expression 108 operands: lhs = Expression(157, Add), rhs = Counter(7) +- expression 109 operands: lhs = Counter(6), rhs = Expression(158, Sub) +- expression 110 operands: lhs = Expression(159, Add), rhs = Counter(6) +- expression 111 operands: lhs = Counter(5), rhs = Expression(160, Sub) +- expression 112 operands: lhs = Expression(161, Add), rhs = Counter(5) +- expression 113 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 114 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 115 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 116 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 117 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 118 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 119 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 120 operands: lhs = Counter(8), rhs = Expression(154, Sub) +- expression 121 operands: lhs = Expression(155, Add), rhs = Counter(8) +- expression 122 operands: lhs = Counter(7), rhs = Expression(156, Sub) +- expression 123 operands: lhs = Expression(157, Add), rhs = Counter(7) +- expression 124 operands: lhs = Counter(6), rhs = Expression(158, Sub) +- expression 125 operands: lhs = Expression(159, Add), rhs = Counter(6) +- expression 126 operands: lhs = Counter(5), rhs = Expression(160, Sub) +- expression 127 operands: lhs = Expression(161, Add), rhs = Counter(5) +- expression 128 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 129 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 130 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 131 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 132 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 133 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 134 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 135 operands: lhs = Expression(153, Add), rhs = Counter(9) +- expression 136 operands: lhs = Counter(8), rhs = Expression(154, Sub) +- expression 137 operands: lhs = Expression(155, Add), rhs = Counter(8) +- expression 138 operands: lhs = Counter(7), rhs = Expression(156, Sub) +- expression 139 operands: lhs = Expression(157, Add), rhs = Counter(7) +- expression 140 operands: lhs = Counter(6), rhs = Expression(158, Sub) +- expression 141 operands: lhs = Expression(159, Add), rhs = Counter(6) +- expression 142 operands: lhs = Counter(5), rhs = Expression(160, Sub) +- expression 143 operands: lhs = Expression(161, Add), rhs = Counter(5) +- expression 144 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 145 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 146 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 147 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 148 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 149 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 150 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 151 operands: lhs = Counter(9), rhs = Expression(152, Sub) +- expression 152 operands: lhs = Expression(153, Add), rhs = Counter(9) +- expression 153 operands: lhs = Counter(8), rhs = Expression(154, Sub) +- expression 154 operands: lhs = Expression(155, Add), rhs = Counter(8) +- expression 155 operands: lhs = Counter(7), rhs = Expression(156, Sub) +- expression 156 operands: lhs = Expression(157, Add), rhs = Counter(7) +- expression 157 operands: lhs = Counter(6), rhs = Expression(158, Sub) +- expression 158 operands: lhs = Expression(159, Add), rhs = Counter(6) +- expression 159 operands: lhs = Counter(5), rhs = Expression(160, Sub) +- expression 160 operands: lhs = Expression(161, Add), rhs = Counter(5) +- expression 161 operands: lhs = Counter(4), rhs = Expression(162, Sub) +- expression 162 operands: lhs = Expression(163, Add), rhs = Counter(4) +- expression 163 operands: lhs = Counter(3), rhs = Expression(164, Sub) +- expression 164 operands: lhs = Expression(165, Add), rhs = Counter(3) +- expression 165 operands: lhs = Counter(2), rhs = Expression(166, Sub) +- expression 166 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 167 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 28 +- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) +- Code(Counter(1)) at (prev + 7, 16) to (start + 4, 6) +- Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(165, Add)) at (prev + 2, 9) to (start + 0, 17) + = (c2 + ((c1 + (c0 - c1)) - c2)) +- Code(Expression(167, Add)) at (prev + 2, 13) to (start + 0, 18) + = (c1 + (c0 - c1)) +- Code(Expression(166, Sub)) at (prev + 2, 13) to (start + 0, 18) + = ((c1 + (c0 - c1)) - c2) +- Code(Expression(163, Add)) at (prev + 3, 9) to (start + 0, 17) + = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) +- Code(Expression(12, Add)) at (prev + 2, 13) to (start + 0, 18) + = ((c2 + ((c1 + (c0 - c1)) - c2)) + Zero) +- Code(Expression(164, Sub)) at (prev + 2, 13) to (start + 0, 18) + = ((c2 + ((c1 + (c0 - c1)) - c2)) - c3) +- Code(Expression(161, Add)) at (prev + 2, 9) to (start + 0, 17) + = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) +- Code(Expression(27, Add)) at (prev + 0, 20) to (start + 0, 25) + = ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) + Zero) +- Code(Counter(4)) at (prev + 0, 29) to (start + 0, 34) +- Code(Expression(159, Add)) at (prev + 1, 9) to (start + 0, 17) + = (c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) +- Code(Expression(42, Add)) at (prev + 0, 20) to (start + 0, 25) + = ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) + Zero) +- Code(Counter(5)) at (prev + 0, 29) to (start + 0, 34) +- Code(Expression(50, Add)) at (prev + 4, 9) to (start + 0, 16) + = ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) + Zero) +- Code(Expression(158, Sub)) at (prev + 1, 5) to (start + 3, 6) + = ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6) +- Code(Counter(6)) at (prev + 3, 6) to (start + 0, 7) +- Code(Expression(157, Add)) at (prev + 3, 9) to (start + 0, 16) + = (c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) +- Code(Counter(7)) at (prev + 1, 5) to (start + 3, 6) +- Code(Expression(156, Sub)) at (prev + 5, 5) to (start + 3, 6) + = ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7) +- Code(Expression(155, Add)) at (prev + 5, 9) to (start + 0, 16) + = (c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) +- Code(Expression(154, Sub)) at (prev + 0, 17) to (start + 2, 6) + = ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8) +- Code(Counter(8)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(153, Add)) at (prev + 2, 8) to (start + 0, 15) + = (c8 + ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)) +- Code(Counter(9)) at (prev + 0, 16) to (start + 2, 6) +- Code(Expression(152, Sub)) at (prev + 2, 12) to (start + 2, 6) + = ((c8 + ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)) - c9) +- Code(Expression(151, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c9 + ((c8 + ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)) - c9)) + diff --git a/tests/coverage-map/status-quo/lazy_boolean.rs b/tests/coverage-map/status-quo/lazy_boolean.rs new file mode 100644 index 0000000000000..bb6219e851c8a --- /dev/null +++ b/tests/coverage-map/status-quo/lazy_boolean.rs @@ -0,0 +1,61 @@ +#![allow(unused_assignments, unused_variables)] + +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let (mut a, mut b, mut c) = (0, 0, 0); + if is_true { + a = 1; + b = 10; + c = 100; + } + let + somebool + = + a < b + || + b < c + ; + let + somebool + = + b < a + || + b < c + ; + let somebool = a < b && b < c; + let somebool = b < a && b < c; + + if + ! + is_true + { + a = 2 + ; + } + + if + is_true + { + b = 30 + ; + } + else + { + c = 400 + ; + } + + if !is_true { + a = 2; + } + + if is_true { + b = 30; + } else { + c = 400; + } +} diff --git a/tests/coverage-map/status-quo/loop_break_value.cov-map b/tests/coverage-map/status-quo/loop_break_value.cov-map new file mode 100644 index 0000000000000..75018442d0757 --- /dev/null +++ b/tests/coverage-map/status-quo/loop_break_value.cov-map @@ -0,0 +1,8 @@ +Function name: loop_break_value::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 0a, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 3, 1) to (start + 10, 2) + diff --git a/tests/coverage-map/status-quo/loop_break_value.rs b/tests/coverage-map/status-quo/loop_break_value.rs new file mode 100644 index 0000000000000..dbc4fad7a2316 --- /dev/null +++ b/tests/coverage-map/status-quo/loop_break_value.rs @@ -0,0 +1,13 @@ +#![allow(unused_assignments, unused_variables)] + +fn main() { + let result + = + loop + { + break + 10 + ; + } + ; +} diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage-map/status-quo/loops_branches.cov-map new file mode 100644 index 0000000000000..56fafc0a67b1f --- /dev/null +++ b/tests/coverage-map/status-quo/loops_branches.cov-map @@ -0,0 +1,193 @@ +Function name: ::fmt +Raw bytes (262): 0x[01, 01, 36, 05, 09, 0a, 02, 00, 00, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, d3, 01, d7, 01, 0d, 00, 11, 15, ca, 01, 00, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, bb, 01, 11, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, 25, b3, 01, b6, 01, 19, bb, 01, 11, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, ca, 01, 03, 0d, 00, 0e, cf, 01, 00, 12, 00, 17, 2b, 01, 10, 00, 14, c6, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, c2, 01, 01, 12, 00, 13, bb, 01, 01, 11, 00, 22, b6, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, af, 01, 01, 05, 00, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 54 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Expression(2, Sub), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Zero, rhs = Zero +- expression 3 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 4 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 5 operands: lhs = Counter(3), rhs = Zero +- expression 6 operands: lhs = Counter(4), rhs = Counter(5) +- expression 7 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 8 operands: lhs = Counter(3), rhs = Zero +- expression 9 operands: lhs = Counter(4), rhs = Counter(5) +- expression 10 operands: lhs = Expression(50, Sub), rhs = Zero +- expression 11 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 12 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 13 operands: lhs = Counter(3), rhs = Zero +- expression 14 operands: lhs = Counter(4), rhs = Counter(5) +- expression 15 operands: lhs = Expression(50, Sub), rhs = Counter(5) +- expression 16 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 17 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 18 operands: lhs = Counter(3), rhs = Zero +- expression 19 operands: lhs = Counter(4), rhs = Counter(5) +- expression 20 operands: lhs = Expression(49, Sub), rhs = Counter(7) +- expression 21 operands: lhs = Expression(50, Sub), rhs = Counter(5) +- expression 22 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 23 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 24 operands: lhs = Counter(3), rhs = Zero +- expression 25 operands: lhs = Counter(4), rhs = Counter(5) +- expression 26 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) +- expression 27 operands: lhs = Zero, rhs = Zero +- expression 28 operands: lhs = Expression(49, Sub), rhs = Counter(7) +- expression 29 operands: lhs = Expression(50, Sub), rhs = Counter(5) +- expression 30 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 31 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 32 operands: lhs = Counter(3), rhs = Zero +- expression 33 operands: lhs = Counter(4), rhs = Counter(5) +- expression 34 operands: lhs = Expression(46, Add), rhs = Counter(4) +- expression 35 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) +- expression 36 operands: lhs = Zero, rhs = Zero +- expression 37 operands: lhs = Expression(49, Sub), rhs = Counter(7) +- expression 38 operands: lhs = Expression(50, Sub), rhs = Counter(5) +- expression 39 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 40 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 41 operands: lhs = Counter(3), rhs = Zero +- expression 42 operands: lhs = Counter(4), rhs = Counter(5) +- expression 43 operands: lhs = Counter(9), rhs = Expression(44, Add) +- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(6) +- expression 45 operands: lhs = Expression(46, Add), rhs = Counter(4) +- expression 46 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) +- expression 47 operands: lhs = Zero, rhs = Zero +- expression 48 operands: lhs = Expression(49, Sub), rhs = Counter(7) +- expression 49 operands: lhs = Expression(50, Sub), rhs = Counter(5) +- expression 50 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 51 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 52 operands: lhs = Counter(3), rhs = Zero +- expression 53 operands: lhs = Counter(4), rhs = Counter(5) +Number of file 0 mappings: 20 +- Code(Counter(0)) at (prev + 9, 5) to (start + 1, 16) +- Code(Counter(1)) at (prev + 2, 16) to (start + 0, 21) +- Code(Zero) at (prev + 1, 23) to (start + 0, 27) +- Code(Zero) at (prev + 0, 28) to (start + 0, 30) +- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 15) + = (c1 - c2) +- Code(Expression(1, Add)) at (prev + 1, 13) to (start + 0, 30) + = ((Zero - Zero) + (c1 - c2)) +- Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) +- Code(Zero) at (prev + 1, 16) to (start + 1, 10) +- Code(Expression(50, Sub)) at (prev + 3, 13) to (start + 0, 14) + = (((c3 + Zero) + (c4 + c5)) - c6) +- Code(Expression(51, Add)) at (prev + 0, 18) to (start + 0, 23) + = ((c3 + Zero) + (c4 + c5)) +- Code(Expression(10, Add)) at (prev + 1, 16) to (start + 0, 20) + = ((((c3 + Zero) + (c4 + c5)) - c6) + Zero) +- Code(Expression(49, Sub)) at (prev + 1, 20) to (start + 0, 25) + = ((((c3 + Zero) + (c4 + c5)) - c6) - c5) +- Code(Zero) at (prev + 1, 27) to (start + 0, 31) +- Code(Zero) at (prev + 0, 32) to (start + 0, 34) +- Code(Expression(48, Sub)) at (prev + 1, 18) to (start + 0, 19) + = (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7) +- Code(Expression(46, Add)) at (prev + 1, 17) to (start + 0, 34) + = ((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) +- Code(Expression(45, Sub)) at (prev + 0, 34) to (start + 0, 35) + = (((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) +- Code(Zero) at (prev + 1, 20) to (start + 1, 14) +- Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) +- Code(Expression(43, Add)) at (prev + 1, 5) to (start + 0, 6) + = (c9 + ((((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) + c6)) + +Function name: ::fmt +Raw bytes (266): 0x[01, 01, 38, 01, 05, 02, 09, 0e, 12, 00, 00, 02, 09, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, d7, 01, db, 01, 05, 0d, 11, 15, ce, 01, 00, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, bf, 01, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ba, 01, df, 01, bf, 01, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, 19, 25, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 12, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, ce, 01, 02, 0d, 00, 0e, d3, 01, 00, 12, 00, 17, 33, 01, 10, 00, 15, 00, 00, 16, 01, 0e, ca, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, c6, 01, 01, 12, 00, 13, bf, 01, 01, 11, 00, 22, ba, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, b7, 01, 01, 05, 00, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 56 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2) +- expression 2 operands: lhs = Expression(3, Sub), rhs = Expression(4, Sub) +- expression 3 operands: lhs = Zero, rhs = Zero +- expression 4 operands: lhs = Expression(0, Sub), rhs = Counter(2) +- expression 5 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 6 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 7 operands: lhs = Counter(1), rhs = Counter(3) +- expression 8 operands: lhs = Counter(4), rhs = Counter(5) +- expression 9 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 10 operands: lhs = Counter(1), rhs = Counter(3) +- expression 11 operands: lhs = Counter(4), rhs = Counter(5) +- expression 12 operands: lhs = Expression(51, Sub), rhs = Zero +- expression 13 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 14 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 15 operands: lhs = Counter(1), rhs = Counter(3) +- expression 16 operands: lhs = Counter(4), rhs = Counter(5) +- expression 17 operands: lhs = Expression(51, Sub), rhs = Counter(4) +- expression 18 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 19 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 20 operands: lhs = Counter(1), rhs = Counter(3) +- expression 21 operands: lhs = Counter(4), rhs = Counter(5) +- expression 22 operands: lhs = Expression(50, Sub), rhs = Counter(7) +- expression 23 operands: lhs = Expression(51, Sub), rhs = Counter(4) +- expression 24 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 25 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 26 operands: lhs = Counter(1), rhs = Counter(3) +- expression 27 operands: lhs = Counter(4), rhs = Counter(5) +- expression 28 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) +- expression 29 operands: lhs = Zero, rhs = Zero +- expression 30 operands: lhs = Expression(50, Sub), rhs = Counter(7) +- expression 31 operands: lhs = Expression(51, Sub), rhs = Counter(4) +- expression 32 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 33 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 34 operands: lhs = Counter(1), rhs = Counter(3) +- expression 35 operands: lhs = Counter(4), rhs = Counter(5) +- expression 36 operands: lhs = Expression(47, Add), rhs = Counter(5) +- expression 37 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) +- expression 38 operands: lhs = Zero, rhs = Zero +- expression 39 operands: lhs = Expression(50, Sub), rhs = Counter(7) +- expression 40 operands: lhs = Expression(51, Sub), rhs = Counter(4) +- expression 41 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 42 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 43 operands: lhs = Counter(1), rhs = Counter(3) +- expression 44 operands: lhs = Counter(4), rhs = Counter(5) +- expression 45 operands: lhs = Expression(46, Sub), rhs = Expression(55, Add) +- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(5) +- expression 47 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) +- expression 48 operands: lhs = Zero, rhs = Zero +- expression 49 operands: lhs = Expression(50, Sub), rhs = Counter(7) +- expression 50 operands: lhs = Expression(51, Sub), rhs = Counter(4) +- expression 51 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 52 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 53 operands: lhs = Counter(1), rhs = Counter(3) +- expression 54 operands: lhs = Counter(4), rhs = Counter(5) +- expression 55 operands: lhs = Counter(6), rhs = Counter(9) +Number of file 0 mappings: 20 +- Code(Counter(0)) at (prev + 34, 5) to (start + 1, 17) +- Code(Zero) at (prev + 1, 18) to (start + 1, 10) +- Code(Expression(0, Sub)) at (prev + 2, 16) to (start + 0, 21) + = (c0 - c1) +- Code(Zero) at (prev + 1, 23) to (start + 0, 27) +- Code(Zero) at (prev + 0, 28) to (start + 0, 30) +- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 15) + = ((c0 - c1) - c2) +- Code(Expression(2, Add)) at (prev + 1, 13) to (start + 0, 30) + = ((Zero - Zero) + ((c0 - c1) - c2)) +- Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) +- Code(Expression(51, Sub)) at (prev + 2, 13) to (start + 0, 14) + = (((c1 + c3) + (c4 + c5)) - c6) +- Code(Expression(52, Add)) at (prev + 0, 18) to (start + 0, 23) + = ((c1 + c3) + (c4 + c5)) +- Code(Expression(12, Add)) at (prev + 1, 16) to (start + 0, 21) + = ((((c1 + c3) + (c4 + c5)) - c6) + Zero) +- Code(Zero) at (prev + 0, 22) to (start + 1, 14) +- Code(Expression(50, Sub)) at (prev + 2, 20) to (start + 0, 25) + = ((((c1 + c3) + (c4 + c5)) - c6) - c4) +- Code(Zero) at (prev + 1, 27) to (start + 0, 31) +- Code(Zero) at (prev + 0, 32) to (start + 0, 34) +- Code(Expression(49, Sub)) at (prev + 1, 18) to (start + 0, 19) + = (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) +- Code(Expression(47, Add)) at (prev + 1, 17) to (start + 0, 34) + = ((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) +- Code(Expression(46, Sub)) at (prev + 0, 34) to (start + 0, 35) + = (((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) +- Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) +- Code(Expression(45, Add)) at (prev + 1, 5) to (start + 0, 6) + = ((((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) + (c6 + c9)) + +Function name: loops_branches::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 37, 01, 05, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 55, 1) to (start + 5, 2) + diff --git a/tests/coverage-map/status-quo/loops_branches.rs b/tests/coverage-map/status-quo/loops_branches.rs new file mode 100644 index 0000000000000..f3a343bcc1f42 --- /dev/null +++ b/tests/coverage-map/status-quo/loops_branches.rs @@ -0,0 +1,60 @@ +#![allow(unused_assignments, unused_variables, while_true)] + +// This test confirms that (1) unexecuted infinite loops are handled correctly by the +// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped. + +struct DebugTest; + +impl std::fmt::Debug for DebugTest { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if true { + if false { + while true {} + } + write!(f, "cool")?; + } else { + } + + for i in 0..10 { + if true { + if false { + while true {} + } + write!(f, "cool")?; + } else { + } + } + Ok(()) + } +} + +struct DisplayTest; + +impl std::fmt::Display for DisplayTest { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if false { + } else { + if false { + while true {} + } + write!(f, "cool")?; + } + for i in 0..10 { + if false { + } else { + if false { + while true {} + } + write!(f, "cool")?; + } + } + Ok(()) + } +} + +fn main() { + let debug_test = DebugTest; + println!("{:?}", debug_test); + let display_test = DisplayTest; + println!("{}", display_test); +} diff --git a/tests/coverage-map/status-quo/match_or_pattern.cov-map b/tests/coverage-map/status-quo/match_or_pattern.cov-map new file mode 100644 index 0000000000000..d63407a99c35f --- /dev/null +++ b/tests/coverage-map/status-quo/match_or_pattern.cov-map @@ -0,0 +1,83 @@ +Function name: match_or_pattern::main +Raw bytes (202): 0x[01, 01, 23, 01, 05, 05, 02, 09, 0d, 2f, 11, 09, 0d, 2b, 15, 2f, 11, 09, 0d, 15, 26, 2b, 15, 2f, 11, 09, 0d, 19, 1d, 57, 21, 19, 1d, 53, 25, 57, 21, 19, 1d, 25, 4e, 53, 25, 57, 21, 19, 1d, 29, 2d, 7f, 31, 29, 2d, 7b, 35, 7f, 31, 29, 2d, 35, 76, 7b, 35, 7f, 31, 29, 2d, 39, 3d, 8b, 01, 41, 39, 3d, 19, 01, 01, 01, 08, 0f, 05, 08, 10, 03, 06, 02, 03, 06, 00, 07, 07, 01, 0b, 00, 11, 11, 03, 1b, 00, 1d, 2f, 01, 0e, 00, 10, 2b, 02, 08, 00, 0f, 15, 00, 10, 03, 06, 26, 03, 06, 00, 07, 23, 01, 0b, 00, 11, 21, 01, 1b, 00, 1d, 57, 01, 0e, 00, 10, 53, 02, 08, 00, 0f, 25, 00, 10, 03, 06, 4e, 03, 06, 00, 07, 4b, 01, 0b, 00, 11, 31, 01, 1b, 00, 1d, 7f, 01, 0e, 00, 10, 7b, 02, 08, 00, 0f, 35, 00, 10, 03, 06, 76, 03, 06, 00, 07, 73, 01, 0b, 00, 11, 41, 01, 1b, 00, 1d, 8b, 01, 01, 0e, 00, 10, 87, 01, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 35 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 3 operands: lhs = Expression(11, Add), rhs = Counter(4) +- expression 4 operands: lhs = Counter(2), rhs = Counter(3) +- expression 5 operands: lhs = Expression(10, Add), rhs = Counter(5) +- expression 6 operands: lhs = Expression(11, Add), rhs = Counter(4) +- expression 7 operands: lhs = Counter(2), rhs = Counter(3) +- expression 8 operands: lhs = Counter(5), rhs = Expression(9, Sub) +- expression 9 operands: lhs = Expression(10, Add), rhs = Counter(5) +- expression 10 operands: lhs = Expression(11, Add), rhs = Counter(4) +- expression 11 operands: lhs = Counter(2), rhs = Counter(3) +- expression 12 operands: lhs = Counter(6), rhs = Counter(7) +- expression 13 operands: lhs = Expression(21, Add), rhs = Counter(8) +- expression 14 operands: lhs = Counter(6), rhs = Counter(7) +- expression 15 operands: lhs = Expression(20, Add), rhs = Counter(9) +- expression 16 operands: lhs = Expression(21, Add), rhs = Counter(8) +- expression 17 operands: lhs = Counter(6), rhs = Counter(7) +- expression 18 operands: lhs = Counter(9), rhs = Expression(19, Sub) +- expression 19 operands: lhs = Expression(20, Add), rhs = Counter(9) +- expression 20 operands: lhs = Expression(21, Add), rhs = Counter(8) +- expression 21 operands: lhs = Counter(6), rhs = Counter(7) +- expression 22 operands: lhs = Counter(10), rhs = Counter(11) +- expression 23 operands: lhs = Expression(31, Add), rhs = Counter(12) +- expression 24 operands: lhs = Counter(10), rhs = Counter(11) +- expression 25 operands: lhs = Expression(30, Add), rhs = Counter(13) +- expression 26 operands: lhs = Expression(31, Add), rhs = Counter(12) +- expression 27 operands: lhs = Counter(10), rhs = Counter(11) +- expression 28 operands: lhs = Counter(13), rhs = Expression(29, Sub) +- expression 29 operands: lhs = Expression(30, Add), rhs = Counter(13) +- expression 30 operands: lhs = Expression(31, Add), rhs = Counter(12) +- expression 31 operands: lhs = Counter(10), rhs = Counter(11) +- expression 32 operands: lhs = Counter(14), rhs = Counter(15) +- expression 33 operands: lhs = Expression(34, Add), rhs = Counter(16) +- expression 34 operands: lhs = Counter(14), rhs = Counter(15) +Number of file 0 mappings: 25 +- Code(Counter(0)) at (prev + 1, 1) to (start + 8, 15) +- Code(Counter(1)) at (prev + 8, 16) to (start + 3, 6) +- Code(Expression(0, Sub)) at (prev + 3, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 11) to (start + 0, 17) + = (c1 + (c0 - c1)) +- Code(Counter(4)) at (prev + 3, 27) to (start + 0, 29) +- Code(Expression(11, Add)) at (prev + 1, 14) to (start + 0, 16) + = (c2 + c3) +- Code(Expression(10, Add)) at (prev + 2, 8) to (start + 0, 15) + = ((c2 + c3) + c4) +- Code(Counter(5)) at (prev + 0, 16) to (start + 3, 6) +- Code(Expression(9, Sub)) at (prev + 3, 6) to (start + 0, 7) + = (((c2 + c3) + c4) - c5) +- Code(Expression(8, Add)) at (prev + 1, 11) to (start + 0, 17) + = (c5 + (((c2 + c3) + c4) - c5)) +- Code(Counter(8)) at (prev + 1, 27) to (start + 0, 29) +- Code(Expression(21, Add)) at (prev + 1, 14) to (start + 0, 16) + = (c6 + c7) +- Code(Expression(20, Add)) at (prev + 2, 8) to (start + 0, 15) + = ((c6 + c7) + c8) +- Code(Counter(9)) at (prev + 0, 16) to (start + 3, 6) +- Code(Expression(19, Sub)) at (prev + 3, 6) to (start + 0, 7) + = (((c6 + c7) + c8) - c9) +- Code(Expression(18, Add)) at (prev + 1, 11) to (start + 0, 17) + = (c9 + (((c6 + c7) + c8) - c9)) +- Code(Counter(12)) at (prev + 1, 27) to (start + 0, 29) +- Code(Expression(31, Add)) at (prev + 1, 14) to (start + 0, 16) + = (c10 + c11) +- Code(Expression(30, Add)) at (prev + 2, 8) to (start + 0, 15) + = ((c10 + c11) + c12) +- Code(Counter(13)) at (prev + 0, 16) to (start + 3, 6) +- Code(Expression(29, Sub)) at (prev + 3, 6) to (start + 0, 7) + = (((c10 + c11) + c12) - c13) +- Code(Expression(28, Add)) at (prev + 1, 11) to (start + 0, 17) + = (c13 + (((c10 + c11) + c12) - c13)) +- Code(Counter(16)) at (prev + 1, 27) to (start + 0, 29) +- Code(Expression(34, Add)) at (prev + 1, 14) to (start + 0, 16) + = (c14 + c15) +- Code(Expression(33, Add)) at (prev + 2, 1) to (start + 0, 2) + = ((c14 + c15) + c16) + diff --git a/tests/coverage-map/status-quo/match_or_pattern.rs b/tests/coverage-map/status-quo/match_or_pattern.rs new file mode 100644 index 0000000000000..ab7aee51d1bc4 --- /dev/null +++ b/tests/coverage-map/status-quo/match_or_pattern.rs @@ -0,0 +1,43 @@ +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut a: u8 = 0; + let mut b: u8 = 0; + if is_true { + a = 2; + b = 0; + } + match (a, b) { + // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`. + // This test confirms a fix for Issue #79569. + (0 | 1, 2 | 3) => {} + _ => {} + } + if is_true { + a = 0; + b = 0; + } + match (a, b) { + (0 | 1, 2 | 3) => {} + _ => {} + } + if is_true { + a = 2; + b = 2; + } + match (a, b) { + (0 | 1, 2 | 3) => {} + _ => {} + } + if is_true { + a = 0; + b = 2; + } + match (a, b) { + (0 | 1, 2 | 3) => {} + _ => {} + } +} diff --git a/tests/coverage-map/status-quo/nested_loops.cov-map b/tests/coverage-map/status-quo/nested_loops.cov-map new file mode 100644 index 0000000000000..35d92594e75e3 --- /dev/null +++ b/tests/coverage-map/status-quo/nested_loops.cov-map @@ -0,0 +1,51 @@ +Function name: nested_loops::main +Raw bytes (115): 0x[01, 01, 17, 01, 57, 05, 09, 03, 0d, 4e, 53, 03, 0d, 15, 19, 4b, 09, 4e, 53, 03, 0d, 15, 19, 46, 05, 4b, 09, 4e, 53, 03, 0d, 15, 19, 42, 19, 46, 05, 4b, 09, 4e, 53, 03, 0d, 15, 19, 05, 09, 11, 0d, 0d, 01, 01, 01, 02, 1b, 03, 04, 13, 00, 20, 4e, 01, 0d, 01, 18, 4b, 02, 12, 00, 17, 46, 01, 10, 00, 16, 05, 01, 11, 00, 16, 42, 01, 0e, 03, 16, 3e, 04, 11, 01, 1b, 11, 02, 15, 00, 21, 15, 01, 18, 02, 12, 19, 03, 0e, 00, 0f, 57, 02, 09, 00, 17, 5b, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 23 +- expression 0 operands: lhs = Counter(0), rhs = Expression(21, Add) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 3 operands: lhs = Expression(19, Sub), rhs = Expression(20, Add) +- expression 4 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 5 operands: lhs = Counter(5), rhs = Counter(6) +- expression 6 operands: lhs = Expression(18, Add), rhs = Counter(2) +- expression 7 operands: lhs = Expression(19, Sub), rhs = Expression(20, Add) +- expression 8 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 9 operands: lhs = Counter(5), rhs = Counter(6) +- expression 10 operands: lhs = Expression(17, Sub), rhs = Counter(1) +- expression 11 operands: lhs = Expression(18, Add), rhs = Counter(2) +- expression 12 operands: lhs = Expression(19, Sub), rhs = Expression(20, Add) +- expression 13 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 14 operands: lhs = Counter(5), rhs = Counter(6) +- expression 15 operands: lhs = Expression(16, Sub), rhs = Counter(6) +- expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(1) +- expression 17 operands: lhs = Expression(18, Add), rhs = Counter(2) +- expression 18 operands: lhs = Expression(19, Sub), rhs = Expression(20, Add) +- expression 19 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 20 operands: lhs = Counter(5), rhs = Counter(6) +- expression 21 operands: lhs = Counter(1), rhs = Counter(2) +- expression 22 operands: lhs = Counter(4), rhs = Counter(3) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 1, 1) to (start + 2, 27) +- Code(Expression(0, Add)) at (prev + 4, 19) to (start + 0, 32) + = (c0 + (c1 + c2)) +- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 1, 24) + = ((c0 + (c1 + c2)) - c3) +- Code(Expression(18, Add)) at (prev + 2, 18) to (start + 0, 23) + = (((c0 + (c1 + c2)) - c3) + (c5 + c6)) +- Code(Expression(17, Sub)) at (prev + 1, 16) to (start + 0, 22) + = ((((c0 + (c1 + c2)) - c3) + (c5 + c6)) - c2) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 22) +- Code(Expression(16, Sub)) at (prev + 1, 14) to (start + 3, 22) + = (((((c0 + (c1 + c2)) - c3) + (c5 + c6)) - c2) - c1) +- Code(Expression(15, Sub)) at (prev + 4, 17) to (start + 1, 27) + = ((((((c0 + (c1 + c2)) - c3) + (c5 + c6)) - c2) - c1) - c6) +- Code(Counter(4)) at (prev + 2, 21) to (start + 0, 33) +- Code(Counter(5)) at (prev + 1, 24) to (start + 2, 18) +- Code(Counter(6)) at (prev + 3, 14) to (start + 0, 15) +- Code(Expression(21, Add)) at (prev + 2, 9) to (start + 0, 23) + = (c1 + c2) +- Code(Expression(22, Add)) at (prev + 2, 1) to (start + 0, 2) + = (c4 + c3) + diff --git a/tests/coverage-map/status-quo/nested_loops.rs b/tests/coverage-map/status-quo/nested_loops.rs new file mode 100644 index 0000000000000..4c7c784279650 --- /dev/null +++ b/tests/coverage-map/status-quo/nested_loops.rs @@ -0,0 +1,25 @@ +fn main() { + let is_true = std::env::args().len() == 1; + let mut countdown = 10; + + 'outer: while countdown > 0 { + let mut a = 100; + let mut b = 100; + for _ in 0..50 { + if a < 30 { + break; + } + a -= 5; + b -= 5; + if b < 90 { + a -= 10; + if is_true { + break 'outer; + } else { + a -= 2; + } + } + } + countdown -= 1; + } +} diff --git a/tests/coverage-map/status-quo/no_cov_crate.cov-map b/tests/coverage-map/status-quo/no_cov_crate.cov-map new file mode 100644 index 0000000000000..7ab5995dc2892 --- /dev/null +++ b/tests/coverage-map/status-quo/no_cov_crate.cov-map @@ -0,0 +1,78 @@ +Function name: no_cov_crate::add_coverage_1 +Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 20, 1) to (start + 2, 2) + +Function name: no_cov_crate::add_coverage_2 +Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 24, 1) to (start + 2, 2) + +Function name: no_cov_crate::add_coverage_not_called (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) + +Function name: no_cov_crate::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 4d, 01, 0b, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 77, 1) to (start + 11, 2) + +Function name: no_cov_crate::nested_fns::outer +Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 05, 0c, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 49, 5) to (start + 12, 6) + +Function name: no_cov_crate::nested_fns::outer_both_covered +Raw bytes (9): 0x[01, 01, 00, 01, 01, 3f, 05, 0b, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 63, 5) to (start + 11, 6) + +Function name: no_cov_crate::nested_fns::outer_both_covered::inner +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 43, 09, 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 + 67, 9) 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)) + +Function name: no_cov_crate::nested_fns::outer_not_covered::inner +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 26, 09, 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 + 38, 9) 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)) + diff --git a/tests/coverage-map/status-quo/no_cov_crate.rs b/tests/coverage-map/status-quo/no_cov_crate.rs new file mode 100644 index 0000000000000..5b748aeefb767 --- /dev/null +++ b/tests/coverage-map/status-quo/no_cov_crate.rs @@ -0,0 +1,88 @@ +// Enables `no_coverage` on the entire crate +#![feature(no_coverage)] + +#[no_coverage] +fn do_not_add_coverage_1() { + println!("called but not covered"); +} + +fn do_not_add_coverage_2() { + #![no_coverage] + println!("called but not covered"); +} + +#[no_coverage] +#[allow(dead_code)] +fn do_not_add_coverage_not_called() { + println!("not called and not covered"); +} + +fn add_coverage_1() { + println!("called and covered"); +} + +fn add_coverage_2() { + println!("called and covered"); +} + +#[allow(dead_code)] +fn add_coverage_not_called() { + println!("not called but covered"); +} + +// FIXME: These test-cases illustrate confusing results of nested functions. +// See https://github.com/rust-lang/rust/issues/93319 +mod nested_fns { + #[no_coverage] + pub fn outer_not_covered(is_true: bool) { + fn inner(is_true: bool) { + if is_true { + println!("called and covered"); + } else { + println!("absolutely not covered"); + } + } + println!("called but not covered"); + inner(is_true); + } + + pub fn outer(is_true: bool) { + println!("called and covered"); + inner_not_covered(is_true); + + #[no_coverage] + fn inner_not_covered(is_true: bool) { + if is_true { + println!("called but not covered"); + } else { + println!("absolutely not covered"); + } + } + } + + pub fn outer_both_covered(is_true: bool) { + println!("called and covered"); + inner(is_true); + + fn inner(is_true: bool) { + if is_true { + println!("called and covered"); + } else { + println!("absolutely not covered"); + } + } + } +} + +fn main() { + let is_true = std::env::args().len() == 1; + + do_not_add_coverage_1(); + do_not_add_coverage_2(); + add_coverage_1(); + add_coverage_2(); + + nested_fns::outer_not_covered(is_true); + nested_fns::outer(is_true); + nested_fns::outer_both_covered(is_true); +} diff --git a/tests/coverage-map/status-quo/overflow.cov-map b/tests/coverage-map/status-quo/overflow.cov-map new file mode 100644 index 0000000000000..bfffd9b2ab515 --- /dev/null +++ b/tests/coverage-map/status-quo/overflow.cov-map @@ -0,0 +1,43 @@ +Function name: overflow::main +Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 0f, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 8 +- expression 0 operands: lhs = Counter(0), rhs = Expression(6, Add) +- expression 1 operands: lhs = Counter(1), rhs = Expression(7, Add) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(4) +- expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(1) +- expression 5 operands: lhs = Expression(0, Add), rhs = Counter(4) +- expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add) +- expression 7 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 27) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24) + = (c0 + (c1 + (c2 + c3))) +- Code(Expression(5, Sub)) at (prev + 1, 12) to (start + 0, 26) + = ((c0 + (c1 + (c2 + c3))) - c4) +- Code(Counter(1)) at (prev + 0, 27) to (start + 3, 10) +- Code(Expression(4, Sub)) at (prev + 3, 19) to (start + 0, 32) + = (((c0 + (c1 + (c2 + c3))) - c4) - c1) +- Code(Counter(2)) at (prev + 0, 33) to (start + 3, 10) +- Code(Counter(3)) at (prev + 3, 10) to (start + 0, 11) +- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) + = (c1 + (c2 + c3)) +- Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) + +Function name: overflow::might_overflow +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 07, 01, 09, 05, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 18) +- Code(Counter(1)) at (prev + 1, 19) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 9) to (start + 5, 2) + = (c1 + (c0 - c1)) + diff --git a/tests/coverage-map/status-quo/overflow.rs b/tests/coverage-map/status-quo/overflow.rs new file mode 100644 index 0000000000000..bbb65c1b35df6 --- /dev/null +++ b/tests/coverage-map/status-quo/overflow.rs @@ -0,0 +1,63 @@ +#![allow(unused_assignments)] +// failure-status: 101 + +fn might_overflow(to_add: u32) -> u32 { + if to_add > 5 { + println!("this will probably overflow"); + } + let add_to = u32::MAX - 5; + println!("does {} + {} overflow?", add_to, to_add); + let result = to_add + add_to; + println!("continuing after overflow check"); + result +} + +fn main() -> Result<(), u8> { + let mut countdown = 10; + while countdown > 0 { + if countdown == 1 { + let result = might_overflow(10); + println!("Result: {}", result); + } else if countdown < 5 { + let result = might_overflow(1); + println!("Result: {}", result); + } + countdown -= 1; + } + Ok(()) +} + +// Notes: +// 1. Compare this program and its coverage results to those of the very similar test `assert.rs`, +// and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`. +// 2. This test confirms the coverage generated when a program passes or fails a +// compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case). +// 3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`, +// compiler-generated assertion failures are assumed to be a symptom of a program bug, not +// expected behavior. To simplify the coverage graphs and keep instrumented programs as +// small and fast as possible, `Assert` terminators are assumed to always succeed, and +// therefore are considered "non-branching" terminators. So, an `Assert` terminator does not +// get its own coverage counter. +// 4. After an unhandled panic or failed Assert, coverage results may not always be intuitive. +// In this test, the final count for the statements after the `if` block in `might_overflow()` +// is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending +// on the MIR graph and the structure of the code, this count could have been 3 (which might +// have been valid for the overflowed add `+`, but should have been 4 for the lines before +// the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented +// via StatementKind::Counter at the end of the block, but (as in the case in this test), +// a CounterKind::Expression is always evaluated. In this case, the expression was based on +// a `Counter` incremented as part of the evaluation of the `if` expression, which was +// executed, and counted, 4 times, before reaching the overflow add. + +// If the program did not overflow, the coverage for `might_overflow()` would look like this: +// +// 4| |fn might_overflow(to_add: u32) -> u32 { +// 5| 4| if to_add > 5 { +// 6| 0| println!("this will probably overflow"); +// 7| 4| } +// 8| 4| let add_to = u32::MAX - 5; +// 9| 4| println!("does {} + {} overflow?", add_to, to_add); +// 10| 4| let result = to_add + add_to; +// 11| 4| println!("continuing after overflow check"); +// 12| 4| result +// 13| 4|} diff --git a/tests/coverage-map/status-quo/panic_unwind.cov-map b/tests/coverage-map/status-quo/panic_unwind.cov-map new file mode 100644 index 0000000000000..f6089ce55ae29 --- /dev/null +++ b/tests/coverage-map/status-quo/panic_unwind.cov-map @@ -0,0 +1,40 @@ +Function name: panic_unwind::main +Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 02, 0a, 12, 02, 13, 00, 20, 09, 00, 21, 02, 0a, 0d, 02, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 8 +- expression 0 operands: lhs = Counter(0), rhs = Expression(6, Add) +- expression 1 operands: lhs = Counter(1), rhs = Expression(7, Add) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(4) +- expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(1) +- expression 5 operands: lhs = Expression(0, Add), rhs = Counter(4) +- expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add) +- expression 7 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 13, 1) to (start + 1, 27) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24) + = (c0 + (c1 + (c2 + c3))) +- Code(Expression(5, Sub)) at (prev + 1, 12) to (start + 0, 26) + = ((c0 + (c1 + (c2 + c3))) - c4) +- Code(Counter(1)) at (prev + 0, 27) to (start + 2, 10) +- Code(Expression(4, Sub)) at (prev + 2, 19) to (start + 0, 32) + = (((c0 + (c1 + (c2 + c3))) - c4) - c1) +- Code(Counter(2)) at (prev + 0, 33) to (start + 2, 10) +- Code(Counter(3)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) + = (c1 + (c2 + c3)) +- Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) + +Function name: panic_unwind::might_panic +Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 19, 02, 02, 0c, 03, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20) +- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 25) +- Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) + = (c0 - c1) + diff --git a/tests/coverage-map/status-quo/panic_unwind.rs b/tests/coverage-map/status-quo/panic_unwind.rs new file mode 100644 index 0000000000000..638d2eb6aaaf8 --- /dev/null +++ b/tests/coverage-map/status-quo/panic_unwind.rs @@ -0,0 +1,31 @@ +#![allow(unused_assignments)] +// failure-status: 101 + +fn might_panic(should_panic: bool) { + if should_panic { + println!("panicking..."); + panic!("panics"); + } else { + println!("Don't Panic"); + } +} + +fn main() -> Result<(), u8> { + let mut countdown = 10; + while countdown > 0 { + if countdown == 1 { + might_panic(true); + } else if countdown < 5 { + might_panic(false); + } + countdown -= 1; + } + Ok(()) +} + +// Notes: +// 1. Compare this program and its coverage results to those of the similar tests `abort.rs` and +// `try_error_result.rs`. +// 2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the +// normal program exit cleanup, including writing out the current values of the coverage +// counters. diff --git a/tests/coverage-map/status-quo/partial_eq.cov-map b/tests/coverage-map/status-quo/partial_eq.cov-map new file mode 100644 index 0000000000000..dd61cd77ab619 --- /dev/null +++ b/tests/coverage-map/status-quo/partial_eq.cov-map @@ -0,0 +1,64 @@ +Function name: ::clone (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 0a, 00, 0f] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 4, 10) to (start + 0, 15) + +Function name: ::cmp (unused) +Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 33, 00, 34, 00, 00, 35, 00, 36] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 4, 51) to (start + 0, 52) +- Code(Zero) at (prev + 0, 53) to (start + 0, 54) + +Function name: ::eq (unused) +Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 18, 00, 19, 00, 00, 20, 00, 21] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 4, 24) to (start + 0, 25) +- Code(Zero) at (prev + 0, 32) to (start + 0, 33) + +Function name: ::partial_cmp +Raw bytes (22): 0x[01, 01, 04, 07, 0b, 05, 09, 0f, 15, 0d, 11, 02, 01, 04, 27, 00, 28, 03, 00, 30, 00, 31] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(2, Add) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5) +- expression 3 operands: lhs = Counter(3), rhs = Counter(4) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 4, 39) to (start + 0, 40) +- Code(Expression(0, Add)) at (prev + 0, 48) to (start + 0, 49) + = ((c1 + c2) + ((c3 + c4) + c5)) + +Function name: ::fmt +Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 11, 00, 16] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 4, 17) to (start + 0, 22) + +Function name: ::new +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 05, 06, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 12, 5) to (start + 6, 6) + +Function name: partial_eq::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 05, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 21, 1) to (start + 5, 2) + diff --git a/tests/coverage-map/status-quo/partial_eq.rs b/tests/coverage-map/status-quo/partial_eq.rs new file mode 100644 index 0000000000000..dd8b42c18cea9 --- /dev/null +++ b/tests/coverage-map/status-quo/partial_eq.rs @@ -0,0 +1,46 @@ +// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the +// structure of this test. + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Version { + major: usize, + minor: usize, + patch: usize, +} + +impl Version { + pub fn new(major: usize, minor: usize, patch: usize) -> Self { + Self { + major, + minor, + patch, + } + } +} + +fn main() { + let version_3_2_1 = Version::new(3, 2, 1); + let version_3_3_0 = Version::new(3, 3, 0); + + println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0); +} + +/* + +This test verifies a bug was fixed that otherwise generated this error: + +thread 'rustc' panicked at 'No counters provided the source_hash for function: + Instance { + def: Item(WithOptConstParam { + did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp), + const_param_did: None + }), + args: [] + }' +The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage +without a code region associated with any `Counter`. Code regions were associated with at least +one expression, which is allowed, but the `function_source_hash` was only passed to the codegen +(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the +`function_source_hash` without a code region, if necessary. + +*/ diff --git a/tests/coverage-map/status-quo/simple_loop.cov-map b/tests/coverage-map/status-quo/simple_loop.cov-map new file mode 100644 index 0000000000000..eb49c2324ccce --- /dev/null +++ b/tests/coverage-map/status-quo/simple_loop.cov-map @@ -0,0 +1,28 @@ +Function name: simple_loop::main +Raw bytes (59): 0x[01, 01, 0a, 01, 05, 27, 09, 05, 02, 23, 09, 27, 09, 05, 02, 1e, 00, 23, 09, 27, 09, 05, 02, 07, 01, 03, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 06, 00, 07, 23, 05, 0d, 02, 0e, 1e, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 1b, 06, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 10 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(9, Add), rhs = Counter(2) +- expression 2 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 3 operands: lhs = Expression(8, Add), rhs = Counter(2) +- expression 4 operands: lhs = Expression(9, Add), rhs = Counter(2) +- expression 5 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 6 operands: lhs = Expression(7, Sub), rhs = Zero +- expression 7 operands: lhs = Expression(8, Add), rhs = Counter(2) +- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(2) +- expression 9 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 3, 1) to (start + 9, 16) +- Code(Counter(1)) at (prev + 10, 5) to (start + 5, 6) +- Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(8, Add)) at (prev + 5, 13) to (start + 2, 14) + = ((c1 + (c0 - c1)) + c2) +- Code(Expression(7, Sub)) at (prev + 4, 13) to (start + 0, 18) + = (((c1 + (c0 - c1)) + c2) - c2) +- Code(Counter(2)) at (prev + 2, 10) to (start + 3, 10) +- Code(Expression(6, Add)) at (prev + 6, 1) to (start + 0, 2) + = ((((c1 + (c0 - c1)) + c2) - c2) + Zero) + diff --git a/tests/coverage-map/status-quo/simple_loop.rs b/tests/coverage-map/status-quo/simple_loop.rs new file mode 100644 index 0000000000000..6f7f23475b826 --- /dev/null +++ b/tests/coverage-map/status-quo/simple_loop.rs @@ -0,0 +1,35 @@ +#![allow(unused_assignments)] + +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut countdown = 0; + + if + is_true + { + countdown + = + 10 + ; + } + + loop + { + if + countdown + == + 0 + { + break + ; + } + countdown + -= + 1 + ; + } +} diff --git a/tests/coverage-map/status-quo/simple_match.cov-map b/tests/coverage-map/status-quo/simple_match.cov-map new file mode 100644 index 0000000000000..d5389f04b2615 --- /dev/null +++ b/tests/coverage-map/status-quo/simple_match.cov-map @@ -0,0 +1,36 @@ +Function name: simple_match::main +Raw bytes (82): 0x[01, 01, 0e, 01, 05, 2f, 33, 05, 02, 09, 0d, 2b, 11, 2f, 33, 05, 02, 09, 0d, 26, 00, 2b, 11, 2f, 33, 05, 02, 09, 0d, 09, 00, 0a, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 2b, 05, 09, 00, 0d, 26, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 23, 02, 11, 02, 12, 37, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 14 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(11, Add), rhs = Expression(12, Add) +- expression 2 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 3 operands: lhs = Counter(2), rhs = Counter(3) +- expression 4 operands: lhs = Expression(10, Add), rhs = Counter(4) +- expression 5 operands: lhs = Expression(11, Add), rhs = Expression(12, Add) +- expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 7 operands: lhs = Counter(2), rhs = Counter(3) +- expression 8 operands: lhs = Expression(9, Sub), rhs = Zero +- expression 9 operands: lhs = Expression(10, Add), rhs = Counter(4) +- expression 10 operands: lhs = Expression(11, Add), rhs = Expression(12, Add) +- expression 11 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 12 operands: lhs = Counter(2), rhs = Counter(3) +- expression 13 operands: lhs = Counter(2), rhs = Zero +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) +- Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(10, Add)) at (prev + 5, 9) to (start + 0, 13) + = ((c1 + (c0 - c1)) + (c2 + c3)) +- Code(Expression(9, Sub)) at (prev + 5, 13) to (start + 0, 22) + = (((c1 + (c0 - c1)) + (c2 + c3)) - c4) +- Code(Counter(2)) at (prev + 2, 13) to (start + 0, 14) +- Code(Expression(8, Add)) at (prev + 2, 17) to (start + 2, 18) + = ((((c1 + (c0 - c1)) + (c2 + c3)) - c4) + Zero) +- Code(Expression(13, Add)) at (prev + 4, 13) to (start + 7, 14) + = (c2 + Zero) +- Code(Counter(3)) at (prev + 10, 13) to (start + 0, 15) +- Code(Counter(4)) at (prev + 3, 1) to (start + 0, 2) + diff --git a/tests/coverage-map/status-quo/simple_match.rs b/tests/coverage-map/status-quo/simple_match.rs new file mode 100644 index 0000000000000..be99e59a82685 --- /dev/null +++ b/tests/coverage-map/status-quo/simple_match.rs @@ -0,0 +1,43 @@ +#![allow(unused_assignments, unused_variables)] + +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut countdown = 1; + if is_true { + countdown = 0; + } + + for + _ + in + 0..2 + { + let z + ; + match + countdown + { + x + if + x + < + 1 + => + { + z = countdown + ; + let y = countdown + ; + countdown = 10 + ; + } + _ + => + {} + } + } +} diff --git a/tests/coverage-map/status-quo/sort_groups.cov-map b/tests/coverage-map/status-quo/sort_groups.cov-map new file mode 100644 index 0000000000000..7156a66cf8984 --- /dev/null +++ b/tests/coverage-map/status-quo/sort_groups.cov-map @@ -0,0 +1,68 @@ +Function name: sort_groups::generic_fn::<&str> +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) +- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: sort_groups::generic_fn::<()> +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) +- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: sort_groups::generic_fn:: +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) +- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: sort_groups::main +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 04, 0d, 00, 04, 0e, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 02, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 13) +- Code(Zero) at (prev + 4, 14) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 2, 2) + = (c1 + (c0 - c1)) + +Function name: sort_groups::other_fn +Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 11] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 17) + diff --git a/tests/coverage-map/status-quo/sort_groups.rs b/tests/coverage-map/status-quo/sort_groups.rs new file mode 100644 index 0000000000000..f89f9f3ec61fa --- /dev/null +++ b/tests/coverage-map/status-quo/sort_groups.rs @@ -0,0 +1,23 @@ +// compile-flags: --edition=2021 + +// Demonstrate that `sort_subviews.py` can sort instantiation groups into a +// predictable order, while preserving their heterogeneous contents. + +fn main() { + let cond = std::env::args().len() > 1; + generic_fn::<()>(cond); + generic_fn::<&'static str>(!cond); + if false { + generic_fn::(cond); + } + generic_fn::(cond); + other_fn(); +} + +fn generic_fn(cond: bool) { + if cond { + println!("{}", std::any::type_name::()); + } +} + +fn other_fn() {} diff --git a/tests/coverage-map/status-quo/test_harness.cov-map b/tests/coverage-map/status-quo/test_harness.cov-map new file mode 100644 index 0000000000000..b0e955dd142a5 --- /dev/null +++ b/tests/coverage-map/status-quo/test_harness.cov-map @@ -0,0 +1,24 @@ +Function name: test_harness::my_test +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 00, 10] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 16) + +Function name: test_harness::my_test::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 01, 00, 08] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 8) + +Function name: test_harness::unused (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 0f] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 15) + diff --git a/tests/coverage-map/status-quo/test_harness.rs b/tests/coverage-map/status-quo/test_harness.rs new file mode 100644 index 0000000000000..12a755734c198 --- /dev/null +++ b/tests/coverage-map/status-quo/test_harness.rs @@ -0,0 +1,10 @@ +// Verify that the entry point injected by the test harness doesn't cause +// weird artifacts in the coverage report (e.g. issue #10749). + +// compile-flags: --test + +#[allow(dead_code)] +fn unused() {} + +#[test] +fn my_test() {} diff --git a/tests/coverage-map/status-quo/tight_inf_loop.cov-map b/tests/coverage-map/status-quo/tight_inf_loop.cov-map new file mode 100644 index 0000000000000..76884212c14fa --- /dev/null +++ b/tests/coverage-map/status-quo/tight_inf_loop.cov-map @@ -0,0 +1,12 @@ +Function name: tight_inf_loop::main +Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 01, 01, 01, 0d, 00, 02, 09, 00, 10, 02, 01, 06, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 1, 1) to (start + 1, 13) +- Code(Zero) at (prev + 2, 9) to (start + 0, 16) +- Code(Expression(0, Sub)) at (prev + 1, 6) to (start + 1, 2) + = (c0 - c1) + diff --git a/tests/coverage-map/status-quo/tight_inf_loop.rs b/tests/coverage-map/status-quo/tight_inf_loop.rs new file mode 100644 index 0000000000000..cef99027aaa4f --- /dev/null +++ b/tests/coverage-map/status-quo/tight_inf_loop.rs @@ -0,0 +1,5 @@ +fn main() { + if false { + loop {} + } +} diff --git a/tests/coverage-map/status-quo/try_error_result.cov-map b/tests/coverage-map/status-quo/try_error_result.cov-map new file mode 100644 index 0000000000000..b52e78d1195ab --- /dev/null +++ b/tests/coverage-map/status-quo/try_error_result.cov-map @@ -0,0 +1,226 @@ +Function name: ::get_thing_2 +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 28, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 1a, 07, 02, 05, 00, 06] +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 + 40, 5) to (start + 1, 24) +- Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) +- Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 26) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 2, 5) to (start + 0, 6) + = (c1 + (c0 - c1)) + +Function name: ::call +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 33, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 07, 02, 05, 00, 06] +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 + 51, 5) to (start + 1, 24) +- Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) +- Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 2, 5) to (start + 0, 6) + = (c1 + (c0 - c1)) + +Function name: try_error_result::call +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 07, 02, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20) +- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 2, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: try_error_result::main +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 70, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 07, 01, 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 = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 112, 1) to (start + 2, 12) +- Code(Counter(1)) at (prev + 3, 5) to (start + 0, 6) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: try_error_result::test1 +Raw bytes (77): 0x[01, 01, 09, 01, 07, 05, 09, 03, 0d, 1d, 11, 16, 1d, 03, 0d, 1f, 0d, 11, 23, 15, 19, 0b, 01, 0c, 01, 02, 17, 03, 07, 09, 00, 0e, 16, 02, 09, 04, 1a, 1d, 06, 0d, 00, 29, 11, 00, 29, 00, 2a, 0e, 01, 0d, 00, 2a, 15, 00, 2a, 00, 2b, 12, 04, 0d, 00, 2a, 19, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 1b, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 9 +- expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 3 operands: lhs = Counter(7), rhs = Counter(4) +- expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(7) +- expression 5 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(3) +- expression 7 operands: lhs = Counter(4), rhs = Expression(8, Add) +- expression 8 operands: lhs = Counter(5), rhs = Counter(6) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 12, 1) to (start + 2, 23) +- Code(Expression(0, Add)) at (prev + 7, 9) to (start + 0, 14) + = (c0 + (c1 + c2)) +- Code(Expression(5, Sub)) at (prev + 2, 9) to (start + 4, 26) + = ((c0 + (c1 + c2)) - c3) +- Code(Counter(7)) at (prev + 6, 13) to (start + 0, 41) +- Code(Counter(4)) at (prev + 0, 41) to (start + 0, 42) +- Code(Expression(3, Sub)) at (prev + 1, 13) to (start + 0, 42) + = (c7 - c4) +- Code(Counter(5)) at (prev + 0, 42) to (start + 0, 43) +- Code(Expression(4, Sub)) at (prev + 4, 13) to (start + 0, 42) + = (((c0 + (c1 + c2)) - c3) - c7) +- Code(Counter(6)) at (prev + 0, 42) to (start + 0, 43) +- Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11) +- Code(Expression(6, Add)) at (prev + 1, 1) to (start + 0, 2) + = ((c4 + (c5 + c6)) + c3) + +Function name: try_error_result::test2 +Raw bytes (373): 0x[01, 01, 41, 01, 07, 05, 09, 03, 0d, 41, 11, 52, 15, 41, 11, 4a, 1d, 4e, 19, 52, 15, 41, 11, 4e, 00, 52, 15, 41, 11, 4e, 19, 52, 15, 41, 11, 46, 00, 4a, 1d, 4e, 19, 52, 15, 41, 11, 6a, 25, 49, 21, 49, 21, 66, 00, 6a, 25, 49, 21, 9a, 01, 2d, 9e, 01, 29, a2, 01, 41, 03, 0d, a2, 01, 41, 03, 0d, 9e, 01, 29, a2, 01, 41, 03, 0d, 96, 01, 00, 9a, 01, 2d, 9e, 01, 29, a2, 01, 41, 03, 0d, ba, 01, 35, 45, 31, 45, 31, b6, 01, 00, ba, 01, 35, 45, 31, d2, 01, 3d, 4d, 39, 4d, 39, ce, 01, 00, d2, 01, 3d, 4d, 39, db, 01, 0d, 11, df, 01, e3, 01, f3, 01, 15, e7, 01, eb, 01, ef, 01, 19, 1d, 21, 25, f7, 01, fb, 01, 29, 2d, ff, 01, 83, 02, 31, 35, 39, 3d, 28, 01, 3c, 01, 03, 17, 03, 08, 09, 00, 0e, a2, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 52, 00, 31, 03, 35, 15, 04, 11, 00, 12, 4e, 02, 11, 04, 12, 46, 05, 11, 00, 14, 2b, 00, 17, 00, 41, 19, 00, 41, 00, 42, 4a, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 43, 01, 0d, 00, 20, 66, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 6a, 00, 43, 00, 60, 25, 00, 60, 00, 61, 63, 01, 0d, 00, 20, 96, 01, 04, 11, 00, 14, 9e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 9a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 93, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, ba, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, b3, 01, 01, 0d, 00, 20, ce, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, d2, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, cb, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, d7, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 65 +- expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 3 operands: lhs = Counter(16), rhs = Counter(4) +- expression 4 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 5 operands: lhs = Counter(16), rhs = Counter(4) +- expression 6 operands: lhs = Expression(18, Sub), rhs = Counter(7) +- expression 7 operands: lhs = Expression(19, Sub), rhs = Counter(6) +- expression 8 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 9 operands: lhs = Counter(16), rhs = Counter(4) +- expression 10 operands: lhs = Expression(19, Sub), rhs = Zero +- expression 11 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 12 operands: lhs = Counter(16), rhs = Counter(4) +- expression 13 operands: lhs = Expression(19, Sub), rhs = Counter(6) +- expression 14 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 15 operands: lhs = Counter(16), rhs = Counter(4) +- expression 16 operands: lhs = Expression(17, Sub), rhs = Zero +- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(7) +- expression 18 operands: lhs = Expression(19, Sub), rhs = Counter(6) +- expression 19 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 20 operands: lhs = Counter(16), rhs = Counter(4) +- expression 21 operands: lhs = Expression(26, Sub), rhs = Counter(9) +- expression 22 operands: lhs = Counter(18), rhs = Counter(8) +- expression 23 operands: lhs = Counter(18), rhs = Counter(8) +- expression 24 operands: lhs = Expression(25, Sub), rhs = Zero +- expression 25 operands: lhs = Expression(26, Sub), rhs = Counter(9) +- expression 26 operands: lhs = Counter(18), rhs = Counter(8) +- expression 27 operands: lhs = Expression(38, Sub), rhs = Counter(11) +- expression 28 operands: lhs = Expression(39, Sub), rhs = Counter(10) +- expression 29 operands: lhs = Expression(40, Sub), rhs = Counter(16) +- expression 30 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 31 operands: lhs = Expression(40, Sub), rhs = Counter(16) +- expression 32 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 33 operands: lhs = Expression(39, Sub), rhs = Counter(10) +- expression 34 operands: lhs = Expression(40, Sub), rhs = Counter(16) +- expression 35 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 36 operands: lhs = Expression(37, Sub), rhs = Zero +- expression 37 operands: lhs = Expression(38, Sub), rhs = Counter(11) +- expression 38 operands: lhs = Expression(39, Sub), rhs = Counter(10) +- expression 39 operands: lhs = Expression(40, Sub), rhs = Counter(16) +- expression 40 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 41 operands: lhs = Expression(46, Sub), rhs = Counter(13) +- expression 42 operands: lhs = Counter(17), rhs = Counter(12) +- expression 43 operands: lhs = Counter(17), rhs = Counter(12) +- expression 44 operands: lhs = Expression(45, Sub), rhs = Zero +- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(13) +- expression 46 operands: lhs = Counter(17), rhs = Counter(12) +- expression 47 operands: lhs = Expression(52, Sub), rhs = Counter(15) +- expression 48 operands: lhs = Counter(19), rhs = Counter(14) +- expression 49 operands: lhs = Counter(19), rhs = Counter(14) +- expression 50 operands: lhs = Expression(51, Sub), rhs = Zero +- expression 51 operands: lhs = Expression(52, Sub), rhs = Counter(15) +- expression 52 operands: lhs = Counter(19), rhs = Counter(14) +- expression 53 operands: lhs = Expression(54, Add), rhs = Counter(3) +- expression 54 operands: lhs = Counter(4), rhs = Expression(55, Add) +- expression 55 operands: lhs = Expression(56, Add), rhs = Expression(60, Add) +- expression 56 operands: lhs = Counter(5), rhs = Expression(57, Add) +- expression 57 operands: lhs = Expression(58, Add), rhs = Expression(59, Add) +- expression 58 operands: lhs = Counter(6), rhs = Counter(7) +- expression 59 operands: lhs = Counter(8), rhs = Counter(9) +- expression 60 operands: lhs = Expression(61, Add), rhs = Expression(62, Add) +- expression 61 operands: lhs = Counter(10), rhs = Counter(11) +- expression 62 operands: lhs = Expression(63, Add), rhs = Expression(64, Add) +- expression 63 operands: lhs = Counter(12), rhs = Counter(13) +- expression 64 operands: lhs = Counter(14), rhs = Counter(15) +Number of file 0 mappings: 40 +- Code(Counter(0)) at (prev + 60, 1) to (start + 3, 23) +- Code(Expression(0, Add)) at (prev + 8, 9) to (start + 0, 14) + = (c0 + (c1 + c2)) +- Code(Expression(40, Sub)) at (prev + 2, 9) to (start + 4, 26) + = ((c0 + (c1 + c2)) - c3) +- Code(Counter(16)) at (prev + 6, 13) to (start + 0, 47) +- Code(Counter(4)) at (prev + 0, 47) to (start + 0, 48) +- Code(Expression(20, Sub)) at (prev + 0, 49) to (start + 3, 53) + = (c16 - c4) +- Code(Counter(5)) at (prev + 4, 17) to (start + 0, 18) +- Code(Expression(19, Sub)) at (prev + 2, 17) to (start + 4, 18) + = ((c16 - c4) - c5) +- Code(Expression(17, Sub)) at (prev + 5, 17) to (start + 0, 20) + = ((((c16 - c4) - c5) - c6) - c7) +- Code(Expression(10, Add)) at (prev + 0, 23) to (start + 0, 65) + = (((c16 - c4) - c5) + Zero) +- Code(Counter(6)) at (prev + 0, 65) to (start + 0, 66) +- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 95) + = (((c16 - c4) - c5) - c6) +- Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96) +- Code(Expression(16, Add)) at (prev + 1, 13) to (start + 0, 32) + = (((((c16 - c4) - c5) - c6) - c7) + Zero) +- Code(Expression(25, Sub)) at (prev + 1, 17) to (start + 0, 20) + = ((c18 - c8) - c9) +- Code(Counter(18)) at (prev + 0, 23) to (start + 0, 65) +- Code(Counter(8)) at (prev + 0, 65) to (start + 0, 66) +- Code(Expression(26, Sub)) at (prev + 0, 67) to (start + 0, 96) + = (c18 - c8) +- Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97) +- Code(Expression(24, Add)) at (prev + 1, 13) to (start + 0, 32) + = (((c18 - c8) - c9) + Zero) +- Code(Expression(37, Sub)) at (prev + 4, 17) to (start + 0, 20) + = (((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11) +- Code(Expression(39, Sub)) at (prev + 0, 23) to (start + 0, 66) + = (((c0 + (c1 + c2)) - c3) - c16) +- Code(Counter(10)) at (prev + 0, 66) to (start + 0, 67) +- Code(Expression(38, Sub)) at (prev + 0, 68) to (start + 0, 97) + = ((((c0 + (c1 + c2)) - c3) - c16) - c10) +- Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98) +- Code(Expression(36, Add)) at (prev + 1, 13) to (start + 0, 32) + = ((((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11) + Zero) +- Code(Expression(45, Sub)) at (prev + 1, 17) to (start + 0, 20) + = ((c17 - c12) - c13) +- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 54) +- Code(Counter(12)) at (prev + 1, 54) to (start + 0, 55) +- Code(Expression(46, Sub)) at (prev + 1, 18) to (start + 0, 47) + = (c17 - c12) +- Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48) +- Code(Expression(44, Add)) at (prev + 1, 13) to (start + 0, 32) + = (((c17 - c12) - c13) + Zero) +- Code(Expression(51, Sub)) at (prev + 1, 17) to (start + 0, 20) + = ((c19 - c14) - c15) +- Code(Counter(19)) at (prev + 0, 23) to (start + 1, 54) +- Code(Counter(14)) at (prev + 2, 17) to (start + 0, 18) +- Code(Expression(52, Sub)) at (prev + 1, 18) to (start + 0, 47) + = (c19 - c14) +- Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18) +- Code(Expression(50, Add)) at (prev + 2, 13) to (start + 0, 32) + = (((c19 - c14) - c15) + Zero) +- Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11) +- Code(Expression(53, Add)) at (prev + 1, 1) to (start + 0, 2) + = ((c4 + ((c5 + ((c6 + c7) + (c8 + c9))) + ((c10 + c11) + ((c12 + c13) + (c14 + c15))))) + c3) + diff --git a/tests/coverage-map/status-quo/try_error_result.rs b/tests/coverage-map/status-quo/try_error_result.rs new file mode 100644 index 0000000000000..557cbf22bfad4 --- /dev/null +++ b/tests/coverage-map/status-quo/try_error_result.rs @@ -0,0 +1,118 @@ +#![allow(unused_assignments)] +// failure-status: 1 + +fn call(return_error: bool) -> Result<(), ()> { + if return_error { + Err(()) + } else { + Ok(()) + } +} + +fn test1() -> Result<(), ()> { + let mut + countdown = 10 + ; + for + _ + in + 0..10 + { + countdown + -= 1 + ; + if + countdown < 5 + { + call(/*return_error=*/ true)?; + call(/*return_error=*/ false)?; + } + else + { + call(/*return_error=*/ false)?; + } + } + Ok(()) +} + +struct Thing1; +impl Thing1 { + fn get_thing_2(&self, return_error: bool) -> Result { + if return_error { + Err(()) + } else { + Ok(Thing2 {}) + } + } +} + +struct Thing2; +impl Thing2 { + fn call(&self, return_error: bool) -> Result { + if return_error { + Err(()) + } else { + Ok(57) + } + } +} + +fn test2() -> Result<(), ()> { + let thing1 = Thing1{}; + let mut + countdown = 10 + ; + for + _ + in + 0..10 + { + countdown + -= 1 + ; + if + countdown < 5 + { + thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail"); + thing1 + . + get_thing_2(/*return_error=*/ false) + ? + . + call(/*return_error=*/ true) + . + expect_err( + "call should fail" + ); + let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?; + assert_eq!(val, 57); + let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?; + assert_eq!(val, 57); + } + else + { + let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?; + assert_eq!(val, 57); + let val = thing1 + .get_thing_2(/*return_error=*/ false)? + .call(/*return_error=*/ false)?; + assert_eq!(val, 57); + let val = thing1 + .get_thing_2(/*return_error=*/ false) + ? + .call(/*return_error=*/ false) + ? + ; + assert_eq!(val, 57); + } + } + Ok(()) +} + +fn main() -> Result<(), ()> { + test1().expect_err("test1 should fail"); + test2() + ? + ; + Ok(()) +} diff --git a/tests/coverage-map/status-quo/unused.cov-map b/tests/coverage-map/status-quo/unused.cov-map new file mode 100644 index 0000000000000..c8b8f195fbd5b --- /dev/null +++ b/tests/coverage-map/status-quo/unused.cov-map @@ -0,0 +1,94 @@ +Function name: unused::foo:: +Raw bytes (42): 0x[01, 01, 04, 01, 0f, 05, 09, 03, 0d, 05, 09, 06, 01, 03, 01, 01, 12, 03, 02, 0b, 00, 11, 0a, 01, 09, 00, 0f, 09, 00, 13, 00, 19, 0f, 01, 09, 00, 0f, 0d, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(0), rhs = Expression(3, Add) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 3 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 3, 1) to (start + 1, 18) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 17) + = (c0 + (c1 + c2)) +- Code(Expression(2, Sub)) at (prev + 1, 9) to (start + 0, 15) + = ((c0 + (c1 + c2)) - c3) +- Code(Counter(2)) at (prev + 0, 19) to (start + 0, 25) +- Code(Expression(3, Add)) at (prev + 1, 9) to (start + 0, 15) + = (c1 + c2) +- Code(Counter(3)) at (prev + 2, 1) to (start + 0, 2) + +Function name: unused::foo:: +Raw bytes (42): 0x[01, 01, 04, 01, 0f, 05, 09, 03, 0d, 05, 09, 06, 01, 03, 01, 01, 12, 03, 02, 0b, 00, 11, 0a, 01, 09, 00, 0f, 09, 00, 13, 00, 19, 0f, 01, 09, 00, 0f, 0d, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(0), rhs = Expression(3, Add) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 3 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 3, 1) to (start + 1, 18) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 17) + = (c0 + (c1 + c2)) +- Code(Expression(2, Sub)) at (prev + 1, 9) to (start + 0, 15) + = ((c0 + (c1 + c2)) - c3) +- Code(Counter(2)) at (prev + 0, 19) to (start + 0, 25) +- Code(Expression(3, Add)) at (prev + 1, 9) to (start + 0, 15) + = (c1 + c2) +- Code(Counter(3)) at (prev + 2, 1) to (start + 0, 2) + +Function name: unused::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 04, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 37, 1) to (start + 4, 2) + +Function name: unused::unused_func (unused) +Raw bytes (24): 0x[01, 01, 00, 04, 01, 13, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 14) +- Code(Zero) at (prev + 1, 15) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) + +Function name: unused::unused_func2 (unused) +Raw bytes (24): 0x[01, 01, 00, 04, 01, 19, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 25, 1) to (start + 1, 14) +- Code(Zero) at (prev + 1, 15) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) + +Function name: unused::unused_func3 (unused) +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1f, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 31, 1) to (start + 1, 14) +- Code(Zero) at (prev + 1, 15) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) + +Function name: unused::unused_template_func::<_> (unused) +Raw bytes (34): 0x[01, 01, 00, 06, 01, 0b, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 11, 1) to (start + 1, 18) +- Code(Zero) at (prev + 2, 11) to (start + 0, 17) +- Code(Zero) at (prev + 1, 9) to (start + 0, 15) +- Code(Zero) at (prev + 0, 19) to (start + 0, 25) +- Code(Zero) at (prev + 1, 9) to (start + 0, 15) +- Code(Zero) at (prev + 2, 1) to (start + 0, 2) + diff --git a/tests/coverage-map/status-quo/unused.rs b/tests/coverage-map/status-quo/unused.rs new file mode 100644 index 0000000000000..d985af135470e --- /dev/null +++ b/tests/coverage-map/status-quo/unused.rs @@ -0,0 +1,41 @@ +#![allow(dead_code, unused_assignments, unused_must_use, unused_variables)] + +fn foo(x: T) { + let mut i = 0; + while i < 10 { + i != 0 || i != 0; + i += 1; + } +} + +fn unused_template_func(x: T) { + let mut i = 0; + while i < 10 { + i != 0 || i != 0; + i += 1; + } +} + +fn unused_func(mut a: u32) { + if a != 0 { + a += 1; + } +} + +fn unused_func2(mut a: u32) { + if a != 0 { + a += 1; + } +} + +fn unused_func3(mut a: u32) { + if a != 0 { + a += 1; + } +} + +fn main() -> Result<(), u8> { + foo::(0); + foo::(0.0); + Ok(()) +} diff --git a/tests/coverage-map/status-quo/while.cov-map b/tests/coverage-map/status-quo/while.cov-map new file mode 100644 index 0000000000000..cfd2be96a0db9 --- /dev/null +++ b/tests/coverage-map/status-quo/while.cov-map @@ -0,0 +1,15 @@ +Function name: while::main +Raw bytes (28): 0x[01, 01, 02, 01, 05, 03, 05, 04, 01, 01, 01, 01, 10, 03, 02, 0b, 00, 14, 00, 00, 15, 01, 06, 06, 02, 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: 4 +- Code(Counter(0)) at (prev + 1, 1) to (start + 1, 16) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 20) + = (c0 + c1) +- Code(Zero) at (prev + 0, 21) to (start + 1, 6) +- Code(Expression(1, Sub)) at (prev + 2, 1) to (start + 0, 2) + = ((c0 + c1) - c1) + diff --git a/tests/coverage-map/status-quo/while.rs b/tests/coverage-map/status-quo/while.rs new file mode 100644 index 0000000000000..781b90b35663e --- /dev/null +++ b/tests/coverage-map/status-quo/while.rs @@ -0,0 +1,5 @@ +fn main() { + let num = 9; + while num >= 10 { + } +} diff --git a/tests/coverage-map/status-quo/while_early_ret.cov-map b/tests/coverage-map/status-quo/while_early_ret.cov-map new file mode 100644 index 0000000000000..369ebe891f127 --- /dev/null +++ b/tests/coverage-map/status-quo/while_early_ret.cov-map @@ -0,0 +1,26 @@ +Function name: while_early_ret::main +Raw bytes (61): 0x[01, 01, 06, 01, 05, 03, 09, 0e, 05, 03, 09, 17, 09, 0d, 11, 09, 01, 04, 01, 01, 1b, 03, 03, 09, 02, 0a, 0e, 05, 0d, 02, 0e, 0a, 06, 15, 02, 16, 0d, 04, 15, 00, 1b, 11, 04, 15, 00, 1b, 05, 03, 0a, 03, 0a, 09, 06, 05, 00, 0b, 13, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 6 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(0, Add), rhs = Counter(2) +- expression 2 operands: lhs = Expression(3, Sub), rhs = Counter(1) +- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(2) +- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(2) +- expression 5 operands: lhs = Counter(3), rhs = Counter(4) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 27) +- Code(Expression(0, Add)) at (prev + 3, 9) to (start + 2, 10) + = (c0 + c1) +- Code(Expression(3, Sub)) at (prev + 5, 13) to (start + 2, 14) + = ((c0 + c1) - c2) +- Code(Expression(2, Sub)) at (prev + 6, 21) to (start + 2, 22) + = (((c0 + c1) - c2) - c1) +- Code(Counter(3)) at (prev + 4, 21) to (start + 0, 27) +- Code(Counter(4)) at (prev + 4, 21) to (start + 0, 27) +- Code(Counter(1)) at (prev + 3, 10) to (start + 3, 10) +- Code(Counter(2)) at (prev + 6, 5) to (start + 0, 11) +- Code(Expression(4, Add)) at (prev + 1, 1) to (start + 0, 2) + = ((c3 + c4) + c2) + diff --git a/tests/coverage-map/status-quo/while_early_ret.rs b/tests/coverage-map/status-quo/while_early_ret.rs new file mode 100644 index 0000000000000..b2f0eee2cc0f4 --- /dev/null +++ b/tests/coverage-map/status-quo/while_early_ret.rs @@ -0,0 +1,42 @@ +#![allow(unused_assignments)] +// failure-status: 1 + +fn main() -> Result<(), u8> { + let mut countdown = 10; + while + countdown + > + 0 + { + if + countdown + < + 5 + { + return + if + countdown + > + 8 + { + Ok(()) + } + else + { + Err(1) + } + ; + } + countdown + -= + 1 + ; + } + Ok(()) +} + +// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and +// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux +// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program +// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical +// to the coverage test for early returns, but this is a limitation that should be fixed. diff --git a/tests/coverage-map/status-quo/yield.cov-map b/tests/coverage-map/status-quo/yield.cov-map new file mode 100644 index 0000000000000..16caa2db343bb --- /dev/null +++ b/tests/coverage-map/status-quo/yield.cov-map @@ -0,0 +1,72 @@ +Function name: yield::main +Raw bytes (118): 0x[01, 01, 11, 01, 00, 05, 09, 0d, 00, 0d, 11, 32, 15, 0d, 11, 11, 15, 2e, 00, 32, 15, 0d, 11, 2e, 00, 32, 15, 0d, 11, 19, 1d, 21, 00, 25, 29, 2d, 00, 10, 01, 07, 01, 01, 16, 03, 06, 0b, 00, 2e, 0d, 01, 27, 00, 29, 07, 01, 0e, 00, 34, 0b, 02, 0b, 00, 2e, 32, 01, 22, 00, 27, 2e, 00, 2c, 00, 2e, 1b, 01, 0e, 00, 34, 1f, 03, 09, 00, 16, 2b, 07, 0b, 00, 2e, 21, 01, 27, 00, 29, 37, 01, 0e, 00, 34, 3b, 02, 0b, 00, 2e, 2d, 01, 27, 00, 29, 3f, 01, 0e, 00, 34, 43, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 17 +- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Counter(3), rhs = Zero +- expression 3 operands: lhs = Counter(3), rhs = Counter(4) +- expression 4 operands: lhs = Expression(12, Sub), rhs = Counter(5) +- expression 5 operands: lhs = Counter(3), rhs = Counter(4) +- expression 6 operands: lhs = Counter(4), rhs = Counter(5) +- expression 7 operands: lhs = Expression(11, Sub), rhs = Zero +- expression 8 operands: lhs = Expression(12, Sub), rhs = Counter(5) +- expression 9 operands: lhs = Counter(3), rhs = Counter(4) +- expression 10 operands: lhs = Expression(11, Sub), rhs = Zero +- expression 11 operands: lhs = Expression(12, Sub), rhs = Counter(5) +- expression 12 operands: lhs = Counter(3), rhs = Counter(4) +- expression 13 operands: lhs = Counter(6), rhs = Counter(7) +- expression 14 operands: lhs = Counter(8), rhs = Zero +- expression 15 operands: lhs = Counter(9), rhs = Counter(10) +- expression 16 operands: lhs = Counter(11), rhs = Zero +Number of file 0 mappings: 16 +- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 22) +- Code(Expression(0, Add)) at (prev + 6, 11) to (start + 0, 46) + = (c0 + Zero) +- Code(Counter(3)) at (prev + 1, 39) to (start + 0, 41) +- Code(Expression(1, Add)) at (prev + 1, 14) to (start + 0, 52) + = (c1 + c2) +- Code(Expression(2, Add)) at (prev + 2, 11) to (start + 0, 46) + = (c3 + Zero) +- Code(Expression(12, Sub)) at (prev + 1, 34) to (start + 0, 39) + = (c3 - c4) +- Code(Expression(11, Sub)) at (prev + 0, 44) to (start + 0, 46) + = ((c3 - c4) - c5) +- Code(Expression(6, Add)) at (prev + 1, 14) to (start + 0, 52) + = (c4 + c5) +- Code(Expression(7, Add)) at (prev + 3, 9) to (start + 0, 22) + = (((c3 - c4) - c5) + Zero) +- Code(Expression(10, Add)) at (prev + 7, 11) to (start + 0, 46) + = (((c3 - c4) - c5) + Zero) +- Code(Counter(8)) at (prev + 1, 39) to (start + 0, 41) +- Code(Expression(13, Add)) at (prev + 1, 14) to (start + 0, 52) + = (c6 + c7) +- Code(Expression(14, Add)) at (prev + 2, 11) to (start + 0, 46) + = (c8 + Zero) +- Code(Counter(11)) at (prev + 1, 39) to (start + 0, 41) +- Code(Expression(15, Add)) at (prev + 1, 14) to (start + 0, 52) + = (c9 + c10) +- Code(Expression(16, Add)) at (prev + 2, 1) to (start + 0, 2) + = (c11 + Zero) + +Function name: yield::main::{closure#0} +Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 1c, 01, 10, 05, 02, 10, 01, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 8, 28) to (start + 1, 16) +- Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) + +Function name: yield::main::{closure#1} +Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 1c, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 16) +- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) +- Code(Counter(2)) at (prev + 1, 9) to (start + 0, 16) +- Code(Counter(3)) at (prev + 1, 16) to (start + 1, 6) + diff --git a/tests/coverage-map/status-quo/yield.rs b/tests/coverage-map/status-quo/yield.rs new file mode 100644 index 0000000000000..361275c921585 --- /dev/null +++ b/tests/coverage-map/status-quo/yield.rs @@ -0,0 +1,37 @@ +#![feature(generators, generator_trait)] +#![allow(unused_assignments)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +fn main() { + let mut generator = || { + yield 1; + return "foo"; + }; + + match Pin::new(&mut generator).resume(()) { + GeneratorState::Yielded(1) => {} + _ => panic!("unexpected value from resume"), + } + match Pin::new(&mut generator).resume(()) { + GeneratorState::Complete("foo") => {} + _ => panic!("unexpected value from resume"), + } + + let mut generator = || { + yield 1; + yield 2; + yield 3; + return "foo"; + }; + + match Pin::new(&mut generator).resume(()) { + GeneratorState::Yielded(1) => {} + _ => panic!("unexpected value from resume"), + } + match Pin::new(&mut generator).resume(()) { + GeneratorState::Yielded(2) => {} + _ => panic!("unexpected value from resume"), + } +}