1
Fork 0

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:
Dylan DPC 2021-03-27 20:37:07 +01:00 committed by GitHub
commit b2e254318d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
111 changed files with 310 additions and 256 deletions

View file

@ -27,6 +27,7 @@ use crate::ty::{self, BoundVar, List, Region, TyCtxt};
use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
use smallvec::SmallVec;
use std::iter;
use std::ops::Index;
/// A "canonicalized" type `V` is one where all free inference
@ -315,10 +316,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
use crate::ty::subst::GenericArgKind;
CanonicalVarValues {
var_values: self
.var_values
.iter()
.zip(0..)
var_values: iter::zip(&self.var_values, 0..)
.map(|(kind, i)| match kind.unpack() {
GenericArgKind::Type(..) => {
tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()

View file

@ -51,6 +51,7 @@
#![feature(exclusive_range_pattern)]
#![feature(control_flow_enum)]
#![feature(associated_type_defaults)]
#![feature(iter_zip)]
#![recursion_limit = "512"]
#[macro_use]

View file

@ -2329,7 +2329,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
CtorKind::Fn => fmt_tuple(fmt, &name),
CtorKind::Fictive => {
let mut struct_fmt = fmt.debug_struct(&name);
for (field, place) in variant_def.fields.iter().zip(places) {
for (field, place) in iter::zip(&variant_def.fields, places) {
struct_fmt.field(&field.ident.as_str(), place);
}
struct_fmt.finish()
@ -2353,7 +2353,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
let mut struct_fmt = fmt.debug_struct(&name);
if let Some(upvars) = tcx.upvars_mentioned(def_id) {
for (&var_id, place) in upvars.keys().zip(places) {
for (&var_id, place) in iter::zip(upvars.keys(), places) {
let var_name = tcx.hir().name(var_id);
struct_fmt.field(&var_name.as_str(), place);
}
@ -2372,7 +2372,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
let mut struct_fmt = fmt.debug_struct(&name);
if let Some(upvars) = tcx.upvars_mentioned(def_id) {
for (&var_id, place) in upvars.keys().zip(places) {
for (&var_id, place) in iter::zip(upvars.keys(), places) {
let var_name = tcx.hir().name(var_id);
struct_fmt.field(&var_name.as_str(), place);
}

View file

@ -67,7 +67,7 @@ impl SwitchTargets {
///
/// Note that this may yield 0 elements. Only the `otherwise` branch is mandatory.
pub fn iter(&self) -> SwitchTargetsIter<'_> {
SwitchTargetsIter { inner: self.values.iter().zip(self.targets.iter()) }
SwitchTargetsIter { inner: iter::zip(&self.values, &self.targets) }
}
/// Returns a slice with all possible jump targets (including the fallback target).

View file

@ -789,7 +789,7 @@ impl CanonicalUserType<'tcx> {
return false;
}
user_substs.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| {
iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
match kind.unpack() {
GenericArgKind::Type(ty) => match ty.kind() {
ty::Bound(debruijn, b) => {

View file

@ -1251,13 +1251,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
} else {
// Try to use a ScalarPair for all tagged enums.
let mut common_prim = None;
for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) {
for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) {
let offsets = match layout_variant.fields {
FieldsShape::Arbitrary { ref offsets, .. } => offsets,
_ => bug!(),
};
let mut fields =
field_layouts.iter().zip(offsets).filter(|p| !p.0.is_zst());
iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
let (field, offset) = match (fields.next(), fields.next()) {
(None, None) => continue,
(Some(pair), None) => pair,
@ -1626,7 +1626,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
const INVALID_FIELD_IDX: u32 = !0;
let mut combined_inverse_memory_index =
vec![INVALID_FIELD_IDX; promoted_memory_index.len() + memory_index.len()];
let mut offsets_and_memory_index = offsets.into_iter().zip(memory_index);
let mut offsets_and_memory_index = iter::zip(offsets, memory_index);
let combined_offsets = variant_fields
.iter()
.enumerate()

View file

@ -19,6 +19,7 @@ use std::char;
use std::collections::BTreeMap;
use std::convert::TryFrom;
use std::fmt::{self, Write as _};
use std::iter;
use std::ops::{ControlFlow, Deref, DerefMut};
// `pretty` is a separate module only for organization.
@ -1223,7 +1224,7 @@ pub trait PrettyPrinter<'tcx>:
CtorKind::Fictive => {
p!(" {{ ");
let mut first = true;
for (field_def, field) in variant_def.fields.iter().zip(fields) {
for (field_def, field) in iter::zip(&variant_def.fields, fields) {
if !first {
p!(", ");
}

View file

@ -140,7 +140,7 @@ pub fn relate_substs<R: TypeRelation<'tcx>>(
) -> RelateResult<'tcx, SubstsRef<'tcx>> {
let tcx = relation.tcx();
let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| {
let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
let variance = variances.map_or(ty::Invariant, |v| v[i]);
relation.relate_with_variance(variance, a, b)
});
@ -170,12 +170,8 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
return Err(TypeError::ArgCount);
}
let inputs_and_output = a
.inputs()
.iter()
.cloned()
.zip(b.inputs().iter().cloned())
.map(|x| (x, false))
let inputs_and_output = iter::zip(a.inputs(), b.inputs())
.map(|(&a, &b)| ((a, b), false))
.chain(iter::once(((a.output(), b.output()), true)))
.map(|((a, b), is_output)| {
if is_output {
@ -299,7 +295,7 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
) -> RelateResult<'tcx, GeneratorWitness<'tcx>> {
assert_eq!(a.0.len(), b.0.len());
let tcx = relation.tcx();
let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?;
let types = tcx.mk_type_list(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?;
Ok(GeneratorWitness(types))
}
}
@ -440,7 +436,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
(&ty::Tuple(as_), &ty::Tuple(bs)) => {
if as_.len() == bs.len() {
Ok(tcx.mk_tup(
as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())),
iter::zip(as_, bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())),
)?)
} else if !(as_.is_empty() || bs.is_empty()) {
Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len())))
@ -584,9 +580,7 @@ fn check_const_value_eq<R: TypeRelation<'tcx>>(
// Both the variant and each field have to be equal.
if a_destructured.variant == b_destructured.variant {
for (a_field, b_field) in
a_destructured.fields.iter().zip(b_destructured.fields.iter())
{
for (a_field, b_field) in iter::zip(a_destructured.fields, b_destructured.fields) {
relation.consts(a_field, b_field)?;
}
@ -622,7 +616,7 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'
return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
}
let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| {
let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
use crate::ty::ExistentialPredicate::*;
match (ep_a.skip_binder(), ep_b.skip_binder()) {
(Trait(a), Trait(b)) => Ok(ty::Binder::bind(Trait(

View file

@ -21,7 +21,7 @@ use rustc_macros::HashStable;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{Integer, Size, TargetDataLayout};
use smallvec::SmallVec;
use std::{cmp, fmt};
use std::{cmp, fmt, iter};
#[derive(Copy, Clone, Debug)]
pub struct Discr<'tcx> {
@ -414,9 +414,7 @@ impl<'tcx> TyCtxt<'tcx> {
_ => bug!(),
};
let result = item_substs
.iter()
.zip(impl_substs.iter())
let result = iter::zip(item_substs, impl_substs)
.filter(|&(_, k)| {
match k.unpack() {
GenericArgKind::Lifetime(&ty::RegionKind::ReEarlyBound(ref ebr)) => {