@@ -74,39 +74,45 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
74
74
_ => return ,
75
75
} ;
76
76
77
- // As this is a method call expression, we have at least one
78
- // argument.
77
+ // As this is a method call expression, we have at least one argument.
79
78
let receiver_arg = & args[ 0 ] ;
79
+ let receiver_ty = cx. typeck_results ( ) . expr_ty ( receiver_arg) ;
80
+ let adjustments = cx. typeck_results ( ) . expr_adjustments ( receiver_arg) ;
80
81
81
- // Peel all `Box<_>` layers. We have to special case `Box` here as
82
- // `Box` is the only thing that values can be moved out of via
83
- // method call. `Box::new([1]).into_iter()` should trigger this
84
- // lint.
85
- let mut recv_ty = cx. typeck_results ( ) . expr_ty ( receiver_arg) ;
86
- let mut num_box_derefs = 0 ;
87
- while recv_ty. is_box ( ) {
88
- num_box_derefs += 1 ;
89
- recv_ty = recv_ty. boxed_ty ( ) ;
90
- }
82
+ let target = match adjustments. last ( ) {
83
+ Some ( Adjustment { kind : Adjust :: Borrow ( _) , target } ) => target,
84
+ _ => return ,
85
+ } ;
91
86
92
- // Make sure we found an array after peeling the boxes.
93
- if !matches ! ( recv_ty. kind( ) , ty:: Array ( ..) ) {
94
- return ;
87
+ let types =
88
+ std:: iter:: once ( receiver_ty) . chain ( adjustments. iter ( ) . map ( |adj| adj. target ) ) ;
89
+
90
+ let mut found_array = false ;
91
+
92
+ for ty in types {
93
+ match ty. kind ( ) {
94
+ // If we run into a &[T; N] or &[T] first, there's nothing to warn about.
95
+ // It'll resolve to the reference version.
96
+ ty:: Ref ( _, inner_ty, _) if inner_ty. is_array ( ) => return ,
97
+ ty:: Ref ( _, inner_ty, _) if matches ! ( inner_ty. kind( ) , ty:: Slice ( ..) ) => return ,
98
+ // Found an actual array type without matching a &[T; N] first.
99
+ // This is the problematic case.
100
+ ty:: Array ( ..) => {
101
+ found_array = true ;
102
+ break ;
103
+ }
104
+ _ => { }
105
+ }
95
106
}
96
107
97
- // Make sure that there is an autoref coercion at the expected
98
- // position. The first `num_box_derefs` adjustments are the derefs
99
- // of the box.
100
- match cx. typeck_results ( ) . expr_adjustments ( receiver_arg) . get ( num_box_derefs) {
101
- Some ( Adjustment { kind : Adjust :: Borrow ( _) , .. } ) => { }
102
- _ => return ,
108
+ if !found_array {
109
+ return ;
103
110
}
104
111
105
112
// Emit lint diagnostic.
106
- let target = match * cx . typeck_results ( ) . expr_ty_adjusted ( receiver_arg ) . kind ( ) {
113
+ let target = match * target . kind ( ) {
107
114
ty:: Ref ( _, inner_ty, _) if inner_ty. is_array ( ) => "[T; N]" ,
108
115
ty:: Ref ( _, inner_ty, _) if matches ! ( inner_ty. kind( ) , ty:: Slice ( ..) ) => "[T]" ,
109
-
110
116
// We know the original first argument type is an array type,
111
117
// we know that the first adjustment was an autoref coercion
112
118
// and we know that `IntoIterator` is the trait involved. The
0 commit comments