From e7e8e790206a94ae96f7c6af944f789b77c7b93d Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sun, 10 Sep 2017 19:32:24 +0200 Subject: [PATCH] suggestion for ptr_arg --- clippy_lints/src/ptr.rs | 30 ++++++++++++++++++++++++------ clippy_lints/src/utils/mod.rs | 9 +++++++++ tests/ui/ptr_arg.stderr | 12 ++++++------ 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index f12ec039f73..4d119c3a42d 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -7,7 +7,8 @@ use rustc::ty; use syntax::ast::NodeId; use syntax::codemap::Span; use syntax_pos::MultiSpan; -use utils::{match_qpath, match_type, paths, span_lint, span_lint_and_then}; +use utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, + span_lint_and_sugg, walk_ptrs_hir_ty}; /// **What it does:** This lint checks for function arguments of type `&String` /// or `&Vec` unless @@ -137,20 +138,37 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { ) = ty.sty { if match_type(cx, ty, &paths::VEC) { - span_lint( + let mut ty_snippet = None; + if_let_chain!([ + let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node, + let Some(&PathSegment{ref parameters, ..}) = path.segments.last(), + parameters.types.len() == 1, + ], { + ty_snippet = snippet_opt(cx, parameters.types[0].span); + }); + //TODO: Suggestion + span_lint_and_then( cx, PTR_ARG, arg.span, "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ - with non-Vec-based slices. Consider changing the type to `&[...]`", + with non-Vec-based slices.", + |db| { + if let Some(ref snippet) = ty_snippet { + db.span_suggestion(arg.span, + "change this to", + format!("&[{}]", snippet)); + } + } ); } else if match_type(cx, ty, &paths::STRING) { - span_lint( + span_lint_and_sugg( cx, PTR_ARG, arg.span, - "writing `&String` instead of `&str` involves a new object where a slice will do. \ - Consider changing the type to `&str`", + "writing `&String` instead of `&str` involves a new object where a slice will do.", + "change this to", + "&str".to_string() ); } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 582cdae47b8..8e816ffbfa4 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -645,6 +645,15 @@ pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: Vec<(S db.suggestions.push(sugg); } +/// Return the base type for HIR references and pointers. +pub fn walk_ptrs_hir_ty(ty: &hir::Ty) -> &hir::Ty { + match ty.node { + TyPtr(ref mut_ty) | + TyRptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty), + _ => ty + } +} + /// Return the base type for references and raw pointers. pub fn walk_ptrs_ty(ty: Ty) -> Ty { match ty.sty { diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index bc5ca11155f..4eafc237a82 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,22 +1,22 @@ -error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. Consider changing the type to `&[...]` +error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. --> $DIR/ptr_arg.rs:6:14 | 6 | fn do_vec(x: &Vec) { - | ^^^^^^^^^ + | ^^^^^^^^^ help: change this to: `&[i64]` | = note: `-D ptr-arg` implied by `-D warnings` -error: writing `&String` instead of `&str` involves a new object where a slice will do. Consider changing the type to `&str` +error: writing `&String` instead of `&str` involves a new object where a slice will do. --> $DIR/ptr_arg.rs:14:14 | 14 | fn do_str(x: &String) { - | ^^^^^^^ + | ^^^^^^^ help: change this to: `&str` -error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. Consider changing the type to `&[...]` +error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. --> $DIR/ptr_arg.rs:27:18 | 27 | fn do_vec(x: &Vec); - | ^^^^^^^^^ + | ^^^^^^^^^ help: change this to: `&[i64]` error: aborting due to 3 previous errors