diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 8855859d7c4a..085424ef7e67 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -37,7 +37,9 @@ impl Emitter for EmitterWriter { if let Some(sugg) = db.suggestion.clone() { assert_eq!(sugg.msp.primary_spans().len(), sugg.substitutes.len()); - if sugg.substitutes.len() == 1 { + if sugg.substitutes.len() == 1 && // don't display multispans as labels + sugg.msg.split_whitespace().count() < 10 && // don't display long messages as labels + sugg.substitutes[0].find('\n').is_none() { // don't display multiline suggestions as labels let msg = format!("{} `{}`", sugg.msg, sugg.substitutes[0]); primary_span.push_span_label(sugg.msp.primary_spans()[0], msg); } else { diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 6968a37361a1..7d17cee98799 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -197,7 +197,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // error types are considered "builtin" if !lhs_ty.references_error() { if let IsAssign::Yes = is_assign { - struct_span_err!(self.tcx.sess, lhs_expr.span, E0368, + struct_span_err!(self.tcx.sess, expr.span, E0368, "binary assignment operation `{}=` \ cannot be applied to type `{}`", op.node.as_str(), @@ -207,7 +207,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { op.node.as_str(), lhs_ty)) .emit(); } else { - let mut err = struct_span_err!(self.tcx.sess, lhs_expr.span, E0369, + let mut err = struct_span_err!(self.tcx.sess, expr.span, E0369, "binary operation `{}` cannot be applied to type `{}`", op.node.as_str(), lhs_ty); @@ -244,7 +244,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(missing_trait) = missing_trait { if missing_trait == "std::ops::Add" && - self.check_str_addition(lhs_expr, lhs_ty, + self.check_str_addition(expr, lhs_expr, lhs_ty, rhs_expr, rhs_ty_var, &mut err) { // This has nothing here because it means we did string // concatenation (e.g. "Hello " + "World!"). This means @@ -266,6 +266,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } fn check_str_addition(&self, + expr: &'gcx hir::Expr, lhs_expr: &'gcx hir::Expr, lhs_ty: Ty<'tcx>, rhs_expr: &'gcx hir::Expr, @@ -277,7 +278,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let TyRef(_, l_ty) = lhs_ty.sty { if let TyRef(_, r_ty) = rhs_ty.sty { if l_ty.ty.sty == TyStr && r_ty.ty.sty == TyStr { - err.note("`+` can't be used to concatenate two `&str` strings"); + err.span_label(expr.span, + &"`+` can't be used to concatenate two `&str` strings"); let codemap = self.tcx.sess.codemap(); let suggestion = match codemap.span_to_snippet(lhs_expr.span) { @@ -289,7 +291,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { from a string reference. String concatenation \ appends the string on the right to the string \ on the left and may require reallocation. This \ - requires ownership of the string on the left:"), suggestion); + requires ownership of the string on the left."), suggestion); is_string_addition = true; } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 2bae6a0d9e11..54637269bc02 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -3181,6 +3181,13 @@ x << 2; // ok! It is also possible to overload most operators for your own type by implementing traits from `std::ops`. + +String concatenation appends the string on the right to the string on the +left and may require reallocation. This requires ownership of the string +on the left. If something should be added to a string literal, move the +literal to the heap by allocating it with `to_owned()` like in +`"Your text".to_owned()`. + "##, E0370: r##" diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 53656d8c6c21..e1fe8f1b2eb3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5160,9 +5160,7 @@ impl<'a> Parser<'a> { `pub(in path::to::module)`: visible only on the specified path"##; let path = self.parse_path(PathStyle::Mod)?; let path_span = self.prev_span; - let help_msg = format!("to make this visible only to module `{}`, add `in` before \ - the path:", - path); + let help_msg = format!("make this visible only to module `{}` with `in`:", path); self.expect(&token::CloseDelim(token::Paren))?; // `)` let mut err = self.span_fatal_help(path_span, &msg, &suggestion); err.span_suggestion(path_span, &help_msg, format!("in {}", path)); diff --git a/src/test/ui/pub/pub-restricted.stderr b/src/test/ui/pub/pub-restricted.stderr index 7bee1791eab4..760df5b5da01 100644 --- a/src/test/ui/pub/pub-restricted.stderr +++ b/src/test/ui/pub/pub-restricted.stderr @@ -2,7 +2,7 @@ error: incorrect visibility restriction --> $DIR/pub-restricted.rs:15:6 | 15 | pub (a) fn afn() {} - | ^ to make this visible only to module `a`, add `in` before the path: `in a` + | ^ make this visible only to module `a` with `in`: `in a` | = help: some possible visibility restrictions are: `pub(crate)`: visible only on the current crate @@ -13,7 +13,7 @@ error: incorrect visibility restriction --> $DIR/pub-restricted.rs:16:6 | 16 | pub (b) fn bfn() {} - | ^ to make this visible only to module `b`, add `in` before the path: `in b` + | ^ make this visible only to module `b` with `in`: `in b` | = help: some possible visibility restrictions are: `pub(crate)`: visible only on the current crate @@ -24,7 +24,7 @@ error: incorrect visibility restriction --> $DIR/pub-restricted.rs:32:14 | 32 | pub (a) invalid: usize, - | ^ to make this visible only to module `a`, add `in` before the path: `in a` + | ^ make this visible only to module `a` with `in`: `in a` | = help: some possible visibility restrictions are: `pub(crate)`: visible only on the current crate @@ -35,7 +35,7 @@ error: incorrect visibility restriction --> $DIR/pub-restricted.rs:41:6 | 41 | pub (xyz) fn xyz() {} - | ^^^ to make this visible only to module `xyz`, add `in` before the path: `in xyz` + | ^^^ make this visible only to module `xyz` with `in`: `in xyz` | = help: some possible visibility restrictions are: `pub(crate)`: visible only on the current crate diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index b588238202e1..cd3a41b037c7 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -2,15 +2,16 @@ error[E0369]: binary operation `+` cannot be applied to type `&'static str` --> $DIR/issue-39018.rs:12:13 | 12 | let x = "Hello " + "World!"; - | ^^^^^^^^ `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left: `"Hello ".to_owned()` + | ^^^^^^^^^^^^^^^^^^^ `+` can't be used to concatenate two `&str` strings | - = note: `+` can't be used to concatenate two `&str` strings +help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + | let x = "Hello ".to_owned() + "World!"; error[E0369]: binary operation `+` cannot be applied to type `World` --> $DIR/issue-39018.rs:17:13 | 17 | let y = World::Hello + World::Goodbye; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: an implementation of `std::ops::Add` might be missing for `World`