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:
@@ -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...
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
Reference in New Issue
Block a user