Skip to content

Commit

Permalink
Fix macro expansion in toplevel_ref_arg lint
Browse files Browse the repository at this point in the history
  • Loading branch information
tesuji committed Sep 26, 2019
1 parent 3b9e5df commit 11fadcf
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 14 deletions.
30 changes: 17 additions & 13 deletions clippy_lints/src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,36 +261,40 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
}
}

fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) {
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
if_chain! {
if let StmtKind::Local(ref l) = s.node;
if let PatKind::Binding(an, .., i, None) = l.pat.node;
if let Some(ref init) = l.init;
if let StmtKind::Local(ref local) = stmt.node;
if let PatKind::Binding(an, .., name, None) = local.pat.node;
if let Some(ref init) = local.init;
then {
if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut {
let sugg_init = Sugg::hir(cx, init, "..");
let (mutopt,initref) = if an == BindingAnnotation::RefMut {
let sugg_init = if init.span.from_expansion() {
Sugg::hir_with_macro_callsite(cx, init, "..")
} else {
Sugg::hir(cx, init, "..")
};
let (mutopt, initref) = if an == BindingAnnotation::RefMut {
("mut ", sugg_init.mut_addr())
} else {
("", sugg_init.addr())
};
let tyopt = if let Some(ref ty) = l.ty {
let tyopt = if let Some(ref ty) = local.ty {
format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, "_"))
} else {
String::new()
};
span_lint_hir_and_then(cx,
TOPLEVEL_REF_ARG,
init.hir_id,
l.pat.span,
local.pat.span,
"`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead",
|db| {
db.span_suggestion(
s.span,
stmt.span,
"try",
format!(
"let {name}{tyopt} = {initref};",
name=snippet(cx, i.span, "_"),
name=snippet(cx, name.span, "_"),
tyopt=tyopt,
initref=initref,
),
Expand All @@ -302,19 +306,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
}
};
if_chain! {
if let StmtKind::Semi(ref expr) = s.node;
if let StmtKind::Semi(ref expr) = stmt.node;
if let ExprKind::Binary(ref binop, ref a, ref b) = expr.node;
if binop.node == BinOpKind::And || binop.node == BinOpKind::Or;
if let Some(sugg) = Sugg::hir_opt(cx, a);
then {
span_lint_and_then(cx,
SHORT_CIRCUIT_STATEMENT,
s.span,
stmt.span,
"boolean short circuit operator in statement may be clearer using an explicit test",
|db| {
let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg };
db.span_suggestion(
s.span,
stmt.span,
"replace it with",
format!(
"if {} {{ {}; }}",
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/toplevel_ref_arg.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ fn main() {
let (ref x, _) = (1, 2); // ok, not top level
println!("The answer is {}.", x);

let x = &vec![1, 2, 3];

// Make sure that allowing the lint works
#[allow(clippy::toplevel_ref_arg)]
let ref mut x = 1_234_543;
Expand Down
8 changes: 7 additions & 1 deletion tests/ui/toplevel_ref_arg.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,11 @@ error: `ref` on an entire `let` pattern is discouraged, take a reference with `&
LL | let ref mut z = 1 + 2;
| ----^^^^^^^^^--------- help: try: `let z = &mut (1 + 2);`

error: aborting due to 4 previous errors
error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
--> $DIR/toplevel_ref_arg.rs:22:9
|
LL | let ref x = vec![1, 2, 3];
| ----^^^^^----------------- help: try: `let x = &vec![1, 2, 3];`

error: aborting due to 5 previous errors

0 comments on commit 11fadcf

Please sign in to comment.