Rollup merge of #82917 - cuviper:iter-zip, r=m-ou-se
Add function core::iter::zip This makes it a little easier to `zip` iterators: ```rust for (x, y) in zip(xs, ys) {} // vs. for (x, y) in xs.into_iter().zip(ys) {} ``` You can `zip(&mut xs, &ys)` for the conventional `iter_mut()` and `iter()`, respectively. This can also support arbitrary nesting, where it's easier to see the item layout than with arbitrary `zip` chains: ```rust for ((x, y), z) in zip(zip(xs, ys), zs) {} for (x, (y, z)) in zip(xs, zip(ys, zs)) {} // vs. for ((x, y), z) in xs.into_iter().zip(ys).zip(xz) {} for (x, (y, z)) in xs.into_iter().zip((ys.into_iter().zip(xz)) {} ``` It may also format more nicely, especially when the first iterator is a longer chain of methods -- for example: ```rust iter::zip( trait_ref.substs.types().skip(1), impl_trait_ref.substs.types().skip(1), ) // vs. trait_ref .substs .types() .skip(1) .zip(impl_trait_ref.substs.types().skip(1)) ``` This replaces the tuple-pair `IntoIterator` in #78204. There is prior art for the utility of this in [`itertools::zip`]. [`itertools::zip`]: https://docs.rs/itertools/0.10.0/itertools/fn.zip.html
This commit is contained in:
commit
b2e254318d
111 changed files with 310 additions and 256 deletions
|
@ -18,6 +18,7 @@ use rustc_span::{
|
|||
Span,
|
||||
};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use std::iter;
|
||||
|
||||
use super::borrow_set::BorrowData;
|
||||
use super::MirBorrowckCtxt;
|
||||
|
@ -970,13 +971,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
|
||||
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
|
||||
if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr {
|
||||
for (captured_place, place) in self
|
||||
.infcx
|
||||
.tcx
|
||||
.typeck(def_id.expect_local())
|
||||
.closure_min_captures_flattened(def_id)
|
||||
.zip(places)
|
||||
{
|
||||
for (captured_place, place) in iter::zip(
|
||||
self.infcx.tcx.typeck(def_id.expect_local()).closure_min_captures_flattened(def_id),
|
||||
places,
|
||||
) {
|
||||
let upvar_hir_id = captured_place.get_root_variable();
|
||||
//FIXME(project-rfc-2229#8): Use better span from captured_place
|
||||
let span = self.infcx.tcx.upvars_mentioned(local_did)?[&upvar_hir_id].span;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::fmt::{self, Display};
|
||||
use std::iter;
|
||||
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_hir as hir;
|
||||
|
@ -536,7 +537,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
// just worry about trying to match up the rustc type
|
||||
// with the HIR types:
|
||||
(ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => {
|
||||
search_stack.extend(elem_tys.iter().map(|k| k.expect_ty()).zip(*elem_hir_tys));
|
||||
search_stack
|
||||
.extend(iter::zip(elem_tys.iter().map(|k| k.expect_ty()), *elem_hir_tys));
|
||||
}
|
||||
|
||||
(ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty))
|
||||
|
@ -611,7 +613,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
args: &'hir hir::GenericArgs<'hir>,
|
||||
search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
|
||||
) -> Option<&'hir hir::Lifetime> {
|
||||
for (kind, hir_arg) in substs.iter().zip(args.args) {
|
||||
for (kind, hir_arg) in iter::zip(substs, args.args) {
|
||||
match (kind.unpack(), hir_arg) {
|
||||
(GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => {
|
||||
if r.to_region_vid() == needle_fr {
|
||||
|
|
|
@ -5,6 +5,7 @@ use rustc_middle::mir::{BorrowKind, Mutability, Operand};
|
|||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||
use rustc_middle::mir::{Statement, StatementKind};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use std::iter;
|
||||
|
||||
use crate::dataflow::indexes::BorrowIndex;
|
||||
|
||||
|
@ -69,7 +70,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
self.mutate_place(location, **place, Shallow(None), JustWrite);
|
||||
}
|
||||
StatementKind::LlvmInlineAsm(asm) => {
|
||||
for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
|
||||
for (o, output) in iter::zip(&asm.asm.outputs, &*asm.outputs) {
|
||||
if o.is_indirect {
|
||||
// FIXME(eddyb) indirect inline asm outputs should
|
||||
// be encoded through MIR place derefs instead.
|
||||
|
|
|
@ -25,6 +25,7 @@ use either::Either;
|
|||
use smallvec::SmallVec;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -595,7 +596,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
|
|||
self.mutate_place(location, (**place, span), Shallow(None), JustWrite, flow_state);
|
||||
}
|
||||
StatementKind::LlvmInlineAsm(ref asm) => {
|
||||
for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
|
||||
for (o, output) in iter::zip(&asm.asm.outputs, &*asm.outputs) {
|
||||
if o.is_indirect {
|
||||
// FIXME(eddyb) indirect inline asm outputs should
|
||||
// be encoded through MIR place derefs instead.
|
||||
|
|
|
@ -5,6 +5,7 @@ use rustc_hir as hir;
|
|||
use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use std::cmp::max;
|
||||
use std::iter;
|
||||
|
||||
/// When checking if a place conflicts with another place, this enum is used to influence decisions
|
||||
/// where a place might be equal or disjoint with another place, such as if `a[i] == a[j]`.
|
||||
|
@ -139,7 +140,7 @@ fn place_components_conflict<'tcx>(
|
|||
|
||||
// loop invariant: borrow_c is always either equal to access_c or disjoint from it.
|
||||
for (i, (borrow_c, &access_c)) in
|
||||
borrow_place.projection.iter().zip(access_place.projection.iter()).enumerate()
|
||||
iter::zip(borrow_place.projection, access_place.projection).enumerate()
|
||||
{
|
||||
debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c);
|
||||
let borrow_proj_base = &borrow_place.projection[..i];
|
||||
|
|
|
@ -1770,7 +1770,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
|
||||
span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
|
||||
}
|
||||
for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() {
|
||||
for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
|
||||
let op_arg_ty = op_arg.ty(body, self.tcx());
|
||||
let op_arg_ty = self.normalize(op_arg_ty, term_location);
|
||||
let category = if from_hir_call {
|
||||
|
|
|
@ -580,7 +580,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
|
||||
let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
|
||||
let subst_mapping =
|
||||
identity_substs.regions().zip(fr_substs.regions().map(|r| r.to_region_vid()));
|
||||
iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.to_region_vid()));
|
||||
|
||||
UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect() }
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use std::iter;
|
||||
|
||||
/// A [partially ordered set][poset] that has a [least upper bound][lub] for any pair of elements
|
||||
/// in the set.
|
||||
|
@ -110,7 +111,7 @@ impl<I: Idx, T: JoinSemiLattice> JoinSemiLattice for IndexVec<I, T> {
|
|||
assert_eq!(self.len(), other.len());
|
||||
|
||||
let mut changed = false;
|
||||
for (a, b) in self.iter_mut().zip(other.iter()) {
|
||||
for (a, b) in iter::zip(self, other) {
|
||||
changed |= a.join(b);
|
||||
}
|
||||
changed
|
||||
|
@ -122,7 +123,7 @@ impl<I: Idx, T: MeetSemiLattice> MeetSemiLattice for IndexVec<I, T> {
|
|||
assert_eq!(self.len(), other.len());
|
||||
|
||||
let mut changed = false;
|
||||
for (a, b) in self.iter_mut().zip(other.iter()) {
|
||||
for (a, b) in iter::zip(self, other) {
|
||||
changed |= a.meet(b);
|
||||
}
|
||||
changed
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::borrow_check::{
|
|||
use crate::dataflow::{self, fmt::DebugWithContext, GenKill};
|
||||
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
pub struct BorrowIndex {
|
||||
|
@ -292,7 +293,7 @@ impl<'tcx> dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
|||
}
|
||||
|
||||
mir::StatementKind::LlvmInlineAsm(ref asm) => {
|
||||
for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
|
||||
for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) {
|
||||
if !kind.is_indirect && !kind.is_rw {
|
||||
self.kill_borrows_on_place(trans, *output);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use rustc_middle::mir::*;
|
|||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
|
||||
use super::abs_domain::Lift;
|
||||
|
@ -296,7 +297,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
|||
self.create_move_path(**place);
|
||||
}
|
||||
StatementKind::LlvmInlineAsm(ref asm) => {
|
||||
for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
|
||||
for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) {
|
||||
if !kind.is_indirect {
|
||||
self.gather_init(output.as_ref(), InitKind::Deep);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ Rust MIR: a lowered representation of Rust.
|
|||
#![feature(decl_macro)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(iter_zip)]
|
||||
#![feature(never_type)]
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(min_specialization)]
|
||||
|
|
|
@ -121,6 +121,7 @@ use rustc_middle::mir::coverage::*;
|
|||
use rustc_middle::mir::{self, BasicBlock, TerminatorKind};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
use std::iter;
|
||||
use std::lazy::SyncOnceCell;
|
||||
|
||||
pub const NESTED_INDENT: &str = " ";
|
||||
|
@ -703,9 +704,7 @@ pub(super) fn dump_coverage_graphviz(
|
|||
let edge_counters = from_terminator
|
||||
.successors()
|
||||
.map(|&successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb));
|
||||
edge_labels
|
||||
.iter()
|
||||
.zip(edge_counters)
|
||||
iter::zip(&edge_labels, edge_counters)
|
||||
.map(|(label, some_counter)| {
|
||||
if let Some(counter) = some_counter {
|
||||
format!("{}\n{}", label, debug_counters.format_counter(counter))
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! This pass finds basic blocks that are completely equal,
|
||||
//! and replaces all uses with just one of them.
|
||||
|
||||
use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher};
|
||||
use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher, iter};
|
||||
|
||||
use crate::transform::MirPass;
|
||||
|
||||
|
@ -115,11 +115,7 @@ impl<'tcx, 'a> PartialEq for BasicBlockHashable<'tcx, 'a> {
|
|||
fn eq(&self, other: &Self) -> bool {
|
||||
self.basic_block_data.statements.len() == other.basic_block_data.statements.len()
|
||||
&& &self.basic_block_data.terminator().kind == &other.basic_block_data.terminator().kind
|
||||
&& self
|
||||
.basic_block_data
|
||||
.statements
|
||||
.iter()
|
||||
.zip(&other.basic_block_data.statements)
|
||||
&& iter::zip(&self.basic_block_data.statements, &other.basic_block_data.statements)
|
||||
.all(|(x, y)| statement_eq(&x.kind, &y.kind))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::transform::MirPass;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use std::iter;
|
||||
|
||||
use super::simplify::simplify_cfg;
|
||||
|
||||
|
@ -83,7 +84,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
|
|||
if first_stmts.len() != scnd_stmts.len() {
|
||||
continue;
|
||||
}
|
||||
for (f, s) in first_stmts.iter().zip(scnd_stmts.iter()) {
|
||||
for (f, s) in iter::zip(first_stmts, scnd_stmts) {
|
||||
match (&f.kind, &s.kind) {
|
||||
// If two statements are exactly the same, we can optimize.
|
||||
(f_s, s_s) if f_s == s_s => {}
|
||||
|
@ -113,7 +114,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
|
|||
// and bb_idx has a different terminator from both of them.
|
||||
let (from, first, second) = bbs.pick3_mut(bb_idx, first, second);
|
||||
|
||||
let new_stmts = first.statements.iter().zip(second.statements.iter()).map(|(f, s)| {
|
||||
let new_stmts = iter::zip(&first.statements, &second.statements).map(|(f, s)| {
|
||||
match (&f.kind, &s.kind) {
|
||||
(f_s, s_s) if f_s == s_s => (*f).clone(),
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue