about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPhilipp Hansch <dev@phansch.net>2018-10-05 07:18:24 +0200
committerPhilipp Hansch <dev@phansch.net>2018-10-05 07:18:24 +0200
commit1544a1a681d4f7ab909f8e89c64d1b14bc7a7337 (patch)
tree45c141cad594caf81486ea4d02caa7e328336a65
parent8b3d2073fa8b1f48a27081944c1a7010a8d7b7b1 (diff)
parenteb2cfe62b523c34dc2ec5990b0113001c936db7e (diff)
downloadrust-1544a1a681d4f7ab909f8e89c64d1b14bc7a7337.tar.gz
rust-1544a1a681d4f7ab909f8e89c64d1b14bc7a7337.zip
Merge remote-tracking branch 'origin/master' into relicense-rewrite
-rw-r--r--.travis.yml6
-rw-r--r--clippy_lints/src/format.rs35
-rw-r--r--clippy_lints/src/methods/mod.rs18
-rw-r--r--clippy_lints/src/utils/mod.rs3
-rw-r--r--src/driver.rs1
-rw-r--r--tests/ui/format.rs12
-rw-r--r--tests/ui/format.stderr38
-rw-r--r--tests/ui/wrong_self_convention.rs1
8 files changed, 79 insertions, 35 deletions
diff --git a/.travis.yml b/.travis.yml
index 948eb23fe83..8aff93d480a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -57,11 +57,9 @@ script:
       export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib
   - |
     if [ -z ${INTEGRATION} ]; then
-      ./ci/base-tests.sh
-      sleep 5
+      ./ci/base-tests.sh && sleep 5
     else
-      ./ci/integration-tests.sh
-      sleep 5
+      ./ci/integration-tests.sh && sleep 5
     fi
 
 after_success: |
diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs
index 2eb95ebffbf..7e2e355c251 100644
--- a/clippy_lints/src/format.rs
+++ b/clippy_lints/src/format.rs
@@ -4,7 +4,6 @@ use crate::rustc::{declare_tool_lint, lint_array};
 use if_chain::if_chain;
 use crate::rustc::ty;
 use crate::syntax::ast::LitKind;
-use crate::syntax_pos::Span;
 use crate::utils::paths;
 use crate::utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty};
 use crate::rustc_errors::Applicability;
