From a0b464ade8c728cbe7f4a05ecdc00f62be064142 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Sat, 23 Apr 2022 07:39:11 +0300 Subject: [PATCH 1/7] Add a couple tests for #90887 fixes --- .../normalize-under-binder/issue-56556.rs | 17 ++++++++++ .../normalize-under-binder/issue-90875.rs | 31 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs index 768d1c36619da..4d38cb19e9bf2 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs @@ -11,3 +11,20 @@ where fn main() { foo::>(vec![]); } + +mod another { + use std::ops::Deref; + + fn test() + where + T: Deref, + TDeref: ?Sized, + for<'a> &'a TDeref: IntoIterator, + for<'a> <&'a TDeref as IntoIterator>::IntoIter: Clone, + { + } + + fn main() { + test::, _>(); + } +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs new file mode 100644 index 0000000000000..ffd6857d84a6e --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs @@ -0,0 +1,31 @@ +// check-pass + +trait Variable<'a> { + type Type; +} + +impl Variable<'_> for () { + type Type = (); +} + +fn check(_: F) +where + F: Fn(T), // <- if removed, all fn_* then require type annotations + F: for<'a> Fn(>::Type), + T: for<'a> Variable<'a>, +{ +} + +fn test(arg: impl Fn(())) { + fn fn_1(_: ()) {} + let fn_2 = |_: ()| (); + let fn_3 = |a| fn_1(a); + let fn_4 = arg; + + check(fn_1); // Error + check(fn_2); // Ok + check(fn_3); // Ok + check(fn_4); // Error +} + +fn main() {} From 0c92519d01b30996594cc16832fc52f0702a4855 Mon Sep 17 00:00:00 2001 From: Chris Martin Date: Mon, 9 May 2022 12:04:53 -0400 Subject: [PATCH 2/7] Make HashMap fall back to RtlGenRandom if BCryptGenRandom fails Issue #84096 changed the hashmap RNG to use BCryptGenRandom instead of RtlGenRandom on Windows. Mozilla Firefox started experiencing random failures in env_logger::Builder::new() (Issue #94098) during initialization of their unsandboxed main process with an "Access Denied" error message from BCryptGenRandom(), which is used by the HashMap contained in env_logger::Builder The root cause appears to be a virus scanner or other software interfering with BCrypt DLLs loading. This change adds a fallback option if BCryptGenRandom is unusable for whatever reason. It will fallback to RtlGenRandom in this case. Fixes #94098 --- library/std/src/sys/windows/c.rs | 4 ++ library/std/src/sys/windows/rand.rs | 83 +++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 0692da1d79519..0bb6fee60c92e 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -788,6 +788,10 @@ if #[cfg(not(target_vendor = "uwp"))] { #[link(name = "advapi32")] extern "system" { + // Forbidden when targeting UWP + #[link_name = "SystemFunction036"] + pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; + // Allowed but unused by UWP pub fn OpenProcessToken( ProcessHandle: HANDLE, diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs index de73e9154b45e..ec6c40d2f4978 100644 --- a/library/std/src/sys/windows/rand.rs +++ b/library/std/src/sys/windows/rand.rs @@ -1,8 +1,69 @@ use crate::io; use crate::mem; +use crate::sync; use crate::sys::c; +// The kinds of HashMap RNG that may be available +#[derive(Clone, Copy, Debug, PartialEq)] +enum HashMapRng { + Preferred, + Fallback, +} + pub fn hashmap_random_keys() -> (u64, u64) { + match get_hashmap_rng() { + HashMapRng::Preferred => { + preferred_rng().expect("couldn't generate random bytes with preferred RNG") + } + HashMapRng::Fallback => { + fallback_rng().unwrap().expect("couldn't generate random bytes with fallback RNG") + } + } +} + +// Returns the HashMap RNG that should be used +// +// Panics if they are both broken +fn get_hashmap_rng() -> HashMapRng { + // Assume that if the preferred RNG is broken the first time we use it, it likely means + // that: the DLL has failed to load, there is no point to calling it over-and-over again, + // and we should cache the result + static INIT: sync::Once = sync::Once::new(); + static mut HASHMAP_RNG: HashMapRng = HashMapRng::Preferred; + + unsafe { + INIT.call_once(|| HASHMAP_RNG = choose_hashmap_rng()); + HASHMAP_RNG + } +} + +// Test whether we should use the preferred or fallback RNG +// +// If the preferred RNG is successful, we choose it. Otherwise, if the fallback RNG is successful, +// we choose that +// +// Panics if both the preferred and the fallback RNG are both non-functional +fn choose_hashmap_rng() -> HashMapRng { + let preferred_error = match preferred_rng() { + Ok(_) => return HashMapRng::Preferred, + Err(e) => e, + }; + + // On UWP, there is no fallback + let fallback_result = fallback_rng() + .unwrap_or_else(|| panic!("preferred RNG broken: `{}`, no fallback", preferred_error)); + + match fallback_result { + Ok(_) => return HashMapRng::Fallback, + Err(fallback_error) => panic!( + "preferred RNG broken: `{}`, fallback RNG broken: `{}`", + preferred_error, fallback_error + ), + } +} + +// Generate random numbers using the preferred RNG function (BCryptGenRandom) +fn preferred_rng() -> Result<(u64, u64), io::Error> { use crate::ptr; let mut v = (0, 0); @@ -14,8 +75,22 @@ pub fn hashmap_random_keys() -> (u64, u64) { c::BCRYPT_USE_SYSTEM_PREFERRED_RNG, ) }; - if ret != 0 { - panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); - } - return v; + + if ret == 0 { Ok(v) } else { Err(io::Error::last_os_error()) } +} + +// Generate random numbers using the fallback RNG function (RtlGenRandom) +#[cfg(not(target_vendor = "uwp"))] +fn fallback_rng() -> Option> { + let mut v = (0, 0); + let ret = + unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) }; + + Some(if ret != 0 { Ok(v) } else { Err(io::Error::last_os_error()) }) +} + +// We can't use RtlGenRandom with UWP, so there is no fallback +#[cfg(target_vendor = "uwp")] +fn fallback_rng() -> Option> { + None } From 3de6c2ca33f45b283ebb177bb29c0c756c6b75cb Mon Sep 17 00:00:00 2001 From: Chris Martin Date: Fri, 13 May 2022 18:14:03 -0400 Subject: [PATCH 3/7] Address review feedback --- library/std/src/sys/windows/rand.rs | 53 ++++++++++++----------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs index ec6c40d2f4978..836fc14898600 100644 --- a/library/std/src/sys/windows/rand.rs +++ b/library/std/src/sys/windows/rand.rs @@ -1,9 +1,9 @@ use crate::io; +use crate::lazy; use crate::mem; -use crate::sync; use crate::sys::c; -// The kinds of HashMap RNG that may be available +/// The kinds of HashMap RNG that may be available #[derive(Clone, Copy, Debug, PartialEq)] enum HashMapRng { Preferred, @@ -16,44 +16,35 @@ pub fn hashmap_random_keys() -> (u64, u64) { preferred_rng().expect("couldn't generate random bytes with preferred RNG") } HashMapRng::Fallback => { - fallback_rng().unwrap().expect("couldn't generate random bytes with fallback RNG") + fallback_rng().expect("couldn't generate random bytes with fallback RNG") } } } -// Returns the HashMap RNG that should be used -// -// Panics if they are both broken +/// Returns the HashMap RNG that should be used +/// +/// Panics if they are both broken fn get_hashmap_rng() -> HashMapRng { // Assume that if the preferred RNG is broken the first time we use it, it likely means // that: the DLL has failed to load, there is no point to calling it over-and-over again, // and we should cache the result - static INIT: sync::Once = sync::Once::new(); - static mut HASHMAP_RNG: HashMapRng = HashMapRng::Preferred; - - unsafe { - INIT.call_once(|| HASHMAP_RNG = choose_hashmap_rng()); - HASHMAP_RNG - } + static VALUE: lazy::SyncOnceCell = lazy::SyncOnceCell::new(); + *VALUE.get_or_init(choose_hashmap_rng) } -// Test whether we should use the preferred or fallback RNG -// -// If the preferred RNG is successful, we choose it. Otherwise, if the fallback RNG is successful, -// we choose that -// -// Panics if both the preferred and the fallback RNG are both non-functional +/// Test whether we should use the preferred or fallback RNG +/// +/// If the preferred RNG is successful, we choose it. Otherwise, if the fallback RNG is successful, +/// we choose that +/// +/// Panics if both the preferred and the fallback RNG are both non-functional fn choose_hashmap_rng() -> HashMapRng { let preferred_error = match preferred_rng() { Ok(_) => return HashMapRng::Preferred, Err(e) => e, }; - // On UWP, there is no fallback - let fallback_result = fallback_rng() - .unwrap_or_else(|| panic!("preferred RNG broken: `{}`, no fallback", preferred_error)); - - match fallback_result { + match fallback_rng() { Ok(_) => return HashMapRng::Fallback, Err(fallback_error) => panic!( "preferred RNG broken: `{}`, fallback RNG broken: `{}`", @@ -62,7 +53,7 @@ fn choose_hashmap_rng() -> HashMapRng { } } -// Generate random numbers using the preferred RNG function (BCryptGenRandom) +/// Generate random numbers using the preferred RNG function (BCryptGenRandom) fn preferred_rng() -> Result<(u64, u64), io::Error> { use crate::ptr; @@ -79,18 +70,18 @@ fn preferred_rng() -> Result<(u64, u64), io::Error> { if ret == 0 { Ok(v) } else { Err(io::Error::last_os_error()) } } -// Generate random numbers using the fallback RNG function (RtlGenRandom) +/// Generate random numbers using the fallback RNG function (RtlGenRandom) #[cfg(not(target_vendor = "uwp"))] -fn fallback_rng() -> Option> { +fn fallback_rng() -> Result<(u64, u64), io::Error> { let mut v = (0, 0); let ret = unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) }; - Some(if ret != 0 { Ok(v) } else { Err(io::Error::last_os_error()) }) + if ret != 0 { Ok(v) } else { Err(io::Error::last_os_error()) } } -// We can't use RtlGenRandom with UWP, so there is no fallback +/// We can't use RtlGenRandom with UWP, so there is no fallback #[cfg(target_vendor = "uwp")] -fn fallback_rng() -> Option> { - None +fn fallback_rng() -> Result<(u64, u64), io::Error> { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "unsupported on UWP")) } From a3bc2e5293840fd23a5237bda6f3bdf1fefbbe4f Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 16 May 2022 19:34:30 +0900 Subject: [PATCH 4/7] Add regression test for #81804 --- src/test/ui/parser/issue-81804.rs | 9 ++++++ src/test/ui/parser/issue-81804.stderr | 41 +++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 src/test/ui/parser/issue-81804.rs create mode 100644 src/test/ui/parser/issue-81804.stderr diff --git a/src/test/ui/parser/issue-81804.rs b/src/test/ui/parser/issue-81804.rs new file mode 100644 index 0000000000000..803bde11e20d1 --- /dev/null +++ b/src/test/ui/parser/issue-81804.rs @@ -0,0 +1,9 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected pattern, found `=` +// error-pattern: expected one of `)`, `,`, `->`, `where`, or `{`, found `]` +// error-pattern: expected item, found `]` + +fn main() {} + +fn p([=(} diff --git a/src/test/ui/parser/issue-81804.stderr b/src/test/ui/parser/issue-81804.stderr new file mode 100644 index 0000000000000..19c4422c6221c --- /dev/null +++ b/src/test/ui/parser/issue-81804.stderr @@ -0,0 +1,41 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-81804.rs:9:11 + | +LL | fn p([=(} + | -- ^ + | || + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-81804.rs:9:11 + | +LL | fn p([=(} + | -- ^ + | || + | |unclosed delimiter + | unclosed delimiter + +error: expected pattern, found `=` + --> $DIR/issue-81804.rs:9:7 + | +LL | fn p([=(} + | ^ expected pattern + +error: expected one of `)`, `,`, `->`, `where`, or `{`, found `]` + --> $DIR/issue-81804.rs:9:8 + | +LL | fn p([=(} + | ^ -^ + | | | + | | help: `)` may belong here + | unclosed delimiter + +error: expected item, found `]` + --> $DIR/issue-81804.rs:9:11 + | +LL | fn p([=(} + | ^ expected item + +error: aborting due to 5 previous errors + From 0ea7301fa34719f1dd26b8e0dfaeeab73c67599a Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 16 May 2022 15:41:05 +0200 Subject: [PATCH 5/7] remove the `RelateResultCompare` trait --- compiler/rustc_infer/src/infer/combine.rs | 15 --------------- compiler/rustc_infer/src/infer/nll_relate/mod.rs | 2 +- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index aa3f0600cccc8..534106ac446cf 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -776,21 +776,6 @@ pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> { fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>); } -pub trait RelateResultCompare<'tcx, T> { - fn compare(&self, t: T, f: F) -> RelateResult<'tcx, T> - where - F: FnOnce() -> TypeError<'tcx>; -} - -impl<'tcx, T: Clone + PartialEq> RelateResultCompare<'tcx, T> for RelateResult<'tcx, T> { - fn compare(&self, t: T, f: F) -> RelateResult<'tcx, T> - where - F: FnOnce() -> TypeError<'tcx>, - { - self.clone().and_then(|s| if s == t { self.clone() } else { Err(f()) }) - } -} - pub fn const_unification_error<'tcx>( a_is_expected: bool, (a, b): (ty::Const<'tcx>, ty::Const<'tcx>), diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 94a795f613e9d..6592e0ae8ec8f 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -859,7 +859,7 @@ where delegate: &'me mut D, - /// After we generalize this type, we are going to relative it to + /// After we generalize this type, we are going to relate it to /// some other type. What will be the variance at this point? ambient_variance: ty::Variance, From aba3454aa136bce4f65978e5bf50683380fbddf3 Mon Sep 17 00:00:00 2001 From: Chris Martin Date: Mon, 16 May 2022 13:49:12 -0400 Subject: [PATCH 6/7] Improve error message for fallback RNG failure --- library/std/src/sys/windows/rand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs index 836fc14898600..22e024d8552ec 100644 --- a/library/std/src/sys/windows/rand.rs +++ b/library/std/src/sys/windows/rand.rs @@ -83,5 +83,5 @@ fn fallback_rng() -> Result<(u64, u64), io::Error> { /// We can't use RtlGenRandom with UWP, so there is no fallback #[cfg(target_vendor = "uwp")] fn fallback_rng() -> Result<(u64, u64), io::Error> { - Err(io::const_io_error!(io::ErrorKind::Unsupported, "unsupported on UWP")) + Err(io::const_io_error!(io::ErrorKind::Unsupported, "RtlGenRandom() not supported on UWP")) } From 38bf1158bd850c80de42599c28602ae11727a133 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Tue, 17 May 2022 08:41:01 +0800 Subject: [PATCH 7/7] Change `Successors` to `impl Iterator` --- compiler/rustc_borrowck/src/dataflow.rs | 2 +- .../src/diagnostics/explain_borrow.rs | 4 +- .../src/diagnostics/find_use.rs | 4 +- compiler/rustc_borrowck/src/nll.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 2 +- .../rustc_middle/src/mir/generic_graph.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 9 ++-- compiler/rustc_middle/src/mir/patch.rs | 4 +- compiler/rustc_middle/src/mir/predecessors.rs | 2 +- compiler/rustc_middle/src/mir/terminator.rs | 50 ++++++++++--------- compiler/rustc_middle/src/mir/traversal.rs | 2 +- .../src/framework/graphviz.rs | 2 +- .../rustc_mir_transform/src/coverage/debug.rs | 2 +- .../rustc_mir_transform/src/coverage/graph.rs | 8 +-- compiler/rustc_mir_transform/src/inline.rs | 2 +- .../src/remove_noop_landing_pads.rs | 2 +- compiler/rustc_mir_transform/src/simplify.rs | 6 +-- .../clippy_lints/src/redundant_clone.rs | 4 +- 18 files changed, 54 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index d38e89cd79edd..5252b0b50c308 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -199,7 +199,7 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> { // Add successor BBs to the work list, if necessary. let bb_data = &self.body[bb]; debug_assert!(hi == bb_data.statements.len()); - for &succ_bb in bb_data.terminator().successors() { + for succ_bb in bb_data.terminator().successors() { if !self.visited.insert(succ_bb) { if succ_bb == location.block && first_lo > 0 { // `succ_bb` has been seen before. If it wasn't diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index ffea15bdc33eb..6ec6b76bb5f85 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -467,7 +467,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { block .terminator() .successors() - .map(|bb| Location { statement_index: 0, block: *bb }) + .map(|bb| Location { statement_index: 0, block: bb }) .filter(|s| visited_locations.insert(*s)) .map(|s| { if self.is_back_edge(location, s) { @@ -526,7 +526,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } else { for bb in block.terminator().successors() { - let successor = Location { statement_index: 0, block: *bb }; + let successor = Location { statement_index: 0, block: bb }; if !visited_locations.contains(&successor) && self.find_loop_head_dfs(successor, loop_head, visited_locations) diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index ab4536f00fc42..22e7cd9e52c9f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -67,8 +67,8 @@ impl<'cx, 'tcx> UseFinder<'cx, 'tcx> { block_data .terminator() .successors() - .filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind()) - .map(|&bb| Location { statement_index: 0, block: bb }), + .filter(|&bb| Some(&Some(bb)) != block_data.terminator().unwind()) + .map(|bb| Location { statement_index: 0, block: bb }), ); } } diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 927eb080b2008..6f8fae2de29a7 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -108,7 +108,7 @@ fn populate_polonius_move_facts( // We are at the terminator of an init that has a panic path, // and where the init should not happen on panic - for &successor in block_data.terminator().successors() { + for successor in block_data.terminator().successors() { if body[successor].is_cleanup { continue; } diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index fa39e8dd247d5..80dab115fac46 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -328,7 +328,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Grap let terminator = body[source].terminator(); let labels = terminator.kind.fmt_successor_labels(); - for (&target, label) in terminator.successors().zip(labels) { + for (target, label) in terminator.successors().zip(labels) { let src = node(def_id, source); let trg = node(def_id, target); edges.push(Edge::new(src, trg, label.to_string())); diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index af18adac2ff79..7a80afa72320b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1355,10 +1355,7 @@ pub enum InlineAsmOperand<'tcx> { /// Type for MIR `Assert` terminator error messages. pub type AssertMessage<'tcx> = AssertKind>; -// FIXME: Change `Successors` to `impl Iterator`. -#[allow(rustc::pass_by_value)] -pub type Successors<'a> = - iter::Chain, slice::Iter<'a, BasicBlock>>; +pub type Successors<'a> = impl Iterator + 'a; pub type SuccessorsMut<'a> = iter::Chain, slice::IterMut<'a, BasicBlock>>; @@ -3434,13 +3431,13 @@ impl<'tcx> graph::WithStartNode for Body<'tcx> { impl<'tcx> graph::WithSuccessors for Body<'tcx> { #[inline] fn successors(&self, node: Self::Node) -> >::Iter { - self.basic_blocks[node].terminator().successors().cloned() + self.basic_blocks[node].terminator().successors() } } impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> { type Item = BasicBlock; - type Iter = iter::Cloned>; + type Iter = Successors<'b>; } impl<'tcx, 'graph> graph::GraphPredecessors<'graph> for Body<'tcx> { diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index d03f9235efd58..3bcb8f9c34c9a 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -166,9 +166,7 @@ impl<'tcx> MirPatch<'tcx> { // get terminator's targets and apply the statement to all of them. if loc.statement_index > body[loc.block].statements.len() { let term = body[loc.block].terminator(); - let successors = term.successors().clone(); - - for i in successors { + for i in term.successors() { stmts_and_targets .push((Statement { source_info, kind: stmt.clone() }, i.clone())); } diff --git a/compiler/rustc_middle/src/mir/predecessors.rs b/compiler/rustc_middle/src/mir/predecessors.rs index 4fe2cde753290..ad09328585d27 100644 --- a/compiler/rustc_middle/src/mir/predecessors.rs +++ b/compiler/rustc_middle/src/mir/predecessors.rs @@ -43,7 +43,7 @@ impl PredecessorCache { let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks); for (bb, data) in basic_blocks.iter_enumerated() { if let Some(term) = &data.terminator { - for &succ in term.successors() { + for succ in term.successors() { preds[succ].push(bb); } } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index e6eb63fd3b2b8..fb3856b4952a0 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -416,32 +416,36 @@ impl<'tcx> TerminatorKind<'tcx> { | Return | Unreachable | Call { destination: None, cleanup: None, .. } - | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&[]), - Goto { target: ref t } - | Call { destination: None, cleanup: Some(ref t), .. } - | Call { destination: Some((_, ref t)), cleanup: None, .. } - | Yield { resume: ref t, drop: None, .. } - | DropAndReplace { target: ref t, unwind: None, .. } - | Drop { target: ref t, unwind: None, .. } - | Assert { target: ref t, cleanup: None, .. } - | FalseUnwind { real_target: ref t, unwind: None } - | InlineAsm { destination: Some(ref t), cleanup: None, .. } - | InlineAsm { destination: None, cleanup: Some(ref t), .. } => { - Some(t).into_iter().chain(&[]) + | InlineAsm { destination: None, cleanup: None, .. } => { + None.into_iter().chain((&[]).into_iter().copied()) } - Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } - | Yield { resume: ref t, drop: Some(ref u), .. } - | DropAndReplace { target: ref t, unwind: Some(ref u), .. } - | Drop { target: ref t, unwind: Some(ref u), .. } - | Assert { target: ref t, cleanup: Some(ref u), .. } - | FalseUnwind { real_target: ref t, unwind: Some(ref u) } - | InlineAsm { destination: Some(ref t), cleanup: Some(ref u), .. } => { - Some(t).into_iter().chain(slice::from_ref(u)) + Goto { target: t } + | Call { destination: None, cleanup: Some(t), .. } + | Call { destination: Some((_, t)), cleanup: None, .. } + | Yield { resume: t, drop: None, .. } + | DropAndReplace { target: t, unwind: None, .. } + | Drop { target: t, unwind: None, .. } + | Assert { target: t, cleanup: None, .. } + | FalseUnwind { real_target: t, unwind: None } + | InlineAsm { destination: Some(t), cleanup: None, .. } + | InlineAsm { destination: None, cleanup: Some(t), .. } => { + Some(t).into_iter().chain((&[]).into_iter().copied()) } - SwitchInt { ref targets, .. } => None.into_iter().chain(&targets.targets), - FalseEdge { ref real_target, ref imaginary_target } => { - Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)) + Call { destination: Some((_, t)), cleanup: Some(ref u), .. } + | Yield { resume: t, drop: Some(ref u), .. } + | DropAndReplace { target: t, unwind: Some(ref u), .. } + | Drop { target: t, unwind: Some(ref u), .. } + | Assert { target: t, cleanup: Some(ref u), .. } + | FalseUnwind { real_target: t, unwind: Some(ref u) } + | InlineAsm { destination: Some(t), cleanup: Some(ref u), .. } => { + Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied()) } + SwitchInt { ref targets, .. } => { + None.into_iter().chain(targets.targets.iter().copied()) + } + FalseEdge { real_target, ref imaginary_target } => Some(real_target) + .into_iter() + .chain(slice::from_ref(imaginary_target).into_iter().copied()), } } diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 8d831cc73b8a4..1cbfed621560d 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -180,7 +180,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { // two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A] loop { let bb = if let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() { - if let Some(&bb) = iter.next() { + if let Some(bb) = iter.next() { bb } else { break; diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 599b4087c78e4..c6a85bc43f458 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -125,7 +125,7 @@ where } fn target(&self, edge: &Self::Edge) -> Self::Node { - self.body[edge.source].terminator().successors().nth(edge.index).copied().unwrap() + self.body[edge.source].terminator().successors().nth(edge.index).unwrap() } } diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index 8e28ed2426bbb..434bf9d849e5a 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -701,7 +701,7 @@ pub(super) fn dump_coverage_graphviz<'tcx>( edge_labels.retain(|label| label != "unreachable"); let edge_counters = from_terminator .successors() - .map(|&successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb)); + .map(|successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb)); iter::zip(&edge_labels, edge_counters) .map(|(label, some_counter)| { if let Some(counter) = some_counter { diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 6bb7e676e851c..47190fa0d1ad9 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -484,17 +484,17 @@ fn bcb_filtered_successors<'a, 'tcx>( body: &'tcx &'a mir::Body<'tcx>, term_kind: &'tcx TerminatorKind<'tcx>, ) -> Box + 'a> { - let mut successors = term_kind.successors(); Box::new( match &term_kind { // SwitchInt successors are never unwind, and all of them should be traversed. - TerminatorKind::SwitchInt { .. } => successors, + TerminatorKind::SwitchInt { ref targets, .. } => { + None.into_iter().chain(targets.all_targets().into_iter().copied()) + } // For all other kinds, return only the first successor, if any, and ignore unwinds. // NOTE: `chain(&[])` is required to coerce the `option::iter` (from // `next().into_iter()`) into the `mir::Successors` aliased type. - _ => successors.next().into_iter().chain(&[]), + _ => term_kind.successors().next().into_iter().chain((&[]).into_iter().copied()), } - .copied() .filter(move |&successor| body[successor].terminator().kind != TerminatorKind::Unreachable), ) } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 012ce73075575..1b58fab57d5af 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -450,7 +450,7 @@ impl<'tcx> Inliner<'tcx> { } if !is_drop { - for &succ in term.successors() { + for succ in term.successors() { work_list.push(succ); } } diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 4d214b0356ca7..f925d13b2fb91 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -65,7 +65,7 @@ impl RemoveNoopLandingPads { | TerminatorKind::SwitchInt { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => { - terminator.successors().all(|&succ| nop_landing_pads.contains(succ)) + terminator.successors().all(|succ| nop_landing_pads.contains(succ)) } TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index b42e3909cf386..72e0834392576 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -81,7 +81,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { for (_, data) in traversal::preorder(body) { if let Some(ref term) = data.terminator { - for &tgt in term.successors() { + for tgt in term.successors() { pred_count[tgt] += 1; } } @@ -235,8 +235,8 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { }; let first_succ = { - if let Some(&first_succ) = terminator.successors().next() { - if terminator.successors().all(|s| *s == first_succ) { + if let Some(first_succ) = terminator.successors().next() { + if terminator.successors().all(|s| s == first_succ) { let count = terminator.successors().count(); self.pred_count[first_succ] -= (count - 1) as u32; first_succ diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index 1507c75ff6123..37aac8b2a4978 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { } // Give up on loops - if terminator.successors().any(|s| *s == bb) { + if terminator.successors().any(|s| s == bb) { continue; } @@ -440,7 +440,7 @@ fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>, // Short-circuit if (usage.cloned_used && usage.clone_consumed_or_mutated) || // Give up on loops - tdata.terminator().successors().any(|s| *s == bb) + tdata.terminator().successors().any(|s| s == bb) { return CloneUsage { cloned_used: true,