@@ -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