From ced11a83cb6cae998df514eb08d1f3dc4bd990c8 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Mon, 5 Oct 2020 12:23:36 -0400 Subject: [PATCH] suggest `MAX` constant if -1 is assigned to unsigned type --- compiler/rustc_typeck/src/check/op.rs | 25 +++++++++++++ .../feature-gate-negate-unsigned.stderr | 5 ++- src/test/ui/unsigned-literal-negation.rs | 5 +++ src/test/ui/unsigned-literal-negation.stderr | 36 +++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/unsigned-literal-negation.rs create mode 100644 src/test/ui/unsigned-literal-negation.stderr diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 66975f32a1f..2f3fb49717b 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -2,6 +2,7 @@ use super::method::MethodCallee; use super::FnCtxt; +use rustc_ast as ast; use rustc_errors::{self, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -13,6 +14,7 @@ use rustc_middle::ty::TyKind::{Adt, Array, Char, FnDef, Never, Ref, Str, Tuple, use rustc_middle::ty::{ self, suggest_constraining_type_param, Ty, TyCtxt, TypeFoldable, TypeVisitor, }; +use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; @@ -673,6 +675,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match actual.kind() { Uint(_) if op == hir::UnOp::UnNeg => { err.note("unsigned values cannot be negated"); + + if let hir::ExprKind::Unary( + _, + hir::Expr { + kind: + hir::ExprKind::Lit(Spanned { + node: ast::LitKind::Int(1, _), + .. + }), + .. + }, + ) = ex.kind + { + err.span_suggestion( + ex.span, + &format!( + "you may have meant the maximum value of `{}`", + actual + ), + format!("{}::MAX", actual), + Applicability::MaybeIncorrect, + ); + } } Str | Never | Char | Tuple(_) | Array(_, _) => {} Ref(_, ref lty, _) if *lty.kind() == Str => {} diff --git a/src/test/ui/feature-gates/feature-gate-negate-unsigned.stderr b/src/test/ui/feature-gates/feature-gate-negate-unsigned.stderr index aa84c27e40f..d1f4ed5cb04 100644 --- a/src/test/ui/feature-gates/feature-gate-negate-unsigned.stderr +++ b/src/test/ui/feature-gates/feature-gate-negate-unsigned.stderr @@ -2,7 +2,10 @@ error[E0600]: cannot apply unary operator `-` to type `usize` --> $DIR/feature-gate-negate-unsigned.rs:10:23 | LL | let _max: usize = -1; - | ^^ cannot apply unary operator `-` + | ^^ + | | + | cannot apply unary operator `-` + | help: you may have meant the maximum value of `usize`: `usize::MAX` | = note: unsigned values cannot be negated diff --git a/src/test/ui/unsigned-literal-negation.rs b/src/test/ui/unsigned-literal-negation.rs new file mode 100644 index 00000000000..943c7f79742 --- /dev/null +++ b/src/test/ui/unsigned-literal-negation.rs @@ -0,0 +1,5 @@ +fn main() { + let x = -1 as usize; //~ ERROR: cannot apply unary operator `-` + let x = (-1) as usize; //~ ERROR: cannot apply unary operator `-` + let x: u32 = -1; //~ ERROR: cannot apply unary operator `-` +} diff --git a/src/test/ui/unsigned-literal-negation.stderr b/src/test/ui/unsigned-literal-negation.stderr new file mode 100644 index 00000000000..0aaa8c3b72f --- /dev/null +++ b/src/test/ui/unsigned-literal-negation.stderr @@ -0,0 +1,36 @@ +error[E0600]: cannot apply unary operator `-` to type `usize` + --> $DIR/unsigned-literal-negation.rs:2:13 + | +LL | let x = -1 as usize; + | ^^ + | | + | cannot apply unary operator `-` + | help: you may have meant the maximum value of `usize`: `usize::MAX` + | + = note: unsigned values cannot be negated + +error[E0600]: cannot apply unary operator `-` to type `usize` + --> $DIR/unsigned-literal-negation.rs:3:13 + | +LL | let x = (-1) as usize; + | ^^^^ + | | + | cannot apply unary operator `-` + | help: you may have meant the maximum value of `usize`: `usize::MAX` + | + = note: unsigned values cannot be negated + +error[E0600]: cannot apply unary operator `-` to type `u32` + --> $DIR/unsigned-literal-negation.rs:4:18 + | +LL | let x: u32 = -1; + | ^^ + | | + | cannot apply unary operator `-` + | help: you may have meant the maximum value of `u32`: `u32::MAX` + | + = note: unsigned values cannot be negated + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0600`.