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
|
@ -15,6 +15,7 @@
|
|||
#![feature(box_patterns)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(iter_zip)]
|
||||
#![feature(never_type)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![cfg_attr(bootstrap, feature(or_patterns))]
|
||||
|
|
|
@ -12,6 +12,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
|||
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::VecDeque;
|
||||
use std::iter;
|
||||
|
||||
// FIXME(twk): this is obviously not nice to duplicate like that
|
||||
#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
|
||||
|
@ -428,7 +429,9 @@ impl AutoTraitFinder<'tcx> {
|
|||
return true;
|
||||
}
|
||||
|
||||
for (new_region, old_region) in new_substs.regions().zip(old_substs.regions()) {
|
||||
for (new_region, old_region) in
|
||||
iter::zip(new_substs.regions(), old_substs.regions())
|
||||
{
|
||||
match (new_region, old_region) {
|
||||
// If both predicates have an `ReLateBound` (a HRTB) in the
|
||||
// same spot, we do nothing.
|
||||
|
|
|
@ -74,23 +74,22 @@ where
|
|||
let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
|
||||
|
||||
// Check if any of the input types definitely do not unify.
|
||||
if impl1_ref
|
||||
.iter()
|
||||
.flat_map(|tref| tref.substs.types())
|
||||
.zip(impl2_ref.iter().flat_map(|tref| tref.substs.types()))
|
||||
.any(|(ty1, ty2)| {
|
||||
let t1 = fast_reject::simplify_type(tcx, ty1, false);
|
||||
let t2 = fast_reject::simplify_type(tcx, ty2, false);
|
||||
if let (Some(t1), Some(t2)) = (t1, t2) {
|
||||
// Simplified successfully
|
||||
// Types cannot unify if they differ in their reference mutability or simplify to different types
|
||||
t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability()
|
||||
} else {
|
||||
// Types might unify
|
||||
false
|
||||
}
|
||||
})
|
||||
{
|
||||
if iter::zip(
|
||||
impl1_ref.iter().flat_map(|tref| tref.substs.types()),
|
||||
impl2_ref.iter().flat_map(|tref| tref.substs.types()),
|
||||
)
|
||||
.any(|(ty1, ty2)| {
|
||||
let t1 = fast_reject::simplify_type(tcx, ty1, false);
|
||||
let t2 = fast_reject::simplify_type(tcx, ty2, false);
|
||||
if let (Some(t1), Some(t2)) = (t1, t2) {
|
||||
// Simplified successfully
|
||||
// Types cannot unify if they differ in their reference mutability or simplify to different types
|
||||
t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability()
|
||||
} else {
|
||||
// Types might unify
|
||||
false
|
||||
}
|
||||
}) {
|
||||
// Some types involved are definitely different, so the impls couldn't possibly overlap.
|
||||
debug!("overlapping_impls: fast_reject early-exit");
|
||||
return no_overlap();
|
||||
|
|
|
@ -23,6 +23,7 @@ use rustc_span::def_id::{DefId, LocalDefId};
|
|||
use rustc_span::Span;
|
||||
|
||||
use std::cmp;
|
||||
use std::iter;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
/// Check if a given constant can be evaluated.
|
||||
|
@ -672,9 +673,7 @@ pub(super) fn try_unify<'tcx>(
|
|||
if a_args.len() == b_args.len() =>
|
||||
{
|
||||
try_unify(tcx, a.subtree(a_f), b.subtree(b_f))
|
||||
&& a_args
|
||||
.iter()
|
||||
.zip(b_args)
|
||||
&& iter::zip(a_args, b_args)
|
||||
.all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn)))
|
||||
}
|
||||
_ => false,
|
||||
|
|
|
@ -28,6 +28,7 @@ use rustc_session::DiagnosticMessageId;
|
|||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP};
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
use crate::traits::query::normalize::AtExt as _;
|
||||
|
@ -161,7 +162,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
for (error, suppressed) in errors.iter().zip(is_suppressed) {
|
||||
for (error, suppressed) in iter::zip(errors, is_suppressed) {
|
||||
if !suppressed {
|
||||
self.report_fulfillment_error(error, body_id, fallback_has_occurred);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_middle::ty::subst::Subst;
|
||||
use rustc_middle::ty::{self, GenericParamDefKind};
|
||||
use rustc_span::symbol::sym;
|
||||
use std::iter;
|
||||
|
||||
use super::InferCtxtPrivExt;
|
||||
|
||||
|
@ -51,12 +52,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
|
||||
self_match_impls.push(def_id);
|
||||
|
||||
if trait_ref
|
||||
.substs
|
||||
.types()
|
||||
.skip(1)
|
||||
.zip(impl_trait_ref.substs.types().skip(1))
|
||||
.all(|(u, v)| self.fuzzy_match_tys(u, v))
|
||||
if iter::zip(
|
||||
trait_ref.substs.types().skip(1),
|
||||
impl_trait_ref.substs.types().skip(1),
|
||||
)
|
||||
.all(|(u, v)| self.fuzzy_match_tys(u, v))
|
||||
{
|
||||
fuzzy_match_impls.push(def_id);
|
||||
}
|
||||
|
|
|
@ -1887,7 +1887,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// substitution if we find that any of the input types, when
|
||||
// simplified, do not match.
|
||||
|
||||
obligation.predicate.skip_binder().trait_ref.substs.iter().zip(impl_trait_ref.substs).any(
|
||||
iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs).any(
|
||||
|(obligation_arg, impl_arg)| {
|
||||
match (obligation_arg.unpack(), impl_arg.unpack()) {
|
||||
(GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => {
|
||||
|
|
|
@ -692,11 +692,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
let predicates = predicates.instantiate(self.infcx.tcx, substs);
|
||||
debug_assert_eq!(predicates.predicates.len(), origins.len());
|
||||
|
||||
predicates
|
||||
.predicates
|
||||
.into_iter()
|
||||
.zip(predicates.spans.into_iter())
|
||||
.zip(origins.into_iter().rev())
|
||||
iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev())
|
||||
.map(|((pred, span), origin_def_id)| {
|
||||
let cause = self.cause(traits::BindingObligation(origin_def_id, span));
|
||||
traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue