diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 838f8b0a61d..8bb0613f456 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -549,15 +549,11 @@ fn check_str_addition( is_assign: IsAssign, op: hir::BinOp, ) -> bool { - let remove_borrow_msg = "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 msg = "`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 str_concat_note = "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 rm_borrow_msg = "remove the borrow to obtain an owned `String`"; + let to_owned_msg = "use `to_owned()` to create an owned `String` from a string reference"; let string_type = self.tcx.get_diagnostic_item(sym::String); let is_std_string = |ty: Ty<'tcx>| match ty.ty_adt_def() { @@ -574,17 +570,18 @@ fn check_str_addition( { if let IsAssign::No = is_assign { // Do not supply this message if `&str += &str` err.span_label(op.span, "`+` cannot be used to concatenate two `&str` strings"); + err.note(str_concat_note); if let hir::ExprKind::AddrOf(_,_,lhs_inner_expr) = lhs_expr.kind { err.span_suggestion( lhs_expr.span.until(lhs_inner_expr.span), - remove_borrow_msg, + rm_borrow_msg, "".to_owned(), Applicability::MachineApplicable ); } else { err.span_suggestion( lhs_expr.span.shrink_to_hi(), - msg, + to_owned_msg, ".to_owned()".to_owned(), Applicability::MachineApplicable ); @@ -601,18 +598,22 @@ fn check_str_addition( ); match is_assign { IsAssign::No => { + let sugg_msg; + let lhs_sugg = if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { + sugg_msg = "remove the borrow on the left and add one on the right"; + (lhs_expr.span.until(lhs_inner_expr.span), "".to_owned()) + } else { + sugg_msg = "call `.to_owned()` on the left and add a borrow on the right"; + (lhs_expr.span.shrink_to_hi(), ".to_owned()".to_owned()) + }; let suggestions = vec![ - if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { - (lhs_expr.span.until(lhs_inner_expr.span), "".to_owned()) - } else { - (lhs_expr.span.shrink_to_hi(), ".to_owned()".to_owned()) - }, + lhs_sugg, (rhs_expr.span.shrink_to_lo(), "&".to_owned()), ]; - err.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable); + err.multipart_suggestion(sugg_msg, suggestions, Applicability::MachineApplicable); } IsAssign::Yes => { - err.help(msg); + err.note(str_concat_note); } } true diff --git a/src/test/ui/issues/issue-47377.stderr b/src/test/ui/issues/issue-47377.stderr index 2c17a19779f..2e00de84087 100644 --- a/src/test/ui/issues/issue-47377.stderr +++ b/src/test/ui/issues/issue-47377.stderr @@ -7,7 +7,8 @@ LL | let _a = b + ", World!"; | | `+` cannot be used to concatenate two `&str` strings | &str | -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 + = note: 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. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _a = b.to_owned() + ", World!"; | +++++++++++ diff --git a/src/test/ui/issues/issue-47380.stderr b/src/test/ui/issues/issue-47380.stderr index 417206e6cc4..fec64009444 100644 --- a/src/test/ui/issues/issue-47380.stderr +++ b/src/test/ui/issues/issue-47380.stderr @@ -7,7 +7,8 @@ LL | println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!"; | | `+` cannot be used to concatenate two `&str` strings | &str | -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 + = note: 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. +help: use `to_owned()` to create an owned `String` from a string reference | LL | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!"; | +++++++++++ diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index 444d037571e..9054dd931ca 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -7,7 +7,8 @@ LL | let x = "Hello " + "World!"; | | `+` cannot be used to concatenate two `&str` strings | &str | -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 + = note: 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. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let x = "Hello ".to_owned() + "World!"; | +++++++++++ @@ -46,7 +47,7 @@ LL | let x = "Hello " + "World!".to_owned(); | | `+` cannot be used to concatenate a `&str` with a `String` | &str | -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 +help: call `.to_owned()` on the left and add a borrow on the right | LL | let x = "Hello ".to_owned() + &"World!".to_owned(); | +++++++++++ + @@ -59,12 +60,9 @@ LL | let _ = &a + &b; | | | | | `+` cannot be used to concatenate two `&str` strings | &String + | help: remove the borrow to obtain an owned `String` | -help: 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 - | -LL - let _ = &a + &b; -LL + let _ = a + &b; - | + = note: 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. error[E0369]: cannot add `String` to `&String` --> $DIR/issue-39018.rs:27:16 @@ -75,7 +73,7 @@ LL | let _ = &a + b; | | `+` cannot be used to concatenate a `&str` with a `String` | &String | -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 +help: remove the borrow on the left and add one on the right | LL - let _ = &a + b; LL + let _ = a + &b; @@ -99,7 +97,7 @@ LL | let _ = e + b; | | `+` cannot be used to concatenate a `&str` with a `String` | &String | -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 +help: call `.to_owned()` on the left and add a borrow on the right | LL | let _ = e.to_owned() + &b; | +++++++++++ + @@ -113,7 +111,8 @@ LL | let _ = e + &b; | | `+` cannot be used to concatenate two `&str` strings | &String | -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 + = note: 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. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = e.to_owned() + &b; | +++++++++++ @@ -127,7 +126,8 @@ LL | let _ = e + d; | | `+` cannot be used to concatenate two `&str` strings | &String | -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 + = note: 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. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = e.to_owned() + d; | +++++++++++ @@ -141,7 +141,8 @@ LL | let _ = e + &d; | | `+` cannot be used to concatenate two `&str` strings | &String | -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 + = note: 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. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = e.to_owned() + &d; | +++++++++++ @@ -171,7 +172,8 @@ LL | let _ = c + &d; | | `+` cannot be used to concatenate two `&str` strings | &str | -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 + = note: 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. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = c.to_owned() + &d; | +++++++++++ @@ -185,7 +187,8 @@ LL | let _ = c + d; | | `+` cannot be used to concatenate two `&str` strings | &str | -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 + = note: 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. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = c.to_owned() + d; | +++++++++++ diff --git a/src/test/ui/str/str-concat-on-double-ref.stderr b/src/test/ui/str/str-concat-on-double-ref.stderr index cc9456be901..e8b5c2bbd85 100644 --- a/src/test/ui/str/str-concat-on-double-ref.stderr +++ b/src/test/ui/str/str-concat-on-double-ref.stderr @@ -7,7 +7,8 @@ LL | let c = a + b; | | `+` cannot be used to concatenate two `&str` strings | &String | -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 + = note: 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. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let c = a.to_owned() + b; | +++++++++++ diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr index 2da3db4a7fa..72005a88980 100644 --- a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr +++ b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr @@ -7,7 +7,8 @@ LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔ | | `+` cannot be used to concatenate two `&str` strings | &str | -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 + = note: 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. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; | +++++++++++