mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 01:34:21 +00:00
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
b094bb1bd7
@ -13,6 +13,7 @@ use rustc_middle::{
|
||||
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 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
|
||||
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();
|
||||
|
@ -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)]
|
||||
|
@ -13,6 +13,7 @@ use rustc_errors::Applicability;
|
||||
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 @@ impl LiteralDigitGrouping {
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ use rustc_middle::hir::map::Map;
|
||||
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 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
|
||||
},
|
||||
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 {
|
||||
|
@ -29,6 +29,7 @@ use rustc_span::source_map::{Span, Spanned};
|
||||
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 @@ where
|
||||
|
||||
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 {
|
||||
|
@ -6,6 +6,7 @@ use rustc_middle::ty::TypeFoldable;
|
||||
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 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
|
||||
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()));
|
||||
|
@ -4,6 +4,7 @@ use rustc_lint::{LateContext, LateLintPass};
|
||||
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 {
|
||||
|
@ -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 @@ impl<'tcx> PassByRefOrValue {
|
||||
|
||||
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,
|
||||
|
@ -10,6 +10,7 @@ use rustc_middle::ty::subst::SubstsRef;
|
||||
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 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch {
|
||||
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, ¶m.pat, ty, DerefPossible::Impossible);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ use rustc_middle::ty::{self, subst::GenericArgKind};
|
||||
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()
|
||||
|
@ -15,6 +15,7 @@ use rustc_span::symbol::Symbol;
|
||||
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 @@ impl Constant {
|
||||
(&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)),
|
||||
|
@ -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"]
|
||||
|
@ -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 @@ impl<'a> NumericLiteral<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
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('_');
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user