+enum Slice<'a> {
+ /// `slice.swap(idx1, idx2)` can be used
+ ///
+ /// ## Example
+ ///
+ /// ```rust
+ /// # let mut a = vec![0, 1];
+ /// let t = a[1];
+ /// a[1] = a[0];
+ /// a[0] = t;
+ /// // can be written as
+ /// a.swap(0, 1);
+ /// ```
+ Swappable(&'a Expr, &'a Expr, &'a Expr),
+ /// The `swap` function cannot be used.
+ ///
+ /// ## Example
+ ///
+ /// ```rust
+ /// # let mut a = [vec![1, 2], vec![3, 4]];
+ /// let t = a[0][1];
+ /// a[0][1] = a[1][0];
+ /// a[1][0] = t;
+ /// ```
+ NotSwappable,
+ /// Not a slice
+ None,
+}
+
+/// Checks if both expressions are index operations into "slice-like" types.
+fn check_for_slice<'a>(cx: &LateContext<'_, '_>, lhs1: &'a Expr, lhs2: &'a Expr) -> Slice<'a> {
+ if let ExprKind::Index(ref lhs1, ref idx1) = lhs1.kind {
+ if let ExprKind::Index(ref lhs2, ref idx2) = lhs2.kind {
+ if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) {
+ let ty = walk_ptrs_ty(cx.tables.expr_ty(lhs1));
+
+ if matches!(ty.kind, ty::Slice(_))
+ || matches!(ty.kind, ty::Array(_, _))
+ || is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type"))
+ || match_type(cx, ty, &paths::VEC_DEQUE)
+ {
+ return Slice::Swappable(lhs1, idx1, idx2);
+ }
+ } else {
+ return Slice::NotSwappable;
+ }
+ }
+ }
+
+ Slice::None
+}
+