88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11+ #![ allow( non_snake_case) ]
12+
1113use middle:: { infer} ;
1214use middle:: def_id:: DefId ;
1315use middle:: subst:: Substs ;
@@ -24,13 +26,39 @@ use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
2426use syntax:: { abi, ast} ;
2527use syntax:: attr:: { self , AttrMetaMethods } ;
2628use syntax:: codemap:: { self , Span } ;
27- use syntax:: feature_gate:: { emit_feature_err, GateIssue } ;
2829use syntax:: ast:: { TyIs , TyUs , TyI8 , TyU8 , TyI16 , TyU16 , TyI32 , TyU32 , TyI64 , TyU64 } ;
2930
3031use rustc_front:: hir;
3132use rustc_front:: intravisit:: { self , Visitor } ;
3233use rustc_front:: util:: is_shift_binop;
3334
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+
3462declare_lint ! {
3563 UNUSED_COMPARISONS ,
3664 Warn ,
@@ -73,30 +101,24 @@ impl LateLintPass for TypeLimits {
73101 fn check_expr ( & mut self , cx : & LateContext , e : & hir:: Expr ) {
74102 match e. node {
75103 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+ _ => ( )
98115 }
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+ }
100122 // propagate negation, if the negation itself isn't negated
101123 if self . negated_expr_id != e. id {
102124 self . negated_expr_id = expr. id ;
@@ -322,15 +344,11 @@ impl LateLintPass for TypeLimits {
322344 }
323345 }
324346
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 ( ) ;
334352 }
335353 }
336354}
0 commit comments