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
|
@ -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()
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#![feature(exclusive_range_pattern)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(iter_zip)]
|
||||
#![recursion_limit = "512"]
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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!(", ");
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue