1
1
use hir:: { ExprKind , Node , is_range_literal} ;
2
2
use rustc_abi:: { Integer , Size } ;
3
+ use rustc_hir:: HirId ;
3
4
use rustc_middle:: ty:: Ty ;
4
5
use rustc_middle:: ty:: layout:: IntegerExt ;
5
6
use rustc_middle:: { bug, ty} ;
7
+ use rustc_span:: Span ;
6
8
use { rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir} ;
7
9
8
10
use crate :: LateContext ;
@@ -21,21 +23,22 @@ fn lint_overflowing_range_endpoint<'tcx>(
21
23
lit : & hir:: Lit ,
22
24
lit_val : u128 ,
23
25
max : u128 ,
24
- expr : & ' tcx hir:: Expr < ' tcx > ,
26
+ hir_id : HirId ,
27
+ lit_span : Span ,
25
28
ty : & str ,
26
29
) -> bool {
27
30
// Look past casts to support cases like `0..256 as u8`
28
- let ( expr , lit_span ) = if let Node :: Expr ( par_expr) = cx. tcx . parent_hir_node ( expr . hir_id )
31
+ let ( hir_id , span ) = if let Node :: Expr ( par_expr) = cx. tcx . parent_hir_node ( hir_id)
29
32
&& let ExprKind :: Cast ( _, _) = par_expr. kind
30
33
{
31
- ( par_expr, expr . span )
34
+ ( par_expr. hir_id , par_expr . span )
32
35
} else {
33
- ( expr , expr . span )
36
+ ( hir_id , lit_span )
34
37
} ;
35
38
36
39
// We only want to handle exclusive (`..`) ranges,
37
40
// which are represented as `ExprKind::Struct`.
38
- let Node :: ExprField ( field) = cx. tcx . parent_hir_node ( expr . hir_id ) else { return false } ;
41
+ let Node :: ExprField ( field) = cx. tcx . parent_hir_node ( hir_id) else { return false } ;
39
42
let Node :: Expr ( struct_expr) = cx. tcx . parent_hir_node ( field. hir_id ) else { return false } ;
40
43
if !is_range_literal ( struct_expr) {
41
44
return false ;
@@ -45,7 +48,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
45
48
// We can suggest using an inclusive range
46
49
// (`..=`) instead only if it is the `end` that is
47
50
// overflowing and only by 1.
48
- if !( end. expr . hir_id == expr . hir_id && lit_val - 1 == max) {
51
+ if !( end. expr . hir_id == hir_id && lit_val - 1 == max) {
49
52
return false ;
50
53
} ;
51
54
@@ -57,7 +60,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
57
60
_ => bug ! ( ) ,
58
61
} ;
59
62
60
- let sub_sugg = if expr . span . lo ( ) == lit_span. lo ( ) {
63
+ let sub_sugg = if span. lo ( ) == lit_span. lo ( ) {
61
64
let Ok ( start) = cx. sess ( ) . source_map ( ) . span_to_snippet ( start. span ) else { return false } ;
62
65
UseInclusiveRange :: WithoutParen {
63
66
sugg : struct_expr. span . shrink_to_lo ( ) . to ( lit_span. shrink_to_hi ( ) ) ,
@@ -67,7 +70,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
67
70
}
68
71
} else {
69
72
UseInclusiveRange :: WithParen {
70
- eq_sugg : expr . span . shrink_to_lo ( ) ,
73
+ eq_sugg : span. shrink_to_lo ( ) ,
71
74
lit_sugg : lit_span,
72
75
literal : lit_val - 1 ,
73
76
suffix,
@@ -125,7 +128,8 @@ fn get_bin_hex_repr(cx: &LateContext<'_>, lit: &hir::Lit) -> Option<String> {
125
128
126
129
fn report_bin_hex_error (
127
130
cx : & LateContext < ' _ > ,
128
- expr : & hir:: Expr < ' _ > ,
131
+ hir_id : HirId ,
132
+ span : Span ,
129
133
ty : attr:: IntType ,
130
134
size : Size ,
131
135
repr_str : String ,
@@ -144,19 +148,19 @@ fn report_bin_hex_error(
144
148
} ;
145
149
let sign =
146
150
if negative { OverflowingBinHexSign :: Negative } else { OverflowingBinHexSign :: Positive } ;
147
- let sub = get_type_suggestion ( cx. typeck_results ( ) . node_type ( expr . hir_id ) , val, negative) . map (
151
+ let sub = get_type_suggestion ( cx. typeck_results ( ) . node_type ( hir_id) , val, negative) . map (
148
152
|suggestion_ty| {
149
153
if let Some ( pos) = repr_str. chars ( ) . position ( |c| c == 'i' || c == 'u' ) {
150
154
let ( sans_suffix, _) = repr_str. split_at ( pos) ;
151
- OverflowingBinHexSub :: Suggestion { span : expr . span , suggestion_ty, sans_suffix }
155
+ OverflowingBinHexSub :: Suggestion { span, suggestion_ty, sans_suffix }
152
156
} else {
153
157
OverflowingBinHexSub :: Help { suggestion_ty }
154
158
}
155
159
} ,
156
160
) ;
157
161
let sign_bit_sub = ( !negative)
158
162
. then ( || {
159
- let ty:: Int ( int_ty) = cx. typeck_results ( ) . node_type ( expr . hir_id ) . kind ( ) else {
163
+ let ty:: Int ( int_ty) = cx. typeck_results ( ) . node_type ( hir_id) . kind ( ) else {
160
164
return None ;
161
165
} ;
162
166
@@ -177,7 +181,7 @@ fn report_bin_hex_error(
177
181
} ;
178
182
179
183
Some ( OverflowingBinHexSignBitSub {
180
- span : expr . span ,
184
+ span,
181
185
lit_no_suffix,
182
186
negative_val : actually. clone ( ) ,
183
187
int_ty : int_ty. name_str ( ) ,
@@ -186,7 +190,7 @@ fn report_bin_hex_error(
186
190
} )
187
191
. flatten ( ) ;
188
192
189
- cx. emit_span_lint ( OVERFLOWING_LITERALS , expr . span , OverflowingBinHex {
193
+ cx. emit_span_lint ( OVERFLOWING_LITERALS , span, OverflowingBinHex {
190
194
ty : t,
191
195
lit : repr_str. clone ( ) ,
192
196
dec : val,
@@ -236,23 +240,26 @@ fn literal_to_i128(val: u128, negative: bool) -> Option<i128> {
236
240
fn lint_int_literal < ' tcx > (
237
241
cx : & LateContext < ' tcx > ,
238
242
type_limits : & TypeLimits ,
239
- e : & ' tcx hir:: Expr < ' tcx > ,
243
+ hir_id : HirId ,
244
+ span : Span ,
240
245
lit : & hir:: Lit ,
241
246
t : ty:: IntTy ,
242
247
v : u128 ,
248
+ negated : bool ,
243
249
) {
244
250
let int_type = t. normalize ( cx. sess ( ) . target . pointer_width ) ;
245
251
let ( min, max) = int_ty_range ( int_type) ;
246
252
let max = max as u128 ;
247
- let negative = type_limits. negated_expr_id == Some ( e . hir_id ) ;
253
+ let negative = negated ^ ( type_limits. negated_expr_id == Some ( hir_id) ) ;
248
254
249
255
// Detect literal value out of range [min, max] inclusive
250
256
// avoiding use of -min to prevent overflow/panic
251
257
if ( negative && v > max + 1 ) || ( !negative && v > max) {
252
258
if let Some ( repr_str) = get_bin_hex_repr ( cx, lit) {
253
259
report_bin_hex_error (
254
260
cx,
255
- e,
261
+ hir_id,
262
+ span,
256
263
attr:: IntType :: SignedInt ( ty:: ast_int_ty ( t) ) ,
257
264
Integer :: from_int_ty ( cx, t) . size ( ) ,
258
265
repr_str,
@@ -262,18 +269,18 @@ fn lint_int_literal<'tcx>(
262
269
return ;
263
270
}
264
271
265
- if lint_overflowing_range_endpoint ( cx, lit, v, max, e , t. name_str ( ) ) {
272
+ if lint_overflowing_range_endpoint ( cx, lit, v, max, hir_id , span , t. name_str ( ) ) {
266
273
// The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`.
267
274
return ;
268
275
}
269
276
270
- let span = if negative { type_limits. negated_expr_span . unwrap ( ) } else { e . span } ;
277
+ let span = if negative { type_limits. negated_expr_span . unwrap ( ) } else { span } ;
271
278
let lit = cx
272
279
. sess ( )
273
280
. source_map ( )
274
281
. span_to_snippet ( span)
275
282
. unwrap_or_else ( |_| if negative { format ! ( "-{v}" ) } else { v. to_string ( ) } ) ;
276
- let help = get_type_suggestion ( cx. typeck_results ( ) . node_type ( e . hir_id ) , v, negative)
283
+ let help = get_type_suggestion ( cx. typeck_results ( ) . node_type ( hir_id) , v, negative)
277
284
. map ( |suggestion_ty| OverflowingIntHelp { suggestion_ty } ) ;
278
285
279
286
cx. emit_span_lint ( OVERFLOWING_LITERALS , span, OverflowingInt {
@@ -288,7 +295,8 @@ fn lint_int_literal<'tcx>(
288
295
289
296
fn lint_uint_literal < ' tcx > (
290
297
cx : & LateContext < ' tcx > ,
291
- e : & ' tcx hir:: Expr < ' tcx > ,
298
+ hir_id : HirId ,
299
+ span : Span ,
292
300
lit : & hir:: Lit ,
293
301
t : ty:: UintTy ,
294
302
) {
@@ -302,7 +310,7 @@ fn lint_uint_literal<'tcx>(
302
310
} ;
303
311
304
312
if lit_val < min || lit_val > max {
305
- if let Node :: Expr ( par_e) = cx. tcx . parent_hir_node ( e . hir_id ) {
313
+ if let Node :: Expr ( par_e) = cx. tcx . parent_hir_node ( hir_id) {
306
314
match par_e. kind {
307
315
hir:: ExprKind :: Cast ( ..) => {
308
316
if let ty:: Char = cx. typeck_results ( ) . expr_ty ( par_e) . kind ( ) {
@@ -316,14 +324,15 @@ fn lint_uint_literal<'tcx>(
316
324
_ => { }
317
325
}
318
326
}
319
- if lint_overflowing_range_endpoint ( cx, lit, lit_val, max, e , t. name_str ( ) ) {
327
+ if lint_overflowing_range_endpoint ( cx, lit, lit_val, max, hir_id , span , t. name_str ( ) ) {
320
328
// The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`.
321
329
return ;
322
330
}
323
331
if let Some ( repr_str) = get_bin_hex_repr ( cx, lit) {
324
332
report_bin_hex_error (
325
333
cx,
326
- e,
334
+ hir_id,
335
+ span,
327
336
attr:: IntType :: UnsignedInt ( ty:: ast_uint_ty ( t) ) ,
328
337
Integer :: from_uint_ty ( cx, t) . size ( ) ,
329
338
repr_str,
@@ -332,7 +341,7 @@ fn lint_uint_literal<'tcx>(
332
341
) ;
333
342
return ;
334
343
}
335
- cx. emit_span_lint ( OVERFLOWING_LITERALS , e . span , OverflowingUInt {
344
+ cx. emit_span_lint ( OVERFLOWING_LITERALS , span, OverflowingUInt {
336
345
ty : t. name_str ( ) ,
337
346
lit : cx
338
347
. sess ( )
@@ -348,19 +357,24 @@ fn lint_uint_literal<'tcx>(
348
357
pub ( crate ) fn lint_literal < ' tcx > (
349
358
cx : & LateContext < ' tcx > ,
350
359
type_limits : & TypeLimits ,
351
- e : & ' tcx hir:: Expr < ' tcx > ,
360
+ hir_id : HirId ,
361
+ span : Span ,
352
362
lit : & hir:: Lit ,
363
+ negated : bool ,
353
364
) {
354
- match * cx. typeck_results ( ) . node_type ( e . hir_id ) . kind ( ) {
365
+ match * cx. typeck_results ( ) . node_type ( hir_id) . kind ( ) {
355
366
ty:: Int ( t) => {
356
367
match lit. node {
357
368
ast:: LitKind :: Int ( v, ast:: LitIntType :: Signed ( _) | ast:: LitIntType :: Unsuffixed ) => {
358
- lint_int_literal ( cx, type_limits, e , lit, t, v. get ( ) )
369
+ lint_int_literal ( cx, type_limits, hir_id , span , lit, t, v. get ( ) , negated )
359
370
}
360
371
_ => bug ! ( ) ,
361
372
} ;
362
373
}
363
- ty:: Uint ( t) => lint_uint_literal ( cx, e, lit, t) ,
374
+ ty:: Uint ( t) => {
375
+ assert ! ( !negated) ;
376
+ lint_uint_literal ( cx, hir_id, span, lit, t)
377
+ }
364
378
ty:: Float ( t) => {
365
379
let ( is_infinite, sym) = match lit. node {
366
380
ast:: LitKind :: Float ( v, _) => match t {
@@ -374,7 +388,7 @@ pub(crate) fn lint_literal<'tcx>(
374
388
_ => bug ! ( ) ,
375
389
} ;
376
390
if is_infinite == Ok ( true ) {
377
- cx. emit_span_lint ( OVERFLOWING_LITERALS , e . span , OverflowingLiteral {
391
+ cx. emit_span_lint ( OVERFLOWING_LITERALS , span, OverflowingLiteral {
378
392
ty : t. name_str ( ) ,
379
393
lit : cx
380
394
. sess ( )
0 commit comments