diff options
3 files changed, 78 insertions, 1 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index d768e0bf63f..f1fd7ebfeba 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -3,7 +3,8 @@ use std::borrow::Cow; use std::path::PathBuf; use rustc_abi::ExternAbi; -use rustc_ast::TraitObjectSyntax; +use rustc_ast::ast::LitKind; +use rustc_ast::{LitIntType, TraitObjectSyntax}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; @@ -280,6 +281,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (suggested, noted_missing_impl) = self.try_conversion_context(&obligation, main_trait_predicate, &mut err); } + suggested |= self.detect_negative_literal( + &obligation, + main_trait_predicate, + &mut err, + ); + if let Some(ret_span) = self.return_type_span(&obligation) { if is_try_conversion { let ty = self.tcx.short_string( @@ -950,6 +957,38 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Ok(()) } + fn detect_negative_literal( + &self, + obligation: &PredicateObligation<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, + err: &mut Diag<'_>, + ) -> bool { + if let ObligationCauseCode::BinOp { lhs_hir_id, .. } = obligation.cause.code() + && let hir::Node::Expr(expr) = self.tcx.hir_node(*lhs_hir_id) + && let hir::ExprKind::Unary(hir::UnOp::Neg, inner) = expr.kind + && let hir::ExprKind::Lit(lit) = inner.kind + && let LitKind::Int(_, LitIntType::Unsuffixed) = lit.node + { + err.span_suggestion_verbose( + lit.span.shrink_to_hi(), + "consider specifying an integer type that can be negative", + match trait_pred.skip_binder().self_ty().kind() { + ty::Uint(ty::UintTy::Usize) => "isize", + ty::Uint(ty::UintTy::U8) => "i8", + ty::Uint(ty::UintTy::U16) => "i16", + ty::Uint(ty::UintTy::U32) => "i32", + ty::Uint(ty::UintTy::U64) => "i64", + ty::Uint(ty::UintTy::U128) => "i128", + _ => "i64", + } + .to_string(), + Applicability::MaybeIncorrect, + ); + return true; + } + false + } + /// When the `E` of the resulting `Result<T, E>` in an expression `foo().bar().baz()?`, /// identify those method chain sub-expressions that could or could not have been annotated /// with `?`. diff --git a/tests/ui/suggestions/negative-literal-infered-to-unsigned.rs b/tests/ui/suggestions/negative-literal-infered-to-unsigned.rs new file mode 100644 index 00000000000..39797574b97 --- /dev/null +++ b/tests/ui/suggestions/negative-literal-infered-to-unsigned.rs @@ -0,0 +1,13 @@ +fn main() { + for x in -5..5 { + //~^ ERROR: the trait bound `usize: Neg` is not satisfied + //~| HELP: consider specifying an integer type that can be negative + do_something(x); + } + let x = -5; + //~^ ERROR: the trait bound `usize: Neg` is not satisfied + //~| HELP: consider specifying an integer type that can be negative + do_something(x); +} + +fn do_something(_val: usize) {} diff --git a/tests/ui/suggestions/negative-literal-infered-to-unsigned.stderr b/tests/ui/suggestions/negative-literal-infered-to-unsigned.stderr new file mode 100644 index 00000000000..b49ea224d2b --- /dev/null +++ b/tests/ui/suggestions/negative-literal-infered-to-unsigned.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `usize: Neg` is not satisfied + --> $DIR/negative-literal-infered-to-unsigned.rs:2:14 + | +LL | for x in -5..5 { + | ^^ the trait `Neg` is not implemented for `usize` + | +help: consider specifying an integer type that can be negative + | +LL | for x in -5isize..5 { + | +++++ + +error[E0277]: the trait bound `usize: Neg` is not satisfied + --> $DIR/negative-literal-infered-to-unsigned.rs:7:13 + | +LL | let x = -5; + | ^^ the trait `Neg` is not implemented for `usize` + | +help: consider specifying an integer type that can be negative + | +LL | let x = -5isize; + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. |
