]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_lint/array_into_iter.rs
Rollup merge of #67875 - dtolnay:hidden, r=GuillaumeGomez
[rust.git] / src / librustc_lint / array_into_iter.rs
index 5a001ef18b2edfc7727554fcad66e5317589853e..46202cda16d50aefc7786c487db42092cd669d5f 100644 (file)
@@ -1,13 +1,10 @@
 use crate::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
-use rustc::{
-    hir,
-    lint::FutureIncompatibleInfo,
-    ty::{
-        self,
-        adjustment::{Adjust, Adjustment},
-    },
-};
-use syntax::{errors::Applicability, symbol::sym};
+use rustc::lint::FutureIncompatibleInfo;
+use rustc::ty;
+use rustc::ty::adjustment::{Adjust, Adjustment};
+use rustc_hir as hir;
+use rustc_span::symbol::sym;
+use syntax::errors::Applicability;
 
 declare_lint! {
     pub ARRAY_INTO_ITER,
@@ -25,7 +22,7 @@
 );
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter {
-    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
+    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'tcx>) {
         // We only care about method call expressions.
         if let hir::ExprKind::MethodCall(call, span, args) = &expr.kind {
             if call.ident.name != sym::into_iter {
@@ -44,14 +41,26 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
             // argument.
             let receiver_arg = &args[0];
 
-            // Test if the original `self` type is an array type.
-            match cx.tables.expr_ty(receiver_arg).kind {
-                ty::Array(..) => {}
-                _ => return,
+            // Peel all `Box<_>` layers. We have to special case `Box` here as
+            // `Box` is the only thing that values can be moved out of via
+            // method call. `Box::new([1]).into_iter()` should trigger this
+            // lint.
+            let mut recv_ty = cx.tables.expr_ty(receiver_arg);
+            let mut num_box_derefs = 0;
+            while recv_ty.is_box() {
+                num_box_derefs += 1;
+                recv_ty = recv_ty.boxed_ty();
+            }
+
+            // Make sure we found an array after peeling the boxes.
+            if !matches!(recv_ty.kind, ty::Array(..)) {
+                return;
             }
 
-            // Make sure that the first adjustment is an autoref coercion.
-            match cx.tables.expr_adjustments(receiver_arg).get(0) {
+            // Make sure that there is an autoref coercion at the expected
+            // position. The first `num_box_derefs` adjustments are the derefs
+            // of the box.
+            match cx.tables.expr_adjustments(receiver_arg).get(num_box_derefs) {
                 Some(Adjustment { kind: Adjust::Borrow(_), .. }) => {}
                 _ => return,
             }