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 rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt};
use std::fmt::Debug;
use std::iter;
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
/// This method is meant to be invoked as the final step of a canonical query
@ -418,7 +419,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
// In terms of our example above, we are iterating over pairs like:
// [(?A, Vec<?0>), ('static, '?1), (?B, ?0)]
for (original_value, result_value) in original_values.var_values.iter().zip(result_values) {
for (original_value, result_value) in iter::zip(&original_values.var_values, result_values)
{
match result_value.unpack() {
GenericArgKind::Type(result_value) => {
// e.g., here `result_value` might be `?0` in the example above...

View file

@ -73,7 +73,7 @@ use rustc_middle::ty::{
use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
use std::ops::ControlFlow;
use std::{cmp, fmt};
use std::{cmp, fmt, iter};
mod note;
@ -963,7 +963,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id),
_ => None,
});
for (def_id, actual) in default_params.zip(substs.iter().rev()) {
for (def_id, actual) in iter::zip(default_params, substs.iter().rev()) {
match actual.unpack() {
GenericArgKind::Const(c) => {
if self.tcx.const_param_default(def_id).subst(self.tcx, substs) != c {
@ -1040,7 +1040,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let len1 = sig1.inputs().len();
let len2 = sig2.inputs().len();
if len1 == len2 {
for (i, (l, r)) in sig1.inputs().iter().zip(sig2.inputs().iter()).enumerate() {
for (i, (l, r)) in iter::zip(sig1.inputs(), sig2.inputs()).enumerate() {
let (x1, x2) = self.cmp(l, r);
(values.0).0.extend(x1.0);
(values.1).0.extend(x2.0);
@ -1161,12 +1161,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let common_len = cmp::min(len1, len2);
let remainder1: Vec<_> = sub1.types().skip(common_len).collect();
let remainder2: Vec<_> = sub2.types().skip(common_len).collect();
let common_default_params = remainder1
.iter()
.rev()
.zip(remainder2.iter().rev())
.filter(|(a, b)| a == b)
.count();
let common_default_params =
iter::zip(remainder1.iter().rev(), remainder2.iter().rev())
.filter(|(a, b)| a == b)
.count();
let len = sub1.len() - common_default_params;
let consts_offset = len - sub1.consts().count();
@ -1297,12 +1295,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
const SEPARATOR: &str = "::";
let separator_len = SEPARATOR.len();
let split_idx: usize = t1_str
.split(SEPARATOR)
.zip(t2_str.split(SEPARATOR))
.take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str)
.map(|(mod_str, _)| mod_str.len() + separator_len)
.sum();
let split_idx: usize =
iter::zip(t1_str.split(SEPARATOR), t2_str.split(SEPARATOR))
.take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str)
.map(|(mod_str, _)| mod_str.len() + separator_len)
.sum();
debug!(
"cmp: separator_len={}, split_idx={}, min_len={}",
@ -1907,7 +1904,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.find_map(|(path, msg)| (&path_str == path).then_some(msg))
{
let mut show_suggestion = true;
for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) {
for (exp_ty, found_ty) in
iter::zip(exp_substs.types(), found_substs.types())
{
match *exp_ty.kind() {
ty::Ref(_, exp_ty, _) => {
match (exp_ty.kind(), found_ty.kind()) {

View file

@ -19,6 +19,7 @@
#![feature(const_fn)]
#![feature(const_panic)]
#![feature(extend_one)]
#![feature(iter_zip)]
#![feature(never_type)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(in_band_lifetimes)]

View file

@ -9,6 +9,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::Symbol;
use rustc_span::{MultiSpan, Span};
use std::fmt;
use std::iter;
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn report_extra_impl_obligation(
@ -94,7 +95,7 @@ pub fn report_object_safety_error(
note_span
.push_span_label(trait_span, "this trait cannot be made into an object...".to_string());
}
for (span, msg) in multi_span.into_iter().zip(messages.into_iter()) {
for (span, msg) in iter::zip(multi_span, messages) {
note_span.push_span_label(span, msg);
}
err.span_note(