@@ -47,7 +46,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
                 return;
             }
             match expr.node {
-
                 // `format!("{}", foo)` expansion
                 ExprKind::Call(ref fun, ref args) => {
                     if_chain! {
@@ -58,12 +56,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
                         if check_single_piece(&args[0]);
                         if let Some(format_arg) = get_single_string_arg(cx, &args[1]);
                         if check_unformatted(&args[2]);
+                        if let ExprKind::AddrOf(_, ref format_arg) = format_arg.node;
                         then {
-                            let sugg = format!("{}.to_string()", snippet(cx, format_arg, "<arg>").into_owned());
+                            let (message, sugg) = if_chain! {
+                                if let ExprKind::MethodCall(ref path, _, _) = format_arg.node;
+                                if path.ident.as_interned_str() == "to_string";
+                                then {
+                                    ("`to_string()` is enough",
+                                    snippet(cx, format_arg.span, "<arg>").to_string())
+                                } else {
+                                    ("consider using .to_string()",
+                                    format!("{}.to_string()", snippet(cx, format_arg.span, "<arg>")))
+                                }
+                            };
+
                             span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| {
                                 db.span_suggestion_with_applicability(
                                     expr.span,
-                                    "consider using .to_string()",
+                                    message,
                                     sugg,
                                     Applicability::MachineApplicable,
                                 );
@@ -114,9 +124,9 @@ fn check_single_piece(expr: &Expr) -> bool {
 /// ::std::fmt::Display::fmt)],
 /// }
 /// ```
-/// and that type of `__arg0` is `&str` or `String`
-/// then returns the span of first element of the matched tuple
-fn get_single_string_arg(cx: &LateContext<'_, '_>, expr: &Expr) -> Option<Span> {
+/// and that the type of `__arg0` is `&str` or `String`,
+/// then returns the span of first element of the matched tuple.
+fn get_single_string_arg<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<&'a Expr> {
     if_chain! {
         if let ExprKind::AddrOf(_, ref expr) = expr.node;
         if let ExprKind::Match(ref match_expr, ref arms, _) = expr.node;
@@ -135,7 +145,7 @@ fn get_single_string_arg(cx: &LateContext<'_, '_>, expr: &Expr) -> Option<Span>
             let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0]));
             if ty.sty == ty::Str || match_type(cx, ty, &paths::STRING) {
                 if let ExprKind::Tup(ref values) = match_expr.node {
-                    return Some(values[0].span);
+                    return Some(&values[0]);
                 }
             }
         }
@@ -162,9 +172,12 @@ fn check_unformatted(expr: &Expr) -> bool {
         if let ExprKind::Struct(_, ref fields, _) = exprs[0].node;
         if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format");
         if let ExprKind::Struct(_, ref fields, _) = format_field.expr.node;
-        if let Some(align_field) = fields.iter().find(|f| f.ident.name == "width");
-        if let ExprKind::Path(ref qpath) = align_field.expr.node;
-        if last_path_segment(qpath).ident.name == "Implied";
+        if let Some(width_field) = fields.iter().find(|f| f.ident.name == "width");
+        if let ExprKind::Path(ref width_qpath) = width_field.expr.node;
+        if last_path_segment(width_qpath).ident.name == "Implied";
+        if let Some(precision_field) = fields.iter().find(|f| f.ident.name == "precision");
+        if let ExprKind::Path(ref precision_path) = precision_field.expr.node;
+        if last_path_segment(precision_path).ident.name == "Implied";
         then {
             return true;
         }
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 2524152a120..e0d858bd270 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -882,12 +882,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
                 let ty = cx.tcx.type_of(def_id);
                 let is_copy = is_copy(cx, ty);
                 for &(ref conv, self_kinds) in &CONVENTIONS {
-                    if_chain! {
-                        if conv.check(&name.as_str());
+                    if conv.check(&name.as_str()) {
                         if !self_kinds
-                            .iter()
-                            .any(|k| k.matches(cx, first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics));
-                        then {
+                                .iter()
+                                .any(|k| k.matches(cx, first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics)) {
                             let lint = if item.vis.node.is_pub() {
                                 WRONG_PUB_SELF_CONVENTION
                             } else {
@@ -904,6 +902,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
                                                           .collect::<Vec<_>>()
                                                           .join(" or ")));
                         }
+
+                        // Only check the first convention to match (CONVENTIONS should be listed from most to least specific)
+                        break;
                     }
                 }
 
@@ -1183,8 +1184,8 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp
                         Applicability::MaybeIncorrect,
                     );
                     db.span_suggestion_with_applicability(
-                        expr.span, 
-                        "or try being explicit about what type to clone", 
+                        expr.span,
+                        "or try being explicit about what type to clone",
                         explicit,
                         Applicability::MaybeIncorrect,
                     );
@@ -2067,12 +2068,13 @@ enum Convention {
 }
 
 #[rustfmt::skip]
-const CONVENTIONS: [(Convention, &[SelfKind]); 6] = [
+const CONVENTIONS: [(Convention, &[SelfKind]); 7] = [
     (Convention::Eq("new"), &[SelfKind::No]),
     (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]),
     (Convention::StartsWith("from_"), &[SelfKind::No]),
     (Convention::StartsWith("into_"), &[SelfKind::Value]),
     (Convention::StartsWith("is_"), &[SelfKind::Ref, SelfKind::No]),
+    (Convention::Eq("to_mut"), &[SelfKind::RefMut]),
     (Convention::StartsWith("to_"), &[SelfKind::Ref]),
 ];
 
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index 0011065db67..fa3c72dbb7d 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -72,6 +72,7 @@ pub fn in_macro(span: Span) -> bool {
 pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> bool {
     use crate::syntax::symbol;
 
+    #[derive(Debug)]
     struct AbsolutePathBuffer {
         names: Vec<symbol::LocalInternedString>,
     }
@@ -89,7 +90,7 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) ->
 
     let mut apb = AbsolutePathBuffer { names: vec![] };
 
-    tcx.push_item_path(&mut apb, def_id);
+    tcx.push_item_path(&mut apb, def_id, false);
 
     apb.names.len() == path.len()
         && apb.names
diff --git a/src/driver.rs b/src/driver.rs
index 99f8bc610ff..6c442e42d95 100644
--- a/src/driver.rs
+++ b/src/driver.rs
@@ -21,6 +21,7 @@ fn show_version() {
 }
 
 pub fn main() {
+    rustc_driver::init_rustc_env_logger();
     exit(rustc_driver::run(move || {
         use std::env;
 
diff --git a/tests/ui/format.rs b/tests/ui/format.rs
index 8f31d92ac3c..858c9fc8de5 100644
--- a/tests/ui/format.rs
+++ b/tests/ui/format.rs
@@ -14,6 +14,7 @@ fn main() {
     format!("{}", "foo");
     format!("{:?}", "foo"); // don't warn about debug
     format!("{:8}", "foo");
+    format!("{:width$}", "foo", width = 8);
     format!("{:+}", "foo"); // warn when the format makes no difference
     format!("{:<}", "foo"); // warn when the format makes no difference
     format!("foo {}", "bar");
@@ -23,6 +24,7 @@ fn main() {
     format!("{}", arg);
     format!("{:?}", arg); // don't warn about debug
     format!("{:8}", arg);
+    format!("{:width$}", arg, width = 8);
     format!("{:+}", arg); // warn when the format makes no difference
     format!("{:<}", arg); // warn when the format makes no difference
     format!("foo {}", arg);
@@ -44,4 +46,14 @@ fn main() {
 
     // A format! inside a macro should not trigger a warning
     foo!("should not warn");
+
+    // precision on string means slicing without panicking on size:
+    format!("{:.1}", "foo"); // could be "foo"[..1]
+    format!("{:.10}", "foo"); // could not be "foo"[..10]
+    format!("{:.prec$}", "foo", prec = 1);
+    format!("{:.prec$}", "foo", prec = 10);
+
+    format!("{}", 42.to_string());
+    let x = std::path::PathBuf::from("/bar/foo/qux");
+    format!("{}", x.display().to_string());
 }
diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr
index ca6ef905396..520c1b79433 100644
--- a/tests/ui/format.stderr
+++ b/tests/ui/format.stderr
@@ -15,44 +15,60 @@ error: useless use of `format!`
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: useless use of `format!`
-  --> $DIR/format.rs:17:5
+  --> $DIR/format.rs:18:5
    |
-17 |     format!("{:+}", "foo"); // warn when the format makes no difference
+18 |     format!("{:+}", "foo"); // warn when the format makes no difference
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()`
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: useless use of `format!`
-  --> $DIR/format.rs:18:5
+  --> $DIR/format.rs:19:5
    |
-18 |     format!("{:<}", "foo"); // warn when the format makes no difference
+19 |     format!("{:<}", "foo"); // warn when the format makes no difference
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `"foo".to_string()`
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: useless use of `format!`
-  --> $DIR/format.rs:23:5
+  --> $DIR/format.rs:24:5
    |
-23 |     format!("{}", arg);
+24 |     format!("{}", arg);
    |     ^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()`
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: useless use of `format!`
-  --> $DIR/format.rs:26:5
+  --> $DIR/format.rs:28:5
    |
-26 |     format!("{:+}", arg); // warn when the format makes no difference
+28 |     format!("{:+}", arg); // warn when the format makes no difference
    |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()`
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: useless use of `format!`
-  --> $DIR/format.rs:27:5
+  --> $DIR/format.rs:29:5
    |
-27 |     format!("{:<}", arg); // warn when the format makes no difference
+29 |     format!("{:<}", arg); // warn when the format makes no difference
    |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using .to_string(): `arg.to_string()`
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
-error: aborting due to 7 previous errors
+error: useless use of `format!`
+  --> $DIR/format.rs:56:5
+   |
+56 |     format!("{}", 42.to_string());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `42.to_string()`
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: useless use of `format!`
+  --> $DIR/format.rs:58:5
+   |
+58 |     format!("{}", x.display().to_string());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `to_string()` is enough: `x.display().to_string()`
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 9 previous errors
 
diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs
index 1e718c1c648..2fb33d08619 100644
--- a/tests/ui/wrong_self_convention.rs
+++ b/tests/ui/wrong_self_convention.rs
@@ -59,4 +59,5 @@ impl Bar {
     fn is_(self) {}
     fn to_(self) {}
     fn from_(self) {}
+    fn to_mut(&mut self) {}
 }