@@ -74,39 +74,45 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
7474 _ => return ,
7575 } ;
7676
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.
7978 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) ;
8081
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+ } ;
9186
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+ }
95106 }
96107
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 ;
103110 }
104111
105112 // Emit lint diagnostic.
106- let target = match * cx . typeck_results ( ) . expr_ty_adjusted ( receiver_arg ) . kind ( ) {
113+ let target = match * target . kind ( ) {
107114 ty:: Ref ( _, inner_ty, _) if inner_ty. is_array ( ) => "[T; N]" ,
108115 ty:: Ref ( _, inner_ty, _) if matches ! ( inner_ty. kind( ) , ty:: Slice ( ..) ) => "[T]" ,
109-
110116 // We know the original first argument type is an array type,
111117 // we know that the first adjustment was an autoref coercion
112118 // and we know that `IntoIterator` is the trait involved. The
0 commit comments