From 66a3ce78b44faf317c6b3c69fc66b6a75f99743d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 15 May 2019 15:56:47 -0700 Subject: [PATCH 1/8] Update books --- src/ci/docker/x86_64-gnu-tools/checktools.sh | 4 +++- src/doc/book | 2 +- src/doc/edition-guide | 2 +- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-guide | 2 +- 8 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index af0198705a2fe..a0fe307cffcdb 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -74,7 +74,9 @@ status_check() { check_dispatch $1 beta nomicon src/doc/nomicon check_dispatch $1 beta reference src/doc/reference check_dispatch $1 beta rust-by-example src/doc/rust-by-example - check_dispatch $1 beta edition-guide src/doc/edition-guide + # Temporarily disabled until + # https://github.com/rust-lang/rust/issues/60459 is fixed. + # check_dispatch $1 beta edition-guide src/doc/edition-guide check_dispatch $1 beta rls src/tools/rls check_dispatch $1 beta rustfmt src/tools/rustfmt check_dispatch $1 beta clippy-driver src/tools/clippy diff --git a/src/doc/book b/src/doc/book index db919bc6bb907..29fe982990e43 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit db919bc6bb9071566e9c4f05053672133eaac33e +Subproject commit 29fe982990e43b9367be0ff47abc82fb2123fd03 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index c413d42a207bd..581c6cccfaf99 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit c413d42a207bd082f801ec0137c31b71e4bfed4c +Subproject commit 581c6cccfaf995394ea9dcac362dc8e731c18558 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index de3d55f521e65..9858872bd1b7d 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit de3d55f521e657863df45260ebbca1b10527f662 +Subproject commit 9858872bd1b7dbba5ec27dc30d34eba00acd7ef9 diff --git a/src/doc/nomicon b/src/doc/nomicon index fb29b147be4d9..c656171b749b7 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit fb29b147be4d9a1f8e24aba753a7e1de537abf61 +Subproject commit c656171b749b7307f21371dd0d3278efee5573b8 diff --git a/src/doc/reference b/src/doc/reference index 2a2de9ce09597..862b669c39582 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 2a2de9ce095979978ad7b582daecf94e4070b916 +Subproject commit 862b669c395822bb0938781d74f860e5762ad4fb diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 1ff0f8e018838..811c697b232c6 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 1ff0f8e018838a710ebc0cc1a7bf74ebe73ad9f1 +Subproject commit 811c697b232c611ed754d279ed20643a0c4096f6 diff --git a/src/doc/rustc-guide b/src/doc/rustc-guide index 99e1b1d53656b..3cb727b62b953 160000 --- a/src/doc/rustc-guide +++ b/src/doc/rustc-guide @@ -1 +1 @@ -Subproject commit 99e1b1d53656be08654df399fc200584aebb50e4 +Subproject commit 3cb727b62b953d59b4360d39aa68b6dc8f157655 From 441ecb88e791cd156f1753a44c70d79f40315326 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 16 May 2019 22:22:18 +0200 Subject: [PATCH 2/8] Allow claiming issues with triagebot --- triagebot.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 6f60481600c2e..0e703a3ab349d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -4,3 +4,5 @@ allow-unauthenticated = [ # I-* without I-nominated "I-compilemem", "I-compiletime", "I-crash", "I-hang", "I-ICE", "I-slow", ] + +[assign] From 234adf84bd834146c76b98dd4328e05a4bf7900b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 May 2019 19:29:02 -0700 Subject: [PATCH 3/8] Handle more string addition cases with appropriate suggestions --- src/librustc_typeck/check/op.rs | 57 +++++-- src/test/ui/span/issue-39018.rs | 20 +++ src/test/ui/span/issue-39018.stderr | 143 +++++++++++++++++- .../ui/str/str-concat-on-double-ref.stderr | 7 +- 4 files changed, 209 insertions(+), 18 deletions(-) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index d1ca05780930a..1913850c94c7e 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -502,6 +502,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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, @@ -514,33 +519,57 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 ( diff --git a/src/test/ui/span/issue-39018.rs b/src/test/ui/span/issue-39018.rs index 6dbc8d39976ad..a3b1d1d81799f 100644 --- a/src/test/ui/span/issue-39018.rs +++ b/src/test/ui/span/issue-39018.rs @@ -16,3 +16,23 @@ enum World { 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 +} diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index a5b91f090d2c0..2f48abcaf3339 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -35,6 +35,145 @@ help: `to_owned()` can be used to create an owned `String` from a string referen 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`. 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 61ebcfdefc316..17d9475b9c07d 100644 --- a/src/test/ui/str/str-concat-on-double-ref.stderr +++ b/src/test/ui/str/str-concat-on-double-ref.stderr @@ -3,10 +3,13 @@ error[E0369]: binary operation `+` cannot be applied to type `&std::string::Stri | 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 From e836a4cd79c8b7f6ba8ea93c6da29e7b803116f3 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 16 May 2019 19:48:13 -0700 Subject: [PATCH 4/8] Prevent Error::type_id overrides type_id now takes an argument that can't be named outside of the std::error module, which prevents any implementations from overriding it. It's a pretty grody solution, and there's no way we can stabilize the method with this API, but it avoids the soudness issue! Closes #60784 --- src/libstd/error.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 7cb830e751a77..d2aa2195a35ed 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -201,11 +201,19 @@ pub trait Error: Debug + Display { #[unstable(feature = "error_type_id", reason = "this is memory unsafe to override in user code", issue = "60784")] - fn type_id(&self) -> TypeId where Self: 'static { + fn type_id(&self, _: private::Internal) -> TypeId where Self: 'static { TypeId::of::() } } +mod private { + // this is a hack to prevent type_id from being overridden by Error + // implementations, since that can enable unsound downcasting. + #[unstable(feature = "error_type_id", issue = "60784")] + #[derive(Debug)] + pub struct Internal; +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + 'a> From for Box { /// Converts a type of [`Error`] into a box of dyn [`Error`]. @@ -575,7 +583,7 @@ impl dyn Error + 'static { let t = TypeId::of::(); // Get TypeId of the type in the trait object - let boxed = self.type_id(); + let boxed = self.type_id(private::Internal); // Compare both TypeIds on equality t == boxed From 2cb91816f24a096a0760a49b6b4095309098e7f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 May 2019 19:56:11 -0700 Subject: [PATCH 5/8] Fix binop span --- src/librustc_typeck/check/op.rs | 17 +++++++++-------- src/libsyntax/parse/parser.rs | 3 +-- src/test/ui/span/issue-39018.stderr | 21 +++++++++------------ 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 1913850c94c7e..619900b6ad903 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -305,8 +305,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if let Some(missing_trait) = missing_trait { if op.node == hir::BinOpKind::Add && - self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty, - rhs_ty, &mut err, true, op) { + self.check_str_addition( + lhs_expr, rhs_expr, lhs_ty, rhs_ty, &mut err, true, op) { // This has nothing here because it means we did string // concatenation (e.g., "Hello " += "World!"). This means // we don't want the note in the else clause to be emitted @@ -400,8 +400,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if let Some(missing_trait) = missing_trait { if op.node == hir::BinOpKind::Add && - self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty, - rhs_ty, &mut err, false, op) { + self.check_str_addition( + lhs_expr, rhs_expr, lhs_ty, rhs_ty, &mut err, false, op) { // This has nothing here because it means we did string // concatenation (e.g., "Hello " + "World!"). This means // we don't want the note in the else clause to be emitted @@ -509,7 +509,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// to print the normal "implementation of `std::ops::Add` might be missing" note fn check_str_addition( &self, - expr: &'gcx hir::Expr, lhs_expr: &'gcx hir::Expr, rhs_expr: &'gcx hir::Expr, lhs_ty: Ty<'tcx>, @@ -537,7 +536,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &format!("{:?}", rhs_ty) == "&&str" ) => { - if !is_assign { + if !is_assign { // Do not supply this message if `&str += &str` err.span_label( op.span, "`+` can't be used to concatenate two `&str` strings", @@ -570,8 +569,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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`"); + err.span_label( + op.span, + "`+` can't be used to concatenate a `&str` with a `String`", + ); match ( source_map.span_to_snippet(lhs_expr.span), source_map.span_to_snippet(rhs_expr.span), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 99e8db9d8e6d2..a80fe4b2fd8e5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3540,8 +3540,7 @@ impl<'a> Parser<'a> { let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs); self.mk_expr(span, binary, ThinVec::new()) } - AssocOp::Assign => - self.mk_expr(span, ExprKind::Assign(lhs, rhs), ThinVec::new()), + AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs), ThinVec::new()), AssocOp::ObsoleteInPlace => self.mk_expr(span, ExprKind::ObsoleteInPlace(lhs, rhs), ThinVec::new()), AssocOp::AssignOp(k) => { diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index 2f48abcaf3339..b174e95c8a1d4 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -25,11 +25,10 @@ error[E0369]: binary operation `+` cannot be applied to type `&str` --> $DIR/issue-39018.rs:11:22 | LL | let x = "Hello " + "World!".to_owned(); - | ---------^-------------------- - | | | - | | std::string::String + | -------- ^ ------------------- std::string::String + | | | + | | `+` can't be used to concatenate a `&str` with a `String` | &str - | `+` 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 x = "Hello ".to_owned() + &"World!".to_owned(); @@ -52,11 +51,10 @@ error[E0369]: binary operation `+` cannot be applied to type `&std::string::Stri --> $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` | &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; @@ -78,11 +76,10 @@ error[E0369]: binary operation `+` cannot be applied to type `&std::string::Stri --> $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` | &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; From 686a611b9e19b487a70fccc960ea0e16e71de988 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 16 May 2019 20:18:29 -0700 Subject: [PATCH 6/8] Update src/libstd/error.rs Co-Authored-By: Mazdak Farrokhzad --- src/libstd/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index d2aa2195a35ed..62282006a4024 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -207,7 +207,7 @@ pub trait Error: Debug + Display { } mod private { - // this is a hack to prevent type_id from being overridden by Error + // This is a hack to prevent `type_id` from being overridden by `Error` // implementations, since that can enable unsound downcasting. #[unstable(feature = "error_type_id", issue = "60784")] #[derive(Debug)] From ee0bf5e6aa7a964bb5c776adba0faad087a6a425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 May 2019 20:05:00 -0700 Subject: [PATCH 7/8] review comments --- src/librustc_typeck/check/op.rs | 20 +++++++++---------- src/test/ui/issues/issue-47377.stderr | 2 +- src/test/ui/issues/issue-47380.stderr | 2 +- src/test/ui/span/issue-39018.stderr | 20 +++++++++---------- .../ui/str/str-concat-on-double-ref.stderr | 2 +- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 619900b6ad903..26a5bdfef7d66 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -527,19 +527,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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"; - debug!("check_str_addition: {:?} + {:?}", lhs_ty, rhs_ty); + + let is_std_string = |ty| &format!("{:?}", ty) == "std::string::String"; + match (&lhs_ty.sty, &rhs_ty.sty) { (&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 (l_ty.sty == Str || is_std_string(l_ty)) && ( + r_ty.sty == Str || is_std_string(r_ty) || + &format!("{:?}", rhs_ty) == "&&str" + ) => { if !is_assign { // Do not supply this message if `&str += &str` err.span_label( op.span, - "`+` can't be used to concatenate two `&str` strings", + "`+` cannot be used to concatenate two `&str` strings", ); match source_map.span_to_snippet(lhs_expr.span) { Ok(lstring) => { @@ -566,12 +567,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { true } (&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" => + if (l_ty.sty == Str || is_std_string(l_ty)) && is_std_string(rhs_ty) => { err.span_label( op.span, - "`+` can't be used to concatenate a `&str` with a `String`", + "`+` cannot be used to concatenate a `&str` with a `String`", ); match ( source_map.span_to_snippet(lhs_expr.span), diff --git a/src/test/ui/issues/issue-47377.stderr b/src/test/ui/issues/issue-47377.stderr index 88466131e3144..7d11a8c802128 100644 --- a/src/test/ui/issues/issue-47377.stderr +++ b/src/test/ui/issues/issue-47377.stderr @@ -4,7 +4,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&str` LL | let _a = b + ", World!"; | - ^ ---------- &str | | | - | | `+` can't be used to concatenate two `&str` strings + | | `+` 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 | diff --git a/src/test/ui/issues/issue-47380.stderr b/src/test/ui/issues/issue-47380.stderr index d69101eab4c46..89a154c5109d8 100644 --- a/src/test/ui/issues/issue-47380.stderr +++ b/src/test/ui/issues/issue-47380.stderr @@ -4,7 +4,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&str` LL | println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!"; | - ^ ---------- &str | | | - | | `+` can't be used to concatenate two `&str` strings + | | `+` 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 | diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index b174e95c8a1d4..cdb9c1168d8e7 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -4,7 +4,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&str` LL | let x = "Hello " + "World!"; | -------- ^ -------- &str | | | - | | `+` can't be used to concatenate two `&str` strings + | | `+` 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 | @@ -27,7 +27,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&str` LL | let x = "Hello " + "World!".to_owned(); | -------- ^ ------------------- std::string::String | | | - | | `+` can't be used to concatenate a `&str` with a `String` + | | `+` 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 | @@ -40,7 +40,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&std::string::Stri LL | let _ = &a + &b; | -- ^ -- &std::string::String | | | - | | `+` can't be used to concatenate two `&str` strings + | | `+` cannot 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 | @@ -53,7 +53,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&std::string::Stri LL | let _ = &a + b; | -- ^ - std::string::String | | | - | | `+` can't be used to concatenate a `&str` with a `String` + | | `+` cannot be used to concatenate a `&str` with a `String` | &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 | @@ -78,7 +78,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&std::string::Stri LL | let _ = e + b; | - ^ - std::string::String | | | - | | `+` can't be used to concatenate a `&str` with a `String` + | | `+` cannot be used to concatenate a `&str` with a `String` | &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 | @@ -91,7 +91,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&std::string::Stri LL | let _ = e + &b; | - ^ -- &std::string::String | | | - | | `+` can't be used to concatenate two `&str` strings + | | `+` cannot 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 | @@ -104,7 +104,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&std::string::Stri LL | let _ = e + d; | - ^ - &str | | | - | | `+` can't be used to concatenate two `&str` strings + | | `+` cannot 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 | @@ -117,7 +117,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&std::string::Stri LL | let _ = e + &d; | - ^ -- &&str | | | - | | `+` can't be used to concatenate two `&str` strings + | | `+` cannot 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 | @@ -150,7 +150,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&str` LL | let _ = c + &d; | - ^ -- &&str | | | - | | `+` can't be used to concatenate two `&str` strings + | | `+` 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 | @@ -163,7 +163,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&str` LL | let _ = c + d; | - ^ - &str | | | - | | `+` can't be used to concatenate two `&str` strings + | | `+` 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 | 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 17d9475b9c07d..3e53cdc4d98ca 100644 --- a/src/test/ui/str/str-concat-on-double-ref.stderr +++ b/src/test/ui/str/str-concat-on-double-ref.stderr @@ -4,7 +4,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&std::string::Stri LL | let c = a + b; | - ^ - &str | | | - | | `+` can't be used to concatenate two `&str` strings + | | `+` cannot 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 | From 8895fb945d0ea0ce124923aadc16adb68c74f3e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 17 May 2019 10:45:54 -0700 Subject: [PATCH 8/8] Account for &String + String --- src/librustc_typeck/check/op.rs | 9 ++++++++- src/test/ui/span/issue-39018.stderr | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 26a5bdfef7d66..cd207478f8f6f 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -579,10 +579,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { is_assign, ) { (Ok(l), Ok(r), false) => { + let to_string = if l.starts_with("&") { + // let a = String::new(); let b = String::new(); + // let _ = &a + b; + format!("{}", &l[1..]) + } else { + format!("{}.to_owned()", l) + }; err.multipart_suggestion( msg, vec![ - (lhs_expr.span, format!("{}.to_owned()", l)), + (lhs_expr.span, to_string), (rhs_expr.span, format!("&{}", r)), ], Applicability::MachineApplicable, diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index cdb9c1168d8e7..d8fbf841b6157 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -57,8 +57,8 @@ LL | let _ = &a + b; | &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 _ = &a.to_owned() + &b; - | ^^^^^^^^^^^^^ ^^ +LL | let _ = a + &b; + | ^ ^^ error[E0308]: mismatched types --> $DIR/issue-39018.rs:29:17