From 1431fc04afe4e7cc2110fc9e9a59b0976b5e64ff Mon Sep 17 00:00:00 2001 From: Jonathan Castello Date: Wed, 24 Dec 2014 15:15:22 -0800 Subject: [PATCH 1/3] Implement a lint to check for args like `fn foo(ref x: u8)`, as the `ref` is effectively ignored by rustc. --- src/lib.rs | 5 +++-- src/misc.rs | 26 +++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 386e8180c22..9ac74eb2320 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,8 @@ -#![feature(globs, phase, plugin_registrar)] +#![feature(globs, phase, plugin_registrar)] #![allow(unused_imports)] -#[phase(plugin,link)] +#[phase(plugin, link)] extern crate syntax; #[phase(plugin, link)] extern crate rustc; @@ -21,4 +21,5 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_lint_pass(box types::TypePass as LintPassObject); reg.register_lint_pass(box misc::MiscPass as LintPassObject); reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); + reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); } diff --git a/src/misc.rs b/src/misc.rs index 68195994907..47e8733abfb 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,6 +1,7 @@ use syntax::ptr::P; use syntax::ast; use syntax::ast::*; +use syntax::visit::{FnKind}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::middle::ty::{mod, expr_ty, ty_str, ty_ptr, ty_rptr}; use syntax::codemap::Span; @@ -38,7 +39,7 @@ impl LintPass for MiscPass { format!("Try if let {} = {} {{ ... }}", map.span_to_snippet(arms[0].pats[0].span).unwrap_or("..".to_string()), map.span_to_snippet(ex.span).unwrap_or("..".to_string())).as_slice() - ); + ); } } } @@ -81,3 +82,26 @@ impl LintPass for StrToStringPass { } } } + + +declare_lint!(CLIPPY_TOPLEVEL_REF_ARG, Warn, "Warn about pattern matches with top-level `ref` bindings"); + +pub struct TopLevelRefPass; + +impl LintPass for TopLevelRefPass { + fn get_lints(&self) -> LintArray { + lint_array!(CLIPPY_TOPLEVEL_REF_ARG) + } + + fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) { + for ref arg in decl.inputs.iter() { + if let PatIdent(BindByRef(_), _, _) = arg.pat.node { + cx.span_lint( + CLIPPY_TOPLEVEL_REF_ARG, + arg.pat.span, + "`ref` directly on a function argument is ignored. Have you considered using a reference type instead?" + ); + } + } + } +} From 8770f794674dd2af61159b4fef889e6257bfdd8b Mon Sep 17 00:00:00 2001 From: Jonathan Castello Date: Wed, 24 Dec 2014 17:48:03 -0800 Subject: [PATCH 2/3] Add an example of the toplevel_ref_arg lint. --- examples/toplevel_ref_arg.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 examples/toplevel_ref_arg.rs diff --git a/examples/toplevel_ref_arg.rs b/examples/toplevel_ref_arg.rs new file mode 100644 index 00000000000..0be737f9028 --- /dev/null +++ b/examples/toplevel_ref_arg.rs @@ -0,0 +1,14 @@ +#![feature(phase)] + +#[phase(plugin)] +extern crate rust_clippy; + +fn the_answer(ref mut x: u8) { + *x = 42; +} + +fn main() { + let mut x = 0; + the_answer(x); + println!("The answer is {}.", x); +} From a7d5048d48d54f691a10552a49e4b9bef89e89b0 Mon Sep 17 00:00:00 2001 From: Jonathan Castello Date: Wed, 24 Dec 2014 18:37:50 -0800 Subject: [PATCH 3/3] Update README.md for `clippy_toplevel_ref_arg`. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 91caaeba41a..3d5e366f56d 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Lints included in this crate: - `clippy_box_vec`: Warns on usage of `Box>` - `clippy_dlist`: Warns on usage of `DList` - `clippy_str_to_string`: Warns on usage of `str::to_string()` + - `clippy_toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`). More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas!