8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
+ #![ allow( non_snake_case) ]
12
+
11
13
use middle:: { infer} ;
12
14
use middle:: def_id:: DefId ;
13
15
use middle:: subst:: Substs ;
@@ -24,13 +26,39 @@ use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
24
26
use syntax:: { abi, ast} ;
25
27
use syntax:: attr:: { self , AttrMetaMethods } ;
26
28
use syntax:: codemap:: { self , Span } ;
27
- use syntax:: feature_gate:: { emit_feature_err, GateIssue } ;
28
29
use syntax:: ast:: { TyIs , TyUs , TyI8 , TyU8 , TyI16 , TyU16 , TyI32 , TyU32 , TyI64 , TyU64 } ;
29
30
30
31
use rustc_front:: hir;
31
32
use rustc_front:: intravisit:: { self , Visitor } ;
32
33
use rustc_front:: util:: is_shift_binop;
33
34
35
+ register_long_diagnostics ! {
36
+ E0519 : r##"
37
+ It is not allowed to negate an unsigned integer.
38
+ You can negate a signed integer and cast it to an
39
+ unsigned integer or use the `!` operator.
40
+
41
+ ```
42
+ let x: usize = -1isize as usize;
43
+ let y: usize = !0;
44
+ assert_eq!(x, y);
45
+ ```
46
+
47
+ Alternatively you can use the `Wrapping` newtype
48
+ or the `wrapping_neg` operation that all
49
+ integral types support:
50
+
51
+ ```
52
+ use std::num::Wrapping;
53
+ let x: Wrapping<usize> = -Wrapping(1);
54
+ let Wrapping(x) = x;
55
+ let y: usize = 1.wrapping_neg();
56
+ assert_eq!(x, y);
57
+ ```
58
+
59
+ "##
60
+ }
61
+
34
62
declare_lint ! {
35
63
UNUSED_COMPARISONS ,
36
64
Warn ,
@@ -73,30 +101,24 @@ impl LateLintPass for TypeLimits {
73
101
fn check_expr ( & mut self , cx : & LateContext , e : & hir:: Expr ) {
74
102
match e. node {
75
103
hir:: ExprUnary ( hir:: UnNeg , ref expr) => {
76
- match expr. node {
77
- hir:: ExprLit ( ref lit) => {
78
- match lit. node {
79
- ast:: LitInt ( _, ast:: UnsignedIntLit ( _) ) => {
80
- check_unsigned_negation_feature ( cx, e. span ) ;
81
- } ,
82
- ast:: LitInt ( _, ast:: UnsuffixedIntLit ( _) ) => {
83
- if let ty:: TyUint ( _) = cx. tcx . node_id_to_type ( e. id ) . sty {
84
- check_unsigned_negation_feature ( cx, e. span ) ;
85
- }
86
- } ,
87
- _ => ( )
88
- }
89
- } ,
90
- _ => {
91
- let t = cx. tcx . node_id_to_type ( expr. id ) ;
92
- match t. sty {
93
- ty:: TyUint ( _) => {
94
- check_unsigned_negation_feature ( cx, e. span ) ;
95
- } ,
96
- _ => ( )
97
- }
104
+ if let hir:: ExprLit ( ref lit) = expr. node {
105
+ match lit. node {
106
+ ast:: LitInt ( _, ast:: UnsignedIntLit ( _) ) => {
107
+ forbid_unsigned_negation ( cx, e. span ) ;
108
+ } ,
109
+ ast:: LitInt ( _, ast:: UnsuffixedIntLit ( _) ) => {
110
+ if let ty:: TyUint ( _) = cx. tcx . node_id_to_type ( e. id ) . sty {
111
+ forbid_unsigned_negation ( cx, e. span ) ;
112
+ }
113
+ } ,
114
+ _ => ( )
98
115
}
99
- } ;
116
+ } else {
117
+ let t = cx. tcx . node_id_to_type ( expr. id ) ;
118
+ if let ty:: TyUint ( _) = t. sty {
119
+ forbid_unsigned_negation ( cx, e. span ) ;
120
+ }
121
+ }
100
122
// propagate negation, if the negation itself isn't negated
101
123
if self . negated_expr_id != e. id {
102
124
self . negated_expr_id = expr. id ;
@@ -322,15 +344,11 @@ impl LateLintPass for TypeLimits {
322
344
}
323
345
}
324
346
325
- fn check_unsigned_negation_feature ( cx : & LateContext , span : Span ) {
326
- if !cx. sess ( ) . features . borrow ( ) . negate_unsigned {
327
- emit_feature_err (
328
- & cx. sess ( ) . parse_sess . span_diagnostic ,
329
- "negate_unsigned" ,
330
- span,
331
- GateIssue :: Language ,
332
- "unary negation of unsigned integers may be removed in the future" ) ;
333
- }
347
+ fn forbid_unsigned_negation ( cx : & LateContext , span : Span ) {
348
+ cx. sess ( )
349
+ . struct_span_err_with_code ( span, "unary negation of unsigned integer" , "E0519" )
350
+ . span_help ( span, "use a cast or the `!` operator" )
351
+ . emit ( ) ;
334
352
}
335
353
}
336
354
}
0 commit comments