Auto merge of #80055 - GuillaumeGomez:rollup-p09mweg, r=GuillaumeGomez

Rollup of 6 pull requests

Successful merges:

 - #79379 (Show hidden elements by default when JS is disabled)
 - #79796 (Hide associated constants too when collapsing implementation)
 - #79958 (Fixes reported bugs in Rust Coverage)
 - #80008 (Fix `cargo-binutils` link)
 - #80016 (Use imports instead of rewriting the type signature of `RustcOptGroup::stable`)
 - #80025 (Replace some `println!` with `tidy_error!` to simplify)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2020-12-15 15:58:46 +00:00
commit e15ec667ce
25 changed files with 657 additions and 96 deletions

View File

@ -587,7 +587,7 @@ fn test_debugging_options_tracking_hash() {
tracked!(share_generics, Some(true));
tracked!(show_span, Some(String::from("abc")));
tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
tracked!(symbol_mangling_version, SymbolManglingVersion::V0);
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
tracked!(teach, true);
tracked!(thinlto, Some(true));
tracked!(tune_cpu, Some(String::from("abc")));

View File

@ -706,7 +706,7 @@ impl<'a> CrateLoader<'a> {
self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime());
}
fn inject_profiler_runtime(&mut self) {
fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
if (self.sess.opts.debugging_opts.instrument_coverage
|| self.sess.opts.debugging_opts.profile
|| self.sess.opts.cg.profile_generate.enabled())
@ -714,6 +714,13 @@ impl<'a> CrateLoader<'a> {
{
info!("loading profiler");
if self.sess.contains_name(&krate.attrs, sym::no_core) {
self.sess.err(
"`profiler_builtins` crate (required by compiler options) \
is not compatible with crate attribute `#![no_core]`",
);
}
let name = sym::profiler_builtins;
let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
let data = self.cstore.get_crate_data(cnum);
@ -879,7 +886,7 @@ impl<'a> CrateLoader<'a> {
}
pub fn postprocess(&mut self, krate: &ast::Crate) {
self.inject_profiler_runtime();
self.inject_profiler_runtime(krate);
self.inject_allocator_crate(krate);
self.inject_panic_runtime(krate);

View File

@ -663,7 +663,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version,
symbol_mangling_version: tcx.sess.opts.debugging_opts.get_symbol_mangling_version(),
crate_deps,
dylib_dependency_formats,

View File

@ -32,24 +32,28 @@ impl CoverageGraph {
// Pre-transform MIR `BasicBlock` successors and predecessors into the BasicCoverageBlock
// equivalents. Note that since the BasicCoverageBlock graph has been fully simplified, the
// each predecessor of a BCB leader_bb should be in a unique BCB, and each successor of a
// BCB last_bb should be in its own unique BCB. Therefore, collecting the BCBs using
// `bb_to_bcb` should work without requiring a deduplication step.
// each predecessor of a BCB leader_bb should be in a unique BCB. It is possible for a
// `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so
// de-duplication is required. This is done without reordering the successors.
let bcbs_len = bcbs.len();
let mut seen = IndexVec::from_elem_n(false, bcbs_len);
let successors = IndexVec::from_fn_n(
|bcb| {
for b in seen.iter_mut() {
*b = false;
}
let bcb_data = &bcbs[bcb];
let bcb_successors =
let mut bcb_successors = Vec::new();
for successor in
bcb_filtered_successors(&mir_body, &bcb_data.terminator(mir_body).kind)
.filter_map(|&successor_bb| bb_to_bcb[successor_bb])
.collect::<Vec<_>>();
debug_assert!({
let mut sorted = bcb_successors.clone();
sorted.sort_unstable();
let initial_len = sorted.len();
sorted.dedup();
sorted.len() == initial_len
});
{
if !seen[successor] {
seen[successor] = true;
bcb_successors.push(successor);
}
}
bcb_successors
},
bcbs.len(),

View File

@ -78,6 +78,14 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
return;
}
match mir_body.basic_blocks()[mir::START_BLOCK].terminator().kind {
TerminatorKind::Unreachable => {
trace!("InstrumentCoverage skipped for unreachable `START_BLOCK`");
return;
}
_ => {}
}
trace!("InstrumentCoverage starting for {:?}", mir_source.def_id());
Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
trace!("InstrumentCoverage starting for {:?}", mir_source.def_id());

View File

@ -41,14 +41,6 @@ impl<'tcx> MirPass<'tcx> for Inline {
return;
}
if tcx.sess.opts.debugging_opts.instrument_coverage {
// The current implementation of source code coverage injects code region counters
// into the MIR, and assumes a 1-to-1 correspondence between MIR and source-code-
// based function.
debug!("function inlining is disabled when compiling with `instrument_coverage`");
return;
}
if inline(tcx, body) {
debug!("running simplify cfg on {:?}", body.source);
CfgSimplifier::new(body).simplify();

View File

@ -692,6 +692,10 @@ impl DebuggingOptions {
deduplicate_diagnostics: self.deduplicate_diagnostics,
}
}
pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion {
self.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy)
}
}
// The type of entry function, so users can have their own entry functions
@ -1757,7 +1761,30 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
// and reversible name mangling. Note, LLVM coverage tools can analyze coverage over
// multiple runs, including some changes to source code; so mangled names must be consistent
// across compilations.
debugging_opts.symbol_mangling_version = SymbolManglingVersion::V0;
match debugging_opts.symbol_mangling_version {
None => {
debugging_opts.symbol_mangling_version = Some(SymbolManglingVersion::V0);
}
Some(SymbolManglingVersion::Legacy) => {
early_warn(
error_format,
"-Z instrument-coverage requires symbol mangling version `v0`, \
but `-Z symbol-mangling-version=legacy` was specified",
);
}
Some(SymbolManglingVersion::V0) => {}
}
if debugging_opts.mir_opt_level > 1 {
early_warn(
error_format,
&format!(
"`-Z mir-opt-level={}` (any level > 1) enables function inlining, which \
limits the effectiveness of `-Z instrument-coverage`.",
debugging_opts.mir_opt_level,
),
);
}
}
if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
@ -2162,7 +2189,7 @@ crate mod dep_tracking {
impl_dep_tracking_hash_via_hash!(Edition);
impl_dep_tracking_hash_via_hash!(LinkerPluginLto);
impl_dep_tracking_hash_via_hash!(SwitchWithOptPath);
impl_dep_tracking_hash_via_hash!(SymbolManglingVersion);
impl_dep_tracking_hash_via_hash!(Option<SymbolManglingVersion>);
impl_dep_tracking_hash_via_hash!(Option<SourceFileHashAlgorithm>);
impl_dep_tracking_hash_via_hash!(TrimmedDefPaths);

View File

@ -677,12 +677,12 @@ macro_rules! options {
}
fn parse_symbol_mangling_version(
slot: &mut SymbolManglingVersion,
slot: &mut Option<SymbolManglingVersion>,
v: Option<&str>,
) -> bool {
*slot = match v {
Some("legacy") => SymbolManglingVersion::Legacy,
Some("v0") => SymbolManglingVersion::V0,
Some("legacy") => Some(SymbolManglingVersion::Legacy),
Some("v0") => Some(SymbolManglingVersion::V0),
_ => return false,
};
true
@ -1088,9 +1088,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"),
strip: Strip = (Strip::None, parse_strip, [UNTRACKED],
"tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
symbol_mangling_version: SymbolManglingVersion = (SymbolManglingVersion::Legacy,
symbol_mangling_version: Option<SymbolManglingVersion> = (None,
parse_symbol_mangling_version, [TRACKED],
"which mangling version to use for symbol names"),
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
teach: bool = (false, parse_bool, [TRACKED],
"show extended diagnostic help (default: no)"),
terminal_width: Option<usize> = (None, parse_opt_uint, [UNTRACKED],

View File

@ -245,7 +245,7 @@ fn compute_symbol_name(
// 2. we favor `instantiating_crate` where possible (i.e. when `Some`)
let mangling_version_crate = instantiating_crate.unwrap_or(def_id.krate);
let mangling_version = if mangling_version_crate == LOCAL_CRATE {
tcx.sess.opts.debugging_opts.symbol_mangling_version
tcx.sess.opts.debugging_opts.get_symbol_mangling_version()
} else {
tcx.symbol_mangling_version(mangling_version_crate)
};

View File

@ -118,7 +118,7 @@ LLVM's supplies two tools—`llvm-profdata` and `llvm-cov`—that process covera
* If you are building the Rust compiler from source, you can optionally use the bundled LLVM tools, built from source. Those tool binaries can typically be found in your build platform directory at something like: `rust/build/x86_64-unknown-linux-gnu/llvm/bin/llvm-*`.
* You can install compatible versions of these tools via `rustup`.
The `rustup` option is guaranteed to install a compatible version of the LLVM tools, but they can be hard to find. We recommend [`cargo-bintools`], which installs Rust-specific wrappers around these and other LLVM tools, so you can invoke them via `cargo` commands!
The `rustup` option is guaranteed to install a compatible version of the LLVM tools, but they can be hard to find. We recommend [`cargo-binutils`], which installs Rust-specific wrappers around these and other LLVM tools, so you can invoke them via `cargo` commands!
```shell
$ rustup component add llvm-tools-preview
@ -320,8 +320,8 @@ Rust's implementation and workflow for source-based code coverage is based on th
[rustc-dev-guide-how-to-build-and-run]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html
[`rustfilt`]: https://crates.io/crates/rustfilt
[`json5format`]: https://crates.io/crates/json5format
[`cargo-bintools`]: https://crates.io/crates/cargo-bintools
[`cargo-binutils`]: https://crates.io/crates/cargo-binutils
[`llvm-profdata merge`]: https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-merge
[`llvm-cov report`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report
[`llvm-cov show`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-show
[source-based code coverage in Clang]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
[source-based code coverage in Clang]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html

View File

@ -2274,9 +2274,12 @@ function defocusSearchBar() {
function implHider(addOrRemove, fullHide) {
return function(n) {
var is_method = hasClass(n, "method") || fullHide;
if (is_method || hasClass(n, "type")) {
if (is_method === true) {
var shouldHide =
fullHide === true ||
hasClass(n, "method") === true ||
hasClass(n, "associatedconstant") === true;
if (shouldHide === true || hasClass(n, "type") === true) {
if (shouldHide === true) {
if (addOrRemove) {
addClass(n, "hidden-by-impl-hider");
} else {

View File

@ -1,3 +1,9 @@
/*
This whole CSS file is used only in case rustdoc is rendered with javascript disabled. Since a lot
of content is hidden by default (depending on the settings too), we have to overwrite some of the
rules.
*/
#main > h2 + div, #main > h2 + h3, #main > h3 + div {
display: block;
}
@ -13,3 +19,7 @@
#main > h2 + h3 {
display: flex;
}
#main .impl-items .hidden {
display: block !important;
}

View File

@ -117,21 +117,9 @@ fn get_args() -> Option<Vec<String>> {
.collect()
}
fn stable<F>(name: &'static str, f: F) -> RustcOptGroup
where
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
{
RustcOptGroup::stable(name, f)
}
fn unstable<F>(name: &'static str, f: F) -> RustcOptGroup
where
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
{
RustcOptGroup::unstable(name, f)
}
fn opts() -> Vec<RustcOptGroup> {
let stable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::stable;
let unstable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::unstable;
vec![
stable("h", |o| o.optflag("h", "help", "show this help message")),
stable("V", |o| o.optflag("V", "version", "print rustdoc's version")),

View File

@ -0,0 +1,59 @@
{
"data": [
{
"files": [
{
"filename": "../coverage/match_or_pattern.rs",
"summary": {
"functions": {
"count": 1,
"covered": 1,
"percent": 100
},
"instantiations": {
"count": 1,
"covered": 1,
"percent": 100
},
"lines": {
"count": 37,
"covered": 33,
"percent": 89.1891891891892
},
"regions": {
"count": 25,
"covered": 17,
"notcovered": 8,
"percent": 68
}
}
}
],
"totals": {
"functions": {
"count": 1,
"covered": 1,
"percent": 100
},
"instantiations": {
"count": 1,
"covered": 1,
"percent": 100
},
"lines": {
"count": 37,
"covered": 33,
"percent": 89.1891891891892
},
"regions": {
"count": 25,
"covered": 17,
"notcovered": 8,
"percent": 68
}
}
}
],
"type": "llvm.coverage.json.export",
"version": "2.0.1"
}

View File

@ -0,0 +1,50 @@
1| |#![feature(or_patterns)]
2| |
3| 1|fn main() {
4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
6| 1| // dependent conditions.
7| 1| let is_true = std::env::args().len() == 1;
8| 1|
9| 1| let mut a: u8 = 0;
10| 1| let mut b: u8 = 0;
11| 1| if is_true {
12| 1| a = 2;
13| 1| b = 0;
14| 1| }
^0
15| 1| match (a, b) {
16| | // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
17| | // This test confirms a fix for Issue #79569.
18| 0| (0 | 1, 2 | 3) => {}
19| 1| _ => {}
20| | }
21| 1| if is_true {
22| 1| a = 0;
23| 1| b = 0;
24| 1| }
^0
25| 1| match (a, b) {
26| 0| (0 | 1, 2 | 3) => {}
27| 1| _ => {}
28| | }
29| 1| if is_true {
30| 1| a = 2;
31| 1| b = 2;
32| 1| }
^0
33| 1| match (a, b) {
34| 0| (0 | 1, 2 | 3) => {}
35| 1| _ => {}
36| | }
37| 1| if is_true {
38| 1| a = 0;
39| 1| b = 2;
40| 1| }
^0
41| 1| match (a, b) {
42| 1| (0 | 1, 2 | 3) => {}
43| 0| _ => {}
44| | }
45| 1|}

View File

@ -28,11 +28,8 @@ Counter in file 0 79:14 -> 79:16, 0
Counter in file 0 81:1 -> 81:2, 0
Counter in file 0 91:25 -> 91:34, 0
Counter in file 0 5:1 -> 5:25, #1
Counter in file 0 5:25 -> 6:14, #1
Counter in file 0 7:9 -> 7:10, #2
Counter in file 0 9:9 -> 9:10, (#1 - #2)
Counter in file 0 11:1 -> 11:2, (#2 + (#1 - #2))
Counter in file 0 21:1 -> 21:23, #1
Counter in file 0 17:20 -> 17:21, #1
Counter in file 0 67:5 -> 67:23, #1
Counter in file 0 38:1 -> 38:19, #1
Counter in file 0 38:19 -> 42:12, #1
@ -46,14 +43,18 @@ Counter in file 0 44:27 -> 44:32, #8
Counter in file 0 44:36 -> 44:38, (#6 + 0)
Counter in file 0 45:14 -> 45:16, #7
Counter in file 0 47:1 -> 47:2, (#5 + (#6 + #7))
Counter in file 0 13:20 -> 13:21, #1
Counter in file 0 29:1 -> 29:22, #1
Counter in file 0 93:1 -> 101:2, #1
Counter in file 0 91:1 -> 91:25, #1
Counter in file 0 5:25 -> 6:14, #1
Counter in file 0 7:9 -> 7:10, #2
Counter in file 0 9:9 -> 9:10, (#1 - #2)
Counter in file 0 11:1 -> 11:2, (#2 + (#1 - #2))
Counter in file 0 51:5 -> 52:18, #1
Counter in file 0 53:13 -> 53:14, #2
Counter in file 0 63:13 -> 63:14, (#1 - #2)
Counter in file 0 65:5 -> 65:6, (#2 + (#1 - #2))
Counter in file 0 17:20 -> 17:21, #1
Counter in file 0 49:1 -> 68:12, #1
Counter in file 0 69:9 -> 69:10, #2
Counter in file 0 69:14 -> 69:27, (#1 + 0)
@ -70,7 +71,6 @@ Counter in file 0 87:14 -> 87:16, #3
Counter in file 0 89:1 -> 89:2, (#3 + (#2 + (#1 - (#3 + #2))))
Counter in file 0 17:1 -> 17:20, #1
Counter in file 0 66:5 -> 66:23, #1
Counter in file 0 13:20 -> 13:21, #1
Counter in file 0 17:9 -> 17:10, #1
Counter in file 0 17:9 -> 17:10, #1
Counter in file 0 117:17 -> 117:19, #1

View File

@ -0,0 +1,98 @@
Counter in file 0 3:1 -> 11:15, #1
Counter in file 0 11:16 -> 14:6, #2
Counter in file 0 14:6 -> 14:7, (#1 - #2)
Counter in file 0 15:11 -> 15:17, (#2 + (#1 - #2))
Counter in file 0 18:27 -> 18:29, #5
Counter in file 0 19:14 -> 19:16, (#3 + #4)
Counter in file 0 21:8 -> 21:15, ((#3 + #4) + #5)
Counter in file 0 21:16 -> 24:6, #6
Counter in file 0 24:6 -> 24:7, (((#3 + #4) + #5) - #6)
Counter in file 0 25:11 -> 25:17, (#6 + (((#3 + #4) + #5) - #6))
Counter in file 0 26:27 -> 26:29, #9
Counter in file 0 27:14 -> 27:16, (#7 + #8)
Counter in file 0 29:8 -> 29:15, ((#7 + #8) + #9)
Counter in file 0 29:16 -> 32:6, #10
Counter in file 0 32:6 -> 32:7, (((#7 + #8) + #9) - #10)
Counter in file 0 33:11 -> 33:17, (#10 + (((#7 + #8) + #9) - #10))
Counter in file 0 34:27 -> 34:29, #13
Counter in file 0 35:14 -> 35:16, (#11 + #12)
Counter in file 0 37:8 -> 37:15, ((#11 + #12) + #13)
Counter in file 0 37:16 -> 40:6, #14
Counter in file 0 40:6 -> 40:7, (((#11 + #12) + #13) - #14)
Counter in file 0 41:11 -> 41:17, (#14 + (((#11 + #12) + #13) - #14))
Counter in file 0 42:27 -> 42:29, #17
Counter in file 0 43:14 -> 43:16, (#15 + #16)
Counter in file 0 45:1 -> 45:2, ((#15 + #16) + #17)
Emitting segments for file: ../coverage/match_or_pattern.rs
Combined regions:
3:1 -> 11:15 (count=1)
11:16 -> 14:6 (count=1)
14:6 -> 14:7 (count=0)
15:11 -> 15:17 (count=1)
18:27 -> 18:29 (count=0)
19:14 -> 19:16 (count=1)
21:8 -> 21:15 (count=1)
21:16 -> 24:6 (count=1)
24:6 -> 24:7 (count=0)
25:11 -> 25:17 (count=1)
26:27 -> 26:29 (count=0)
27:14 -> 27:16 (count=1)
29:8 -> 29:15 (count=1)
29:16 -> 32:6 (count=1)
32:6 -> 32:7 (count=0)
33:11 -> 33:17 (count=1)
34:27 -> 34:29 (count=0)
35:14 -> 35:16 (count=1)
37:8 -> 37:15 (count=1)
37:16 -> 40:6 (count=1)
40:6 -> 40:7 (count=0)
41:11 -> 41:17 (count=1)
42:27 -> 42:29 (count=1)
43:14 -> 43:16 (count=0)
45:1 -> 45:2 (count=1)
Segment at 3:1 (count = 1), RegionEntry
Segment at 11:15 (count = 0), Skipped
Segment at 11:16 (count = 1), RegionEntry
Segment at 14:6 (count = 0), RegionEntry
Segment at 14:7 (count = 0), Skipped
Segment at 15:11 (count = 1), RegionEntry
Segment at 15:17 (count = 0), Skipped
Segment at 18:27 (count = 0), RegionEntry
Segment at 18:29 (count = 0), Skipped
Segment at 19:14 (count = 1), RegionEntry
Segment at 19:16 (count = 0), Skipped
Segment at 21:8 (count = 1), RegionEntry
Segment at 21:15 (count = 0), Skipped
Segment at 21:16 (count = 1), RegionEntry
Segment at 24:6 (count = 0), RegionEntry
Segment at 24:7 (count = 0), Skipped
Segment at 25:11 (count = 1), RegionEntry
Segment at 25:17 (count = 0), Skipped
Segment at 26:27 (count = 0), RegionEntry
Segment at 26:29 (count = 0), Skipped
Segment at 27:14 (count = 1), RegionEntry
Segment at 27:16 (count = 0), Skipped
Segment at 29:8 (count = 1), RegionEntry
Segment at 29:15 (count = 0), Skipped
Segment at 29:16 (count = 1), RegionEntry
Segment at 32:6 (count = 0), RegionEntry
Segment at 32:7 (count = 0), Skipped
Segment at 33:11 (count = 1), RegionEntry
Segment at 33:17 (count = 0), Skipped
Segment at 34:27 (count = 0), RegionEntry
Segment at 34:29 (count = 0), Skipped
Segment at 35:14 (count = 1), RegionEntry
Segment at 35:16 (count = 0), Skipped
Segment at 37:8 (count = 1), RegionEntry
Segment at 37:15 (count = 0), Skipped
Segment at 37:16 (count = 1), RegionEntry
Segment at 40:6 (count = 0), RegionEntry
Segment at 40:7 (count = 0), Skipped
Segment at 41:11 (count = 1), RegionEntry
Segment at 41:17 (count = 0), Skipped
Segment at 42:27 (count = 1), RegionEntry
Segment at 42:29 (count = 0), Skipped
Segment at 43:14 (count = 0), RegionEntry
Segment at 43:16 (count = 0), Skipped
Segment at 45:1 (count = 1), RegionEntry
Segment at 45:2 (count = 0), Skipped

View File

@ -0,0 +1,271 @@
<!DOCTYPE html>
<!--
Preview this file as rendered HTML from the github source at:
https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html
For revisions in Pull Requests (PR):
* Replace "rust-lang" with the github PR author
* Replace "master" with the PR branch name
-->
<html>
<head>
<title>match_or_pattern.main - Coverage Spans</title>
<style>
.line {
counter-increment: line;
}
.line:before {
content: counter(line) ": ";
font-family: Menlo, Monaco, monospace;
font-style: italic;
width: 3.8em;
display: inline-block;
text-align: right;
filter: opacity(50%);
-webkit-user-select: none;
}
.code {
color: #dddddd;
background-color: #222222;
font-family: Menlo, Monaco, monospace;
line-height: 1.4em;
border-bottom: 2px solid #222222;
white-space: pre;
display: inline-block;
}
.odd {
background-color: #55bbff;
color: #223311;
}
.even {
background-color: #ee7756;
color: #551133;
}
.code {
--index: calc(var(--layer) - 1);
padding-top: calc(var(--index) * 0.15em);
filter:
hue-rotate(calc(var(--index) * 25deg))
saturate(calc(100% - (var(--index) * 2%)))
brightness(calc(100% - (var(--index) * 1.5%)));
}
.annotation {
color: #4444ff;
font-family: monospace;
font-style: italic;
display: none;
-webkit-user-select: none;
}
body:active .annotation {
/* requires holding mouse down anywhere on the page */
display: inline-block;
}
span:hover .annotation {
/* requires hover over a span ONLY on its first line */
display: inline-block;
}
</style>
</head>
<body>
<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
7:19-7:35: @1[0]: _3 = &amp;_4
7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
7:9-7:16: @2[3]: FakeRead(ForLet, _1)
9:21-9:22: @3[2]: _5 = const 0_u8
9:9-9:14: @3[3]: FakeRead(ForLet, _5)
9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] })
10:21-10:22: @3[6]: _6 = const 0_u8
10:9-10:14: @3[7]: FakeRead(ForLet, _6)
10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
11:8-11:15: @3[11]: _8 = _1
11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
7:19-7:35: @1[0]: _3 = &amp;_4
7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
7:9-7:16: @2[3]: FakeRead(ForLet, _1)
9:21-9:22: @3[2]: _5 = const 0_u8
9:9-9:14: @3[3]: FakeRead(ForLet, _5)
9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] })
10:21-10:22: @3[6]: _6 = const 0_u8
10:9-10:14: @3[7]: FakeRead(ForLet, _6)
10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
11:8-11:15: @3[11]: _8 = _1
11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
7:19-7:35: @1[0]: _3 = &amp;_4
7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
7:9-7:16: @2[3]: FakeRead(ForLet, _1)
9:21-9:22: @3[2]: _5 = const 0_u8
9:9-9:14: @3[3]: FakeRead(ForLet, _5)
9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] })
10:21-10:22: @3[6]: _6 = const 0_u8
10:9-10:14: @3[7]: FakeRead(ForLet, _6)
10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
11:8-11:15: @3[11]: _8 = _1
11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
7:19-7:35: @1[0]: _3 = &amp;_4
7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
7:9-7:16: @2[3]: FakeRead(ForLet, _1)
9:21-9:22: @3[2]: _5 = const 0_u8
9:9-9:14: @3[3]: FakeRead(ForLet, _5)
9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] })
10:21-10:22: @3[6]: _6 = const 0_u8
10:9-10:14: @3[7]: FakeRead(ForLet, _6)
10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
11:8-11:15: @3[11]: _8 = _1
11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> // dependent conditions.</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
7:19-7:35: @1[0]: _3 = &amp;_4
7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
7:9-7:16: @2[3]: FakeRead(ForLet, _1)
9:21-9:22: @3[2]: _5 = const 0_u8
9:9-9:14: @3[3]: FakeRead(ForLet, _5)
9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] })
10:21-10:22: @3[6]: _6 = const 0_u8
10:9-10:14: @3[7]: FakeRead(ForLet, _6)
10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
11:8-11:15: @3[11]: _8 = _1
11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> let is_true = std::env::args().len() == 1;</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
7:19-7:35: @1[0]: _3 = &amp;_4
7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
7:9-7:16: @2[3]: FakeRead(ForLet, _1)
9:21-9:22: @3[2]: _5 = const 0_u8
9:9-9:14: @3[3]: FakeRead(ForLet, _5)
9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] })
10:21-10:22: @3[6]: _6 = const 0_u8
10:9-10:14: @3[7]: FakeRead(ForLet, _6)
10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
11:8-11:15: @3[11]: _8 = _1
11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"></span></span>
<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
7:19-7:35: @1[0]: _3 = &amp;_4
7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
7:9-7:16: @2[3]: FakeRead(ForLet, _1)
9:21-9:22: @3[2]: _5 = const 0_u8
9:9-9:14: @3[3]: FakeRead(ForLet, _5)
9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] })
10:21-10:22: @3[6]: _6 = const 0_u8
10:9-10:14: @3[7]: FakeRead(ForLet, _6)
10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
11:8-11:15: @3[11]: _8 = _1
11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> let mut a: u8 = 0;</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
7:19-7:35: @1[0]: _3 = &amp;_4
7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
7:9-7:16: @2[3]: FakeRead(ForLet, _1)
9:21-9:22: @3[2]: _5 = const 0_u8
9:9-9:14: @3[3]: FakeRead(ForLet, _5)
9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] })
10:21-10:22: @3[6]: _6 = const 0_u8
10:9-10:14: @3[7]: FakeRead(ForLet, _6)
10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
11:8-11:15: @3[11]: _8 = _1
11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> let mut b: u8 = 0;</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -&gt; [return: bb1, unwind: bb41]
7:19-7:35: @1[0]: _3 = &amp;_4
7:19-7:41: @1.Call: _2 = &lt;Args as ExactSizeIterator&gt;::len(move _3) -&gt; [return: bb2, unwind: bb40]
7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize)
7:9-7:16: @2[3]: FakeRead(ForLet, _1)
9:21-9:22: @3[2]: _5 = const 0_u8
9:9-9:14: @3[3]: FakeRead(ForLet, _5)
9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] })
10:21-10:22: @3[6]: _6 = const 0_u8
10:9-10:14: @3[7]: FakeRead(ForLet, _6)
10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] })
11:8-11:15: @3[11]: _8 = _1
11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8
13:9-13:14: @6[1]: _6 = const 0_u8
11:16-14:6: @6[2]: _7 = const ()"><span class="annotation">@4,6⦊</span>{</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8
13:9-13:14: @6[1]: _6 = const 0_u8
11:16-14:6: @6[2]: _7 = const ()"> a = 2;</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8
13:9-13:14: @6[1]: _6 = const 0_u8
11:16-14:6: @6[2]: _7 = const ()"> b = 0;</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8
13:9-13:14: @6[1]: _6 = const 0_u8
11:16-14:6: @6[2]: _7 = const ()"> }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="14:6-14:6: @5[0]: _7 = const ()"><span class="annotation">@5⦊</span><span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> match </span><span><span class="code odd" style="--layer: 1" title="15:12-15:13: @7[5]: _11 = _5
15:15-15:16: @7[7]: _12 = _6
15:11-15:17: @7[8]: _10 = (move _11, move _12)
15:11-15:17: @7[11]: FakeRead(ForMatchedPlace, _10)"><span class="annotation">@7⦊</span>(a, b)<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> {</span></span>
<span class="line"><span class="code" style="--layer: 0"> // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.</span></span>
<span class="line"><span class="code" style="--layer: 0"> // This test confirms a fix for Issue #79569.</span></span>
<span class="line"><span class="code" style="--layer: 0"> (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="18:27-18:29: @11[0]: _9 = const ()"><span class="annotation">@10,11⦊</span>{}<span class="annotation">⦉@10,11</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="19:14-19:16: @8[0]: _9 = const ()"><span class="annotation">@8⦊</span>{}<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> }</span></span>
<span class="line"><span class="code" style="--layer: 0"> if </span><span><span class="code even" style="--layer: 1" title="21:8-21:15: @12[4]: _14 = _1
21:8-21:15: @12[5]: FakeRead(ForMatchedPlace, _14)"><span class="annotation">@12⦊</span>is_true<span class="annotation">⦉@12</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8
23:9-23:14: @15[1]: _6 = const 0_u8
21:16-24:6: @15[2]: _13 = const ()"><span class="annotation">@13,15⦊</span>{</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8
23:9-23:14: @15[1]: _6 = const 0_u8
21:16-24:6: @15[2]: _13 = const ()"> a = 0;</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8
23:9-23:14: @15[1]: _6 = const 0_u8
21:16-24:6: @15[2]: _13 = const ()"> b = 0;</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8
23:9-23:14: @15[1]: _6 = const 0_u8
21:16-24:6: @15[2]: _13 = const ()"> }<span class="annotation">⦉@13,15</span></span></span><span><span class="code even" style="--layer: 1" title="24:6-24:6: @14[0]: _13 = const ()"><span class="annotation">@14⦊</span><span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> match </span><span><span class="code odd" style="--layer: 1" title="25:12-25:13: @16[5]: _17 = _5
25:15-25:16: @16[7]: _18 = _6
25:11-25:17: @16[8]: _16 = (move _17, move _18)
25:11-25:17: @16[11]: FakeRead(ForMatchedPlace, _16)"><span class="annotation">@16⦊</span>(a, b)<span class="annotation">⦉@16</span></span></span><span class="code" style="--layer: 0"> {</span></span>
<span class="line"><span class="code" style="--layer: 0"> (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="26:27-26:29: @20[0]: _15 = const ()"><span class="annotation">@19,20⦊</span>{}<span class="annotation">⦉@19,20</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="27:14-27:16: @17[0]: _15 = const ()"><span class="annotation">@17⦊</span>{}<span class="annotation">⦉@17</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> }</span></span>
<span class="line"><span class="code" style="--layer: 0"> if </span><span><span class="code even" style="--layer: 1" title="29:8-29:15: @21[4]: _20 = _1
29:8-29:15: @21[5]: FakeRead(ForMatchedPlace, _20)"><span class="annotation">@21⦊</span>is_true<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8
31:9-31:14: @24[1]: _6 = const 2_u8
29:16-32:6: @24[2]: _19 = const ()"><span class="annotation">@22,24⦊</span>{</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8
31:9-31:14: @24[1]: _6 = const 2_u8
29:16-32:6: @24[2]: _19 = const ()"> a = 2;</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8
31:9-31:14: @24[1]: _6 = const 2_u8
29:16-32:6: @24[2]: _19 = const ()"> b = 2;</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8
31:9-31:14: @24[1]: _6 = const 2_u8
29:16-32:6: @24[2]: _19 = const ()"> }<span class="annotation">⦉@22,24</span></span></span><span><span class="code even" style="--layer: 1" title="32:6-32:6: @23[0]: _19 = const ()"><span class="annotation">@23⦊</span><span class="annotation">⦉@23</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> match </span><span><span class="code odd" style="--layer: 1" title="33:12-33:13: @25[5]: _23 = _5
33:15-33:16: @25[7]: _24 = _6
33:11-33:17: @25[8]: _22 = (move _23, move _24)
33:11-33:17: @25[11]: FakeRead(ForMatchedPlace, _22)"><span class="annotation">@25⦊</span>(a, b)<span class="annotation">⦉@25</span></span></span><span class="code" style="--layer: 0"> {</span></span>
<span class="line"><span class="code" style="--layer: 0"> (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="34:27-34:29: @29[0]: _21 = const ()"><span class="annotation">@28,29⦊</span>{}<span class="annotation">⦉@28,29</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="35:14-35:16: @26[0]: _21 = const ()"><span class="annotation">@26⦊</span>{}<span class="annotation">⦉@26</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> }</span></span>
<span class="line"><span class="code" style="--layer: 0"> if </span><span><span class="code even" style="--layer: 1" title="37:8-37:15: @30[4]: _26 = _1
37:8-37:15: @30[5]: FakeRead(ForMatchedPlace, _26)"><span class="annotation">@30⦊</span>is_true<span class="annotation">⦉@30</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8
39:9-39:14: @33[1]: _6 = const 2_u8
37:16-40:6: @33[2]: _25 = const ()"><span class="annotation">@31,33⦊</span>{</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8
39:9-39:14: @33[1]: _6 = const 2_u8
37:16-40:6: @33[2]: _25 = const ()"> a = 0;</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8
39:9-39:14: @33[1]: _6 = const 2_u8
37:16-40:6: @33[2]: _25 = const ()"> b = 2;</span></span>
<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8
39:9-39:14: @33[1]: _6 = const 2_u8
37:16-40:6: @33[2]: _25 = const ()"> }<span class="annotation">⦉@31,33</span></span></span><span><span class="code even" style="--layer: 1" title="40:6-40:6: @32[0]: _25 = const ()"><span class="annotation">@32⦊</span><span class="annotation">⦉@32</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> match </span><span><span class="code odd" style="--layer: 1" title="41:12-41:13: @34[4]: _28 = _5
41:15-41:16: @34[6]: _29 = _6
41:11-41:17: @34[7]: _27 = (move _28, move _29)
41:11-41:17: @34[10]: FakeRead(ForMatchedPlace, _27)"><span class="annotation">@34⦊</span>(a, b)<span class="annotation">⦉@34</span></span></span><span class="code" style="--layer: 0"> {</span></span>
<span class="line"><span class="code" style="--layer: 0"> (0 | 1, 2 | 3) =&gt; </span><span><span class="code even" style="--layer: 1" title="42:27-42:29: @38[0]: _0 = const ()"><span class="annotation">@37,38⦊</span>{}<span class="annotation">⦉@37,38</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> _ =&gt; </span><span><span class="code odd" style="--layer: 1" title="43:14-43:16: @35[0]: _0 = const ()"><span class="annotation">@35⦊</span>{}<span class="annotation">⦉@35</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> }</span></span>
<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="45:2-45:2: @39.Return: return"><span class="annotation">@39⦊</span><span class="annotation">⦉@39</span></span></span></span></div>
</body>
</html>

View File

@ -0,0 +1,45 @@
#![feature(or_patterns)]
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) => {}
_ => {}
}
}

View File

@ -41,7 +41,7 @@ fn arg_value<'a, T: Deref<Target = str>>(
match arg.next().or_else(|| args.next()) {
Some(v) if pred(v) => return Some(v),
_ => {},
_ => {}
}
}
None
@ -121,11 +121,12 @@ You can use tool lints to allow or deny lints from your code, eg.:
const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new";
static ICE_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> = SyncLazy::new(|| {
let hook = panic::take_hook();
panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL)));
hook
});
static ICE_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
SyncLazy::new(|| {
let hook = panic::take_hook();
panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL)));
hook
});
fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
// Invoke our ICE handler, which prints the actual panic message and optionally a backtrace
@ -257,14 +258,17 @@ pub fn main() {
// Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
// We're invoking the compiler programmatically, so we ignore this/
let wrapper_mode = orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref());
let wrapper_mode =
orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref());
if wrapper_mode {
// we still want to be able to invoke it normally though
orig_args.remove(1);
}
if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) {
if !wrapper_mode
&& (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1)
{
display_help();
exit(0);
}
@ -285,13 +289,11 @@ pub fn main() {
if clippy_enabled {
args.extend(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()]);
if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| {
if s.is_empty() {
None
} else {
Some(s.to_string())
}
}));
args.extend(
extra_args
.split("__CLIPPY_HACKERY__")
.filter_map(|s| if s.is_empty() { None } else { Some(s.to_string()) }),
);
}
}
let mut clippy = ClippyCallbacks;

View File

@ -214,12 +214,12 @@ fn check_exceptions(metadata: &Metadata, bad: &mut bool) {
for (name, license) in EXCEPTIONS {
// Check that the package actually exists.
if !metadata.packages.iter().any(|p| p.name == *name) {
println!(
tidy_error!(
bad,
"could not find exception package `{}`\n\
Remove from EXCEPTIONS list if it is no longer used.",
name
);
*bad = true;
}
// Check that the license hasn't changed.
for pkg in metadata.packages.iter().filter(|p| p.name == *name) {
@ -232,11 +232,11 @@ fn check_exceptions(metadata: &Metadata, bad: &mut bool) {
}
match &pkg.license {
None => {
println!(
tidy_error!(
bad,
"dependency exception `{}` does not declare a license expression",
pkg.id
);
*bad = true;
}
Some(pkg_license) => {
if pkg_license.as_str() != *license {
@ -273,8 +273,7 @@ fn check_exceptions(metadata: &Metadata, bad: &mut bool) {
let license = match &pkg.license {
Some(license) => license,
None => {
println!("dependency `{}` does not define a license expression", pkg.id,);
*bad = true;
tidy_error!(bad, "dependency `{}` does not define a license expression", pkg.id);
continue;
}
};
@ -286,8 +285,7 @@ fn check_exceptions(metadata: &Metadata, bad: &mut bool) {
// general, these should never be added.
continue;
}
println!("invalid license `{}` in `{}`", license, pkg.id);
*bad = true;
tidy_error!(bad, "invalid license `{}` in `{}`", license, pkg.id);
}
}
}
@ -300,12 +298,12 @@ fn check_dependencies(metadata: &Metadata, bad: &mut bool) {
// Check that the PERMITTED_DEPENDENCIES does not have unused entries.
for name in PERMITTED_DEPENDENCIES {
if !metadata.packages.iter().any(|p| p.name == *name) {
println!(
tidy_error!(
bad,
"could not find allowed package `{}`\n\
Remove from PERMITTED_DEPENDENCIES list if it is no longer used.",
name
);
*bad = true;
}
}
// Get the list in a convenient form.
@ -322,11 +320,10 @@ fn check_dependencies(metadata: &Metadata, bad: &mut bool) {
}
if !unapproved.is_empty() {
println!("Dependencies not explicitly permitted:");
tidy_error!(bad, "Dependencies not explicitly permitted:");
for dep in unapproved {
println!("* {}", dep);
}
*bad = true;
}
}
@ -381,16 +378,17 @@ fn check_crate_duplicate(metadata: &Metadata, bad: &mut bool) {
let matches: Vec<_> = metadata.packages.iter().filter(|pkg| pkg.name == name).collect();
match matches.len() {
0 => {
println!(
tidy_error!(
bad,
"crate `{}` is missing, update `check_crate_duplicate` \
if it is no longer used",
name
);
*bad = true;
}
1 => {}
_ => {
println!(
tidy_error!(
bad,
"crate `{}` is duplicated in `Cargo.lock`, \
it is too expensive to build multiple times, \
so make sure only one version appears across all dependencies",
@ -399,7 +397,6 @@ fn check_crate_duplicate(metadata: &Metadata, bad: &mut bool) {
for pkg in matches {
println!(" * {}", pkg.id);
}
*bad = true;
}
}
}

View File

@ -27,8 +27,7 @@ pub fn check(root: &Path, bad: &mut bool) {
// Ensure source is allowed.
if !ALLOWED_SOURCES.contains(&&*source) {
println!("invalid source: {}", source);
*bad = true;
tidy_error!(bad, "invalid source: {}", source);
}
}
}

View File

@ -330,7 +330,6 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features
let issue_str = parts.next().unwrap().trim();
let tracking_issue = if issue_str.starts_with("None") {
if level == Status::Unstable && !next_feature_omits_tracking_issue {
*bad = true;
tidy_error!(
bad,
"{}:{}: no tracking issue for feature {}",

View File

@ -28,6 +28,10 @@ macro_rules! t {
}
macro_rules! tidy_error {
($bad:expr, $fmt:expr) => ({
*$bad = true;
eprintln!("tidy error: {}", $fmt);
});
($bad:expr, $fmt:expr, $($arg:tt)*) => ({
*$bad = true;
eprint!("tidy error: ");

View File

@ -67,14 +67,12 @@ pub fn check(path: &Path, bad: &mut bool) {
let testname =
file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0;
if !file_path.with_file_name(testname).with_extension("rs").exists() {
println!("Stray file with UI testing output: {:?}", file_path);
*bad = true;
tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
}
if let Ok(metadata) = fs::metadata(file_path) {
if metadata.len() == 0 {
println!("Empty file with UI testing output: {:?}", file_path);
*bad = true;
tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
}
}
}