diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index c3dfca44349eb..21b5714037749 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -104,11 +104,11 @@ impl LateLintPass for TypeLimits { if let hir::ExprLit(ref lit) = expr.node { match lit.node { ast::LitInt(_, ast::UnsignedIntLit(_)) => { - forbid_unsigned_negation(cx, e.span); + forbid_unsigned_negation(cx, e.span, lit.span); }, ast::LitInt(_, ast::UnsuffixedIntLit(_)) => { if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty { - forbid_unsigned_negation(cx, e.span); + forbid_unsigned_negation(cx, e.span, lit.span); } }, _ => () @@ -116,7 +116,7 @@ impl LateLintPass for TypeLimits { } else { let t = cx.tcx.node_id_to_type(expr.id); if let ty::TyUint(_) = t.sty { - forbid_unsigned_negation(cx, e.span); + forbid_unsigned_negation(cx, e.span, expr.span); } } // propagate negation, if the negation itself isn't negated @@ -344,11 +344,18 @@ impl LateLintPass for TypeLimits { } } - 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(); + fn forbid_unsigned_negation(cx: &LateContext, span: Span, lit_span: Span) { + let mut err = cx.sess() + .struct_span_err_with_code(span, + "unary negation of unsigned integer", + "E0519"); + if let Ok(snip) = cx.sess().codemap().span_to_snippet(lit_span) { + err.span_suggestion(span, "try using a cast or the `!` operator:", + format!("!{}", snip)); + } else { + err.span_help(span, "use a cast or the `!` operator"); + } + err.emit(); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8464d3ef29870..60fd8cbbd9510 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -420,12 +420,22 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, name) } ResolutionError::StructVariantUsedAsFunction(path_name) => { - struct_span_err!(resolver.session, - span, - E0423, - "`{}` is the name of a struct or struct variant, but this expression \ - uses it like a function name", - path_name) + let mut err = struct_span_err!(resolver.session, + span, + E0423, + "`{}` is the name of a struct or \ + struct variant, but this expression \ + uses it like a function name", + path_name); + if resolver.emit_errors { + let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?", + path_name); + err.fileline_help(span, &msg); + } else { + let suggestion = format!("{} {{ /* fields */ }}", path_name); + err.span_suggestion(span, "did you mean to write", suggestion); + } + err } ResolutionError::SelfNotAvailableInStaticMethod => { struct_span_err!(resolver.session, @@ -3521,18 +3531,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let DefVariant(_, _, true) = path_res.base_def { let path_name = path_names_to_string(path, 0); - let mut err = resolve_struct_error(self, - expr.span, - ResolutionError::StructVariantUsedAsFunction(&*path_name)); + resolve_error(self, expr.span, + ResolutionError::StructVariantUsedAsFunction(&*path_name)); - let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?", - path_name); - if self.emit_errors { - err.fileline_help(expr.span, &msg); - } else { - err.span_help(expr.span, &msg); - } - err.emit(); self.record_def(expr.id, err_path_resolution()); } else { // Write the result into the def map. @@ -3562,18 +3563,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(expr.id, err_path_resolution()); match type_res.map(|r| r.base_def) { Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => { - let mut err = resolve_struct_error(self, - expr.span, - ResolutionError::StructVariantUsedAsFunction(&*path_name)); - - let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?", - path_name); - if self.emit_errors { - err.fileline_help(expr.span, &msg); - } else { - err.span_help(expr.span, &msg); - } - err.emit(); + resolve_error(self, expr.span, + ResolutionError::StructVariantUsedAsFunction(&*path_name)); } _ => { // Keep reporting some errors even if they're ignored above. diff --git a/src/test/compile-fail/feature-gate-negate-unsigned.rs b/src/test/compile-fail/feature-gate-negate-unsigned.rs index 15cc17b19db33..6b9cd8b5132b0 100644 --- a/src/test/compile-fail/feature-gate-negate-unsigned.rs +++ b/src/test/compile-fail/feature-gate-negate-unsigned.rs @@ -18,25 +18,29 @@ impl std::ops::Neg for S { const _MAX: usize = -1; //~^ ERROR unary negation of unsigned integer -//~| HELP use a cast or the `!` operator +//~| HELP try using a cast or the `!` operator fn main() { let a = -1; //~^ ERROR unary negation of unsigned integer - //~| HELP use a cast or the `!` operator + //~| HELP try using a cast or the `!` operator + //~| SUGGESTION let a = !1; let _b : u8 = a; // for infering variable a to u8. -a; //~^ ERROR unary negation of unsigned integer - //~| HELP use a cast or the `!` operator + //~| HELP try using a cast or the `!` operator + //~| SUGGESTION !a let _d = -1u8; //~^ ERROR unary negation of unsigned integer - //~| HELP use a cast or the `!` operator + //~| HELP try using a cast or the `!` operator + //~| SUGGESTION let _d = !1u8; for _ in -10..10u8 {} //~^ ERROR unary negation of unsigned integer - //~| HELP use a cast or the `!` operator + //~| HELP try using a cast or the `!` operator + //~| SUGGESTION for _ in !10..10u8 {} -S; // should not trigger the gate; issue 26840 }