false
}
+ /// Provide actionable suggestions when trying to add two strings with incorrect types,
+ /// like `&str + &str`, `String + String` and `&str + &String`.
+ ///
+ /// If this function returns `true` it means a note was printed, so we don't need
+ /// to print the normal "implementation of `std::ops::Add` might be missing" note
fn check_str_addition(
&self,
expr: &'gcx hir::Expr,
op: hir::BinOp,
) -> bool {
let source_map = self.tcx.sess.source_map();
+ 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";
- // If this function returns true it means a note was printed, so we don't need
- // to print the normal "implementation of `std::ops::Add` might be missing" note
+ debug!("check_str_addition: {:?} + {:?}", lhs_ty, rhs_ty);
match (&lhs_ty.sty, &rhs_ty.sty) {
- (&Ref(_, l_ty, _), &Ref(_, r_ty, _))
- if l_ty.sty == Str && r_ty.sty == Str => {
+ (&Ref(_, l_ty, _), &Ref(_, r_ty, _)) // &str or &String + &str, &String or &&str
+ if (l_ty.sty == Str || &format!("{:?}", l_ty) == "std::string::String") && (
+ r_ty.sty == Str ||
+ &format!("{:?}", r_ty) == "std::string::String" ||
+ &format!("{:?}", rhs_ty) == "&&str"
+ ) =>
+ {
if !is_assign {
- err.span_label(op.span,
- "`+` can't be used to concatenate two `&str` strings");
+ err.span_label(
+ op.span,
+ "`+` can't be used to concatenate two `&str` strings",
+ );
match source_map.span_to_snippet(lhs_expr.span) {
- Ok(lstring) => err.span_suggestion(
- lhs_expr.span,
- msg,
- format!("{}.to_owned()", lstring),
- Applicability::MachineApplicable,
- ),
+ Ok(lstring) => {
+ err.span_suggestion(
+ lhs_expr.span,
+ if lstring.starts_with("&") {
+ remove_borrow_msg
+ } else {
+ msg
+ },
+ if lstring.starts_with("&") {
+ // let a = String::new();
+ // let _ = &a + "bar";
+ format!("{}", &lstring[1..])
+ } else {
+ format!("{}.to_owned()", lstring)
+ },
+ Applicability::MachineApplicable,
+ )
+ }
_ => err.help(msg),
};
}
true
}
- (&Ref(_, l_ty, _), &Adt(..))
- if l_ty.sty == Str && &format!("{:?}", rhs_ty) == "std::string::String" => {
+ (&Ref(_, l_ty, _), &Adt(..)) // Handle `&str` & `&String` + `String`
+ if (l_ty.sty == Str || &format!("{:?}", l_ty) == "std::string::String") &&
+ &format!("{:?}", rhs_ty) == "std::string::String" =>
+ {
err.span_label(expr.span,
"`+` can't be used to concatenate a `&str` with a `String`");
match (
Hello,
Goodbye,
}
+
+fn foo() {
+ let a = String::new();
+ let b = String::new();
+ let c = "";
+ let d = "";
+ let e = &a;
+ let _ = &a + &b; //~ ERROR binary operation
+ let _ = &a + b; //~ ERROR binary operation
+ let _ = a + &b; // ok
+ let _ = a + b; //~ ERROR mismatched types
+ let _ = e + b; //~ ERROR binary operation
+ let _ = e + &b; //~ ERROR binary operation
+ let _ = e + d; //~ ERROR binary operation
+ let _ = e + &d; //~ ERROR binary operation
+ let _ = &c + &d; //~ ERROR binary operation
+ let _ = &c + d; //~ ERROR binary operation
+ let _ = c + &d; //~ ERROR binary operation
+ let _ = c + d; //~ ERROR binary operation
+}
LL | let x = "Hello ".to_owned() + &"World!".to_owned();
| ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+ --> $DIR/issue-39018.rs:26:16
+ |
+LL | let _ = &a + &b;
+ | -- ^ -- &std::string::String
+ | | |
+ | | `+` can't be used to concatenate two `&str` strings
+ | &std::string::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;
+ | ^
+
+error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+ --> $DIR/issue-39018.rs:27:16
+ |
+LL | let _ = &a + b;
+ | ---^--
+ | | |
+ | | std::string::String
+ | &std::string::String
+ | `+` can't be used to concatenate a `&str` with a `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
+ |
+LL | let _ = &a.to_owned() + &b;
+ | ^^^^^^^^^^^^^ ^^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-39018.rs:29:17
+ |
+LL | let _ = a + b;
+ | ^
+ | |
+ | expected &str, found struct `std::string::String`
+ | help: consider borrowing here: `&b`
+ |
+ = note: expected type `&str`
+ found type `std::string::String`
+
+error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+ --> $DIR/issue-39018.rs:30:15
+ |
+LL | let _ = e + b;
+ | --^--
+ | | |
+ | | std::string::String
+ | &std::string::String
+ | `+` can't be used to concatenate a `&str` with a `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
+ |
+LL | let _ = e.to_owned() + &b;
+ | ^^^^^^^^^^^^ ^^
+
+error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+ --> $DIR/issue-39018.rs:31:15
+ |
+LL | let _ = e + &b;
+ | - ^ -- &std::string::String
+ | | |
+ | | `+` can't be used to concatenate two `&str` strings
+ | &std::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
+ |
+LL | let _ = e.to_owned() + &b;
+ | ^^^^^^^^^^^^
+
+error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+ --> $DIR/issue-39018.rs:32:15
+ |
+LL | let _ = e + d;
+ | - ^ - &str
+ | | |
+ | | `+` can't be used to concatenate two `&str` strings
+ | &std::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
+ |
+LL | let _ = e.to_owned() + d;
+ | ^^^^^^^^^^^^
+
+error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+ --> $DIR/issue-39018.rs:33:15
+ |
+LL | let _ = e + &d;
+ | - ^ -- &&str
+ | | |
+ | | `+` can't be used to concatenate two `&str` strings
+ | &std::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
+ |
+LL | let _ = e.to_owned() + &d;
+ | ^^^^^^^^^^^^
+
+error[E0369]: binary operation `+` cannot be applied to type `&&str`
+ --> $DIR/issue-39018.rs:34:16
+ |
+LL | let _ = &c + &d;
+ | -- ^ -- &&str
+ | |
+ | &&str
+ |
+ = note: an implementation of `std::ops::Add` might be missing for `&&str`
+
+error[E0369]: binary operation `+` cannot be applied to type `&&str`
+ --> $DIR/issue-39018.rs:35:16
+ |
+LL | let _ = &c + d;
+ | -- ^ - &str
+ | |
+ | &&str
+ |
+ = note: an implementation of `std::ops::Add` might be missing for `&&str`
+
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+ --> $DIR/issue-39018.rs:36:15
+ |
+LL | let _ = c + &d;
+ | - ^ -- &&str
+ | | |
+ | | `+` can't 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
+ |
+LL | let _ = c.to_owned() + &d;
+ | ^^^^^^^^^^^^
+
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+ --> $DIR/issue-39018.rs:37:15
+ |
+LL | let _ = c + d;
+ | - ^ - &str
+ | | |
+ | | `+` can't 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
+ |
+LL | let _ = c.to_owned() + d;
+ | ^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
-For more information about this error, try `rustc --explain E0369`.
+Some errors have detailed explanations: E0308, E0369.
+For more information about an error, try `rustc --explain E0308`.
|
LL | let c = a + b;
| - ^ - &str
- | |
+ | | |
+ | | `+` can't be used to concatenate two `&str` strings
| &std::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
|
- = note: an implementation of `std::ops::Add` might be missing for `&std::string::String`
+LL | let c = a.to_owned() + b;
+ | ^^^^^^^^^^^^
error: aborting due to previous error