-Subproject commit 98589876259e19f13eab81b033ced95bbb6deca0
+Subproject commit 7d57bdcdbb56540f37afe5a934ce12d33a6ca7fc
use rustc_i128::{i128, u128};
-register_long_diagnostics! {
-E0519: r##"
-It is not allowed to negate an unsigned integer.
-You can negate a signed integer and cast it to an
-unsigned integer or use the `!` operator.
-
-```
-let x: usize = -1isize as usize;
-let y: usize = !0;
-assert_eq!(x, y);
-```
-
-Alternatively you can use the `Wrapping` newtype
-or the `wrapping_neg` operation that all
-integral types support:
-
-```
-use std::num::Wrapping;
-let x: Wrapping<usize> = -Wrapping(1);
-let Wrapping(x) = x;
-let y: usize = 1.wrapping_neg();
-assert_eq!(x, y);
-```
-"##
-}
-
declare_lint! {
UNUSED_COMPARISONS,
Warn,
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
match e.node {
hir::ExprUnary(hir::UnNeg, ref expr) => {
- if let hir::ExprLit(ref lit) = expr.node {
- match lit.node {
- ast::LitKind::Int(_, ast::LitIntType::Unsigned(_)) => {
- forbid_unsigned_negation(cx, e.span);
- }
- ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
- if let ty::TyUint(_) = cx.tcx.tables().node_id_to_type(e.id).sty {
- forbid_unsigned_negation(cx, e.span);
- }
- }
- _ => (),
- }
- } else {
- let t = cx.tcx.tables().node_id_to_type(expr.id);
- if let ty::TyUint(_) = t.sty {
- forbid_unsigned_negation(cx, e.span);
- }
- }
// propagate negation, if the negation itself isn't negated
if self.negated_expr_id != e.id {
self.negated_expr_id = expr.id;
_ => false,
}
}
-
- fn forbid_unsigned_negation(cx: &LateContext, span: Span) {
- cx.sess()
- .struct_span_err_with_code(span, "unary negation of unsigned integer", "E0519")
- .span_help(span, "use a cast or the `!` operator")
- .emit();
- }
}
}
hir::UnNot => {
oprnd_t = self.structurally_resolved_type(oprnd.span,
oprnd_t);
+ let result = self.check_user_unop("!", "not",
+ tcx.lang_items.not_trait(),
+ expr, &oprnd, oprnd_t, unop);
+ // If it's builtin, we can reuse the type, this helps inference.
if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
- oprnd_t = self.check_user_unop("!", "not",
- tcx.lang_items.not_trait(),
- expr, &oprnd, oprnd_t, unop);
+ oprnd_t = result;
}
}
hir::UnNeg => {
oprnd_t = self.structurally_resolved_type(oprnd.span,
oprnd_t);
+ let result = self.check_user_unop("-", "neg",
+ tcx.lang_items.neg_trait(),
+ expr, &oprnd, oprnd_t, unop);
+ // If it's builtin, we can reuse the type, this helps inference.
if !(oprnd_t.is_integral() || oprnd_t.is_fp()) {
- oprnd_t = self.check_user_unop("-", "neg",
- tcx.lang_items.neg_trait(),
- expr, &oprnd, oprnd_t, unop);
+ oprnd_t = result;
}
}
}
// as potentially overloaded. But then, during writeback, if
// we observe that something like `a+b` is (known to be)
// operating on scalars, we clear the overload.
- fn fix_scalar_binary_expr(&mut self, e: &hir::Expr) {
+ fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr) {
match e.node {
+ hir::ExprUnary(hir::UnNeg, ref inner) |
+ hir::ExprUnary(hir::UnNot, ref inner) => {
+ let inner_ty = self.fcx.node_ty(inner.id);
+ let inner_ty = self.fcx.resolve_type_vars_if_possible(&inner_ty);
+
+ if inner_ty.is_scalar() {
+ self.fcx.tables.borrow_mut().method_map.remove(&MethodCall::expr(e.id));
+ }
+ }
hir::ExprBinary(ref op, ref lhs, ref rhs) |
hir::ExprAssignOp(ref op, ref lhs, ref rhs) => {
let lhs_ty = self.fcx.node_ty(lhs.id);
return;
}
- self.fix_scalar_binary_expr(e);
+ self.fix_scalar_builtin_expr(e);
self.visit_node_id(ResolvingExpr(e.span), e.id);
self.visit_method_map_entry(ResolvingExpr(e.span),
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![allow(unused_imports)]
-
-// Note: the relevant lint pass here runs before some of the constant
-// evaluation below (e.g. that performed by trans and llvm), so if you
-// change this warn to a deny, then the compiler will exit before
-// those errors are detected.
-
-use std::fmt;
-use std::{i8, i16, i32, i64, isize};
-use std::{u8, u16, u32, u64, usize};
-
-const VALS_I8: (i8, i8, i8, i8) =
- (-i8::MIN,
- i8::MIN - 1,
- i8::MAX + 1,
- i8::MIN * 2,
- );
-
-const VALS_I16: (i16, i16, i16, i16) =
- (-i16::MIN,
- i16::MIN - 1,
- i16::MAX + 1,
- i16::MIN * 2,
- );
-
-const VALS_I32: (i32, i32, i32, i32) =
- (-i32::MIN,
- i32::MIN - 1,
- i32::MAX + 1,
- i32::MIN * 2,
- );
-
-const VALS_I64: (i64, i64, i64, i64) =
- (-i64::MIN,
- i64::MIN - 1,
- i64::MAX + 1,
- i64::MAX * 2,
- );
-
-const VALS_U8: (u8, u8, u8, u8) =
- (-u8::MIN,
- //~^ ERROR unary negation of unsigned integer
- //~| HELP use a cast or the `!` operator
- u8::MIN - 1,
- u8::MAX + 1,
- u8::MAX * 2,
- );
-
-const VALS_U16: (u16, u16, u16, u16) =
- (-u16::MIN,
- //~^ ERROR unary negation of unsigned integer
- //~| HELP use a cast or the `!` operator
- u16::MIN - 1,
- u16::MAX + 1,
- u16::MAX * 2,
- );
-
-const VALS_U32: (u32, u32, u32, u32) =
- (-u32::MIN,
- //~^ ERROR unary negation of unsigned integer
- //~| HELP use a cast or the `!` operator
- u32::MIN - 1,
- u32::MAX + 1,
- u32::MAX * 2,
- );
-
-const VALS_U64: (u64, u64, u64, u64) =
- (-u64::MIN,
- //~^ ERROR unary negation of unsigned integer
- //~| HELP use a cast or the `!` operator
- u64::MIN - 1,
- u64::MAX + 1,
- u64::MAX * 2,
- );
-
-fn main() {
- foo(VALS_I8);
- foo(VALS_I16);
- foo(VALS_I32);
- foo(VALS_I64);
-
- foo(VALS_U8);
- foo(VALS_U16);
- foo(VALS_U32);
- foo(VALS_U64);
-}
-
-fn foo<T:fmt::Debug>(x: T) {
- println!("{:?}", x);
-}
fn neg(self) -> u32 { 0 }
}
-// FIXME(eddyb) move this back to a `-1` literal when
-// MIR building stops eagerly erroring in that case.
-const _MAX: usize = -(2 - 1);
-//~^ WARN unary negation of unsigned integer
-//~| ERROR unary negation of unsigned integer
-//~| HELP use a cast or the `!` operator
-
fn main() {
+ let _max: usize = -1;
+ //~^ ERROR cannot apply unary operator `-` to type `usize`
+
let x = 5u8;
- let _y = -x; //~ ERROR unary negation of unsigned integer
- //~^ HELP use a cast or the `!` operator
+ let _y = -x;
+ //~^ ERROR cannot apply unary operator `-` to type `u8`
+
-S; // should not trigger the gate; issue 26840
}
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that negating unsigned integers doesn't compile
-
-struct S;
-impl std::ops::Neg for S {
- type Output = u32;
- fn neg(self) -> u32 { 0 }
-}
-
-fn main() {
- let a = -1;
- //~^ ERROR E0080
- //~| unary negation of unsigned integer
- let _b : u8 = a; // for infering variable a to u8.
-
- let _d = -1u8;
- //~^ ERROR E0080
- //~| unary negation of unsigned integer
-
- for _ in -10..10u8 {}
- //~^ ERROR E0080
- //~| unary negation of unsigned integer
-
- -S; // should not trigger the gate; issue 26840
-}