|
1 | 1 | //! lint on indexing and slicing operations
|
2 | 2 |
|
3 | 3 | use crate::consts::{constant, Constant};
|
| 4 | +use crate::utils; |
| 5 | +use crate::utils::higher; |
4 | 6 | use crate::utils::higher::Range;
|
5 |
| -use crate::utils::{self, higher}; |
6 | 7 | use rustc::hir::*;
|
7 | 8 | use rustc::lint::*;
|
8 | 9 | use rustc::ty;
|
@@ -97,89 +98,65 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing {
|
97 | 98 | fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
98 | 99 | if let ExprIndex(ref array, ref index) = &expr.node {
|
99 | 100 | let ty = cx.tables.expr_ty(array);
|
100 |
| - match &index.node { |
101 |
| - // Both ExprStruct and ExprPath require this approach's checks |
102 |
| - // on the `range` returned by `higher::range(cx, index)`. |
103 |
| - // ExprStruct handles &x[n..m], &x[n..] and &x[..n]. |
104 |
| - // ExprPath handles &x[..] and x[var] |
105 |
| - ExprStruct(..) | ExprPath(..) => { |
106 |
| - if let Some(range) = higher::range(cx, index) { |
107 |
| - if let ty::TyArray(_, s) = ty.sty { |
108 |
| - let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); |
109 |
| - // Index is a constant range. |
110 |
| - if let Some((start, end)) = to_const_range(cx, range, size) { |
111 |
| - if start > size || end > size { |
112 |
| - utils::span_lint( |
113 |
| - cx, |
114 |
| - OUT_OF_BOUNDS_INDEXING, |
115 |
| - expr.span, |
116 |
| - "range is out of bounds", |
117 |
| - ); |
118 |
| - } // Else range is in bounds, ok. |
119 |
| - |
120 |
| - return; |
121 |
| - } |
| 101 | + if let Some(range) = higher::range(cx, index) { |
| 102 | + // Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..] |
| 103 | + if let ty::TyArray(_, s) = ty.sty { |
| 104 | + let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); |
| 105 | + // Index is a constant range. |
| 106 | + if let Some((start, end)) = to_const_range(cx, range, size) { |
| 107 | + if start > size || end > size { |
| 108 | + utils::span_lint( |
| 109 | + cx, |
| 110 | + OUT_OF_BOUNDS_INDEXING, |
| 111 | + expr.span, |
| 112 | + "range is out of bounds", |
| 113 | + ); |
122 | 114 | }
|
123 |
| - |
124 |
| - let help_msg = match (range.start, range.end) { |
125 |
| - (None, Some(_)) => { |
126 |
| - "Consider using `.get(..n)`or `.get_mut(..n)` instead" |
127 |
| - } |
128 |
| - (Some(_), None) => { |
129 |
| - "Consider using `.get(n..)` or .get_mut(n..)` instead" |
130 |
| - } |
131 |
| - (Some(_), Some(_)) => { |
132 |
| - "Consider using `.get(n..m)` or `.get_mut(n..m)` instead" |
133 |
| - } |
134 |
| - (None, None) => return, // [..] is ok. |
135 |
| - }; |
136 |
| - |
137 |
| - utils::span_help_and_lint( |
138 |
| - cx, |
139 |
| - INDEXING_SLICING, |
140 |
| - expr.span, |
141 |
| - "slicing may panic.", |
142 |
| - help_msg, |
143 |
| - ); |
144 |
| - } else { |
145 |
| - utils::span_help_and_lint( |
146 |
| - cx, |
147 |
| - INDEXING_SLICING, |
148 |
| - expr.span, |
149 |
| - "indexing may panic.", |
150 |
| - "Consider using `.get(n)` or `.get_mut(n)` instead", |
151 |
| - ); |
| 115 | + return; |
152 | 116 | }
|
153 | 117 | }
|
154 |
| - ExprLit(..) => { |
155 |
| - // [n] |
156 |
| - if let ty::TyArray(_, s) = ty.sty { |
157 |
| - let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); |
158 |
| - // Index is a constant uint. |
159 |
| - if let Some((Constant::Int(const_index), _)) = |
160 |
| - constant(cx, cx.tables, index) |
161 |
| - { |
162 |
| - if size <= const_index { |
163 |
| - utils::span_lint( |
164 |
| - cx, |
165 |
| - OUT_OF_BOUNDS_INDEXING, |
166 |
| - expr.span, |
167 |
| - "const index is out of bounds", |
168 |
| - ); |
169 |
| - } |
170 |
| - // Else index is in bounds, ok. |
| 118 | + |
| 119 | + let help_msg = match (range.start, range.end) { |
| 120 | + (None, Some(_)) => "Consider using `.get(..n)`or `.get_mut(..n)` instead", |
| 121 | + (Some(_), None) => "Consider using `.get(n..)` or .get_mut(n..)` instead", |
| 122 | + (Some(_), Some(_)) => "Consider using `.get(n..m)` or `.get_mut(n..m)` instead", |
| 123 | + (None, None) => return, // [..] is ok. |
| 124 | + }; |
| 125 | + |
| 126 | + utils::span_help_and_lint( |
| 127 | + cx, |
| 128 | + INDEXING_SLICING, |
| 129 | + expr.span, |
| 130 | + "slicing may panic.", |
| 131 | + help_msg, |
| 132 | + ); |
| 133 | + } else { |
| 134 | + // Catchall non-range index, i.e. [n] or [n << m] |
| 135 | + if let ty::TyArray(_, s) = ty.sty { |
| 136 | + let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); |
| 137 | + // Index is a constant uint. |
| 138 | + if let Some((Constant::Int(const_index), _)) = constant(cx, cx.tables, index) { |
| 139 | + if size <= const_index { |
| 140 | + utils::span_lint( |
| 141 | + cx, |
| 142 | + OUT_OF_BOUNDS_INDEXING, |
| 143 | + expr.span, |
| 144 | + "const index is out of bounds", |
| 145 | + ); |
171 | 146 | }
|
172 |
| - } else { |
173 |
| - utils::span_help_and_lint( |
174 |
| - cx, |
175 |
| - INDEXING_SLICING, |
176 |
| - expr.span, |
177 |
| - "indexing may panic.", |
178 |
| - "Consider using `.get(n)` or `.get_mut(n)` instead", |
179 |
| - ); |
| 147 | + // Else index is in bounds, ok. |
| 148 | + |
| 149 | + return; |
180 | 150 | }
|
181 | 151 | }
|
182 |
| - _ => (), |
| 152 | + |
| 153 | + utils::span_help_and_lint( |
| 154 | + cx, |
| 155 | + INDEXING_SLICING, |
| 156 | + expr.span, |
| 157 | + "indexing may panic.", |
| 158 | + "Consider using `.get(n)` or `.get_mut(n)` instead", |
| 159 | + ); |
183 | 160 | }
|
184 | 161 | }
|
185 | 162 | }
|
|
0 commit comments