]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #82917 - cuviper:iter-zip, r=m-ou-se
authorDylan DPC <dylan.dpc@gmail.com>
Sat, 27 Mar 2021 19:37:07 +0000 (20:37 +0100)
committerGitHub <noreply@github.com>
Sat, 27 Mar 2021 19:37:07 +0000 (20:37 +0100)
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

13 files changed:
clippy_lints/src/default_numeric_fallback.rs
clippy_lints/src/lib.rs
clippy_lints/src/literal_representation.rs
clippy_lints/src/loops/needless_range_loop.rs
clippy_lints/src/matches.rs
clippy_lints/src/mut_key.rs
clippy_lints/src/mut_reference.rs
clippy_lints/src/pass_by_ref_or_value.rs
clippy_lints/src/pattern_type_mismatch.rs
clippy_lints/src/unnecessary_sort_by.rs
clippy_utils/src/consts.rs
clippy_utils/src/lib.rs
clippy_utils/src/numeric_literal.rs

index d136db9373c2d1273fd1cf3b4f532a62b88006f9..73f71d88b05254a5d9ed0e6a4b6f88e767974b8f 100644 (file)
@@ -13,6 +13,7 @@
     ty::{self, FloatTy, IntTy, PolyFnSig, Ty},
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for usage of unconstrained numeric literals which may cause default numeric fallback in type
@@ -107,7 +108,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         match &expr.kind {
             ExprKind::Call(func, args) => {
                 if let Some(fn_sig) = fn_sig_opt(self.cx, func.hir_id) {
-                    for (expr, bound) in args.iter().zip(fn_sig.skip_binder().inputs().iter()) {
+                    for (expr, bound) in iter::zip(*args, fn_sig.skip_binder().inputs()) {
                         // Push found arg type, then visit arg.
                         self.ty_bounds.push(TyBound::Ty(bound));
                         self.visit_expr(expr);
@@ -120,7 +121,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
             ExprKind::MethodCall(_, _, args, _) => {
                 if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
                     let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder();
-                    for (expr, bound) in args.iter().zip(fn_sig.inputs().iter()) {
+                    for (expr, bound) in iter::zip(*args, fn_sig.inputs()) {
                         self.ty_bounds.push(TyBound::Ty(bound));
                         self.visit_expr(expr);
                         self.ty_bounds.pop();
index 1c3841f8efd6feed9eb6d4801b8de63e7a1885e9..a99ed7656bfb3619d10f1e12b80c2b282329b409 100644 (file)
@@ -4,6 +4,7 @@
 #![feature(box_syntax)]
 #![feature(drain_filter)]
 #![feature(in_band_lifetimes)]
+#![feature(iter_zip)]
 #![feature(once_cell)]
 #![cfg_attr(bootstrap, feature(or_patterns))]
 #![feature(rustc_private)]
index 7fd55151226b40c39d604e6216ea7640ed931022..5447051926060dca553be8d6a45462db3b7972d2 100644 (file)
@@ -13,6 +13,7 @@
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Warns if a long integral or floating-point constant does
@@ -349,7 +350,7 @@ fn is_literal_uuid_formatted(num_lit: &mut NumericLiteral<'_>) -> bool {
 
         let group_sizes: Vec<usize> = num_lit.integer.split('_').map(str::len).collect();
         if UUID_GROUP_LENS.len() == group_sizes.len() {
-            UUID_GROUP_LENS.iter().zip(&group_sizes).all(|(&a, &b)| a == b)
+            iter::zip(&UUID_GROUP_LENS, &group_sizes).all(|(&a, &b)| a == b)
         } else {
             false
         }
index 3c40d54cb42106f33d92757dc01d86609ba915a7..64ab3b6bfec026df969e46b585182213486833f7 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_middle::middle::region;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::{sym, Symbol};
-use std::iter::Iterator;
+use std::iter::{self, Iterator};
 use std::mem;
 
 /// Checks for looping over a range and then indexing a sequence with it.
@@ -369,7 +369,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
             },
             ExprKind::MethodCall(_, _, args, _) => {
                 let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
-                for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) {
+                for (ty, expr) in iter::zip(self.cx.tcx.fn_sig(def_id).inputs().skip_binder(), args) {
                     self.prefer_mutable = false;
                     if let ty::Ref(_, _, mutbl) = *ty.kind() {
                         if mutbl == Mutability::Mut {
index 3680429fed7d8709ba446ec993d6a39da6fd6d39..2f2dc4cfc6b03eb972d95bbb573c8789897e038d 100644 (file)
@@ -29,6 +29,7 @@
 use rustc_span::sym;
 use std::cmp::Ordering;
 use std::collections::hash_map::Entry;
+use std::iter;
 use std::ops::Bound;
 
 declare_clippy_lint! {
@@ -1668,7 +1669,7 @@ fn cmp(&self, other: &Self) -> Ordering {
 
     values.sort();
 
-    for (a, b) in values.iter().zip(values.iter().skip(1)) {
+    for (a, b) in iter::zip(&values, &values[1..]) {
         match (a, b) {
             (&Kind::Start(_, ra), &Kind::End(_, rb)) => {
                 if ra.node != rb.node {
index 41bd07bcf1ea2fd2523a790792d2183762b67da1..4d3dff36a2069f34652acd5e7f3e20284bad27d9 100644 (file)
@@ -6,6 +6,7 @@
 use rustc_middle::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for sets/maps with mutable key types.
@@ -87,7 +88,7 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) {
 fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) {
     let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id);
     let fn_sig = cx.tcx.fn_sig(fn_def_id);
-    for (hir_ty, ty) in decl.inputs.iter().zip(fn_sig.inputs().skip_binder().iter()) {
+    for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) {
         check_ty(cx, hir_ty.span, ty);
     }
     check_ty(cx, decl.output.span(), cx.tcx.erase_late_bound_regions(fn_sig.output()));
index 0c09ddb80733d3ee7a16ce53e0afaee323535c25..05457e80d52c960833eb9c853da293d7532b26cd 100644 (file)
@@ -4,6 +4,7 @@
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Detects passing a mutable reference to a function that only
@@ -64,7 +65,7 @@ fn check_arguments<'tcx>(
     match type_definition.kind() {
         ty::FnDef(..) | ty::FnPtr(_) => {
             let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs();
-            for (argument, parameter) in arguments.iter().zip(parameters.iter()) {
+            for (argument, parameter) in iter::zip(arguments, parameters) {
                 match parameter.kind() {
                     ty::Ref(_, _, Mutability::Not)
                     | ty::RawPtr(ty::TypeAndMut {
index 9a5b1c3b9442a7e7f8658df06e98f5233dccd107..e151f85a39137883b3f16e596b35086e25f89c08 100644 (file)
@@ -1,4 +1,5 @@
 use std::cmp;
+use std::iter;
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_self_ty;
@@ -122,7 +123,7 @@ fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, hir_id: HirId, decl: &FnDecl
 
         let fn_body = cx.enclosing_body.map(|id| cx.tcx.hir().body(id));
 
-        for (index, (input, &ty)) in decl.inputs.iter().zip(fn_sig.inputs()).enumerate() {
+        for (index, (input, &ty)) in iter::zip(decl.inputs, fn_sig.inputs()).enumerate() {
             // All spans generated from a proc-macro invocation are the same...
             match span {
                 Some(s) if s == input.span => return,
index 4550b367da4bf92fd9a39493554c9e105dc2621b..c0c2ab67e382e0194906e80c4955867a84636b7c 100644 (file)
@@ -10,6 +10,7 @@
 use rustc_middle::ty::{AdtDef, FieldDef, Ty, TyKind, VariantDef};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for patterns that aren't exact representations of the types
@@ -134,7 +135,7 @@ fn check_fn(
         hir_id: HirId,
     ) {
         if let Some(fn_sig) = cx.typeck_results().liberated_fn_sigs().get(hir_id) {
-            for (param, ty) in body.params.iter().zip(fn_sig.inputs().iter()) {
+            for (param, ty) in iter::zip(body.params, fn_sig.inputs()) {
                 apply_lint(cx, &param.pat, ty, DerefPossible::Impossible);
             }
         }
index e23bab5eba03fc2f50f16f23e2a9935176875aaf..6becff9662a76ff79b74e191baf506b7788ee73b 100644 (file)
@@ -9,6 +9,7 @@
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 use rustc_span::symbol::Ident;
+use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:**
@@ -79,17 +80,15 @@ fn mirrored_exprs(
             mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident)
         },
         // Two arrays with mirrored contents
-        (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => left_exprs
-            .iter()
-            .zip(right_exprs.iter())
-            .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)),
+        (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => {
+            iter::zip(*left_exprs, *right_exprs)
+                .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
+        }
         // The two exprs are function calls.
         // Check to see that the function itself and its arguments are mirrored
         (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) => {
             mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident)
-                && left_args
-                    .iter()
-                    .zip(right_args.iter())
+                && iter::zip(*left_args, *right_args)
                     .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
         },
         // The two exprs are method calls.
@@ -100,16 +99,14 @@ fn mirrored_exprs(
             ExprKind::MethodCall(right_segment, _, right_args, _),
         ) => {
             left_segment.ident == right_segment.ident
-                && left_args
-                    .iter()
-                    .zip(right_args.iter())
+                && iter::zip(*left_args, *right_args)
                     .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
-        },
+        }
         // Two tuples with mirrored contents
-        (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => left_exprs
-            .iter()
-            .zip(right_exprs.iter())
-            .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)),
+        (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => {
+            iter::zip(*left_exprs, *right_exprs)
+                .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
+        }
         // Two binary ops, which are the same operation and which have mirrored arguments
         (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) => {
             left_op.node == right_op.node
@@ -146,9 +143,7 @@ fn mirrored_exprs(
                 },
             )),
         ) => {
-            (left_segments
-                .iter()
-                .zip(right_segments.iter())
+            (iter::zip(*left_segments, *right_segments)
                 .all(|(left, right)| left.ident == right.ident)
                 && left_segments
                     .iter()
index ebe896b7ae86771c13ecabf27d3434a7d53ec6e0..8af10ebe777ea0ed4c2c9b54df7b6017558a9355 100644 (file)
@@ -15,6 +15,7 @@
 use std::cmp::Ordering::{self, Equal};
 use std::convert::TryInto;
 use std::hash::{Hash, Hasher};
+use std::iter;
 
 /// A `LitKind`-like enum to fold constant `Expr`s into.
 #[derive(Debug, Clone)]
@@ -139,12 +140,12 @@ pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self)
             (&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r),
             (&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r),
             (&Self::Bool(ref l), &Self::Bool(ref r)) => Some(l.cmp(r)),
-            (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => l
-                .iter()
-                .zip(r.iter())
-                .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
-                .find(|r| r.map_or(true, |o| o != Ordering::Equal))
-                .unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
+            (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => {
+                iter::zip(l, r)
+                    .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
+                    .find(|r| r.map_or(true, |o| o != Ordering::Equal))
+                    .unwrap_or_else(|| Some(l.len().cmp(&r.len())))
+            }
             (&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => {
                 match Self::partial_cmp(tcx, cmp_type, lv, rv) {
                     Some(Equal) => Some(ls.cmp(rs)),
index b613ae9b9180645b2754ac143c58b7de9fa8fa01..b2655f8d797b1e67aa166d5cdb7d6c0ce873cfd5 100644 (file)
@@ -1,5 +1,6 @@
 #![feature(box_patterns)]
 #![feature(in_band_lifetimes)]
+#![feature(iter_zip)]
 #![cfg_attr(bootstrap, feature(or_patterns))]
 #![feature(rustc_private)]
 #![recursion_limit = "512"]
index d02603d7702c7f3c6a8f7f48d30b29a027ff7e00..268bc5b320533536ea5fba32dd5d7bcf8c0ce9bf 100644 (file)
@@ -1,4 +1,5 @@
 use rustc_ast::ast::{Lit, LitFloatType, LitIntType, LitKind};
+use std::iter;
 
 #[derive(Debug, PartialEq, Copy, Clone)]
 pub enum Radix {
@@ -192,7 +193,7 @@ pub fn group_digits(output: &mut String, input: &str, group_size: usize, partial
             }
         }
 
-        for (c, i) in digits.zip((0..group_size).cycle()) {
+        for (c, i) in iter::zip(digits, (0..group_size).cycle()) {
             if i == 0 {
                 output.push('_');
             }