From ad9ad6f402e3e15706519e59ef111a941d28d5af Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 17:42:57 +1200 Subject: [PATCH 001/526] Don't negate resulted offsets when `offset` is subtraction by 0 --- clippy_lints/src/loops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index cb44eccae68..f16b98883b8 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -960,8 +960,8 @@ fn detect_manual_memcpy<'a, 'tcx>( let print_sum = |arg1: &Offset, arg2: &Offset| -> String { match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { ("0", _, "0", _) => "".into(), - ("0", _, x, false) | (x, false, "0", false) => x.into(), - ("0", _, x, true) | (x, false, "0", true) => format!("-{}", x), + ("0", _, x, false) | (x, false, "0", _) => x.into(), + ("0", _, x, true) => format!("-{}", x), (x, false, y, false) => format!("({} + {})", x, y), (x, false, y, true) => { if x == y { From 37261a904ce2fbd4137180500c57f75f29945828 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 17:51:01 +1200 Subject: [PATCH 002/526] Print 0 when `end` and `offset` is 0, and also simplify the suggestion --- clippy_lints/src/loops.rs | 15 ++++++++++++--- tests/ui/manual_memcpy.stderr | 4 ++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f16b98883b8..6b5a8498dc9 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -959,7 +959,7 @@ fn detect_manual_memcpy<'a, 'tcx>( if let PatKind::Binding(_, canonical_id, _, _) = pat.kind { let print_sum = |arg1: &Offset, arg2: &Offset| -> String { match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { - ("0", _, "0", _) => "".into(), + ("0", _, "0", _) => "0".into(), ("0", _, x, false) | (x, false, "0", _) => x.into(), ("0", _, x, true) => format!("-{}", x), (x, false, y, false) => format!("({} + {})", x, y), @@ -981,6 +981,15 @@ fn detect_manual_memcpy<'a, 'tcx>( } }; + let print_offset = |start_str: &Offset, inline_offset: &Offset| -> String { + let offset = print_sum(start_str, inline_offset); + if offset.as_str() == "0" { + "".into() + } else { + offset + } + }; + let print_limit = |end: &Option<&Expr<'_>>, offset: Offset, var_name: &str| { if let Some(end) = *end { if_chain! { @@ -1020,9 +1029,9 @@ fn detect_manual_memcpy<'a, 'tcx>( .into_iter() .map(|(dst_var, src_var)| { let start_str = Offset::positive(snippet(cx, start.span, "").to_string()); - let dst_offset = print_sum(&start_str, &dst_var.offset); + let dst_offset = print_offset(&start_str, &dst_var.offset); let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); - let src_offset = print_sum(&start_str, &src_var.offset); + let src_offset = print_offset(&start_str, &src_var.offset); let src_limit = print_limit(end, src_var.offset, &src_var.var_name); let dst = if dst_offset == "" && dst_limit == "" { dst_var.var_name diff --git a/tests/ui/manual_memcpy.stderr b/tests/ui/manual_memcpy.stderr index 3dbb2155d4d..ec80f6070d6 100644 --- a/tests/ui/manual_memcpy.stderr +++ b/tests/ui/manual_memcpy.stderr @@ -58,13 +58,13 @@ error: it looks like you're manually copying between slices --> $DIR/manual_memcpy.rs:94:14 | LL | for i in from..from + src.len() { - | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[..(from + src.len() - from)])` error: it looks like you're manually copying between slices --> $DIR/manual_memcpy.rs:98:14 | LL | for i in from..from + 3 { - | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` + | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[..(from + 3 - from)])` error: it looks like you're manually copying between slices --> $DIR/manual_memcpy.rs:105:14 From 75ad839cd26c1da17fe6ba3aae1153ee96de26c8 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 18:04:37 +1200 Subject: [PATCH 003/526] Do not trigger `manual_memcpy` for `RangeTo` --- clippy_lints/src/loops.rs | 52 ++++++++++++++++------------------- tests/ui/manual_memcpy.rs | 5 ++++ tests/ui/manual_memcpy.stderr | 2 +- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6b5a8498dc9..ca61c97e3e3 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -951,7 +951,7 @@ fn detect_manual_memcpy<'a, 'tcx>( ) { if let Some(higher::Range { start: Some(start), - ref end, + end: Some(end), limits, }) = higher::range(cx, arg) { @@ -990,35 +990,31 @@ fn detect_manual_memcpy<'a, 'tcx>( } }; - let print_limit = |end: &Option<&Expr<'_>>, offset: Offset, var_name: &str| { - if let Some(end) = *end { - if_chain! { - if let ExprKind::MethodCall(ref method, _, ref len_args) = end.kind; - if method.ident.name == sym!(len); - if len_args.len() == 1; - if let Some(arg) = len_args.get(0); - if snippet(cx, arg.span, "??") == var_name; - then { - return if offset.negate { - format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value) - } else { - String::new() - }; - } + let print_limit = |end: &Expr<'_>, offset: Offset, var_name: &str| { + if_chain! { + if let ExprKind::MethodCall(ref method, _, ref len_args) = end.kind; + if method.ident.name == sym!(len); + if len_args.len() == 1; + if let Some(arg) = len_args.get(0); + if snippet(cx, arg.span, "??") == var_name; + then { + return if offset.negate { + format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value) + } else { + String::new() + }; } - - let end_str = match limits { - ast::RangeLimits::Closed => { - let end = sugg::Sugg::hir(cx, end, "<count>"); - format!("{}", end + sugg::ONE) - }, - ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), - }; - - print_sum(&Offset::positive(end_str), &offset) - } else { - "..".into() } + + let end_str = match limits { + ast::RangeLimits::Closed => { + let end = sugg::Sugg::hir(cx, end, "<count>"); + format!("{}", end + sugg::ONE) + }, + ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), + }; + + print_sum(&Offset::positive(end_str), &offset) }; // The only statements in the for loops can be indexed assignments from diff --git a/tests/ui/manual_memcpy.rs b/tests/ui/manual_memcpy.rs index aa347288875..1f41838fa16 100644 --- a/tests/ui/manual_memcpy.rs +++ b/tests/ui/manual_memcpy.rs @@ -98,6 +98,11 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { for i in from..from + 3 { dst[i] = src[i - from]; } + + // `RangeTo` `for` loop - don't trigger lint + for i in 0.. { + dst[i] = src[i]; + } } #[warn(clippy::needless_range_loop, clippy::manual_memcpy)] diff --git a/tests/ui/manual_memcpy.stderr b/tests/ui/manual_memcpy.stderr index ec80f6070d6..95114c46f36 100644 --- a/tests/ui/manual_memcpy.stderr +++ b/tests/ui/manual_memcpy.stderr @@ -67,7 +67,7 @@ LL | for i in from..from + 3 { | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/manual_memcpy.rs:105:14 + --> $DIR/manual_memcpy.rs:110:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` From c94f0f49f8e025aae11534f9f2b4c59c34b1edb8 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 18:22:10 +1200 Subject: [PATCH 004/526] Remove all `ref` keyword --- clippy_lints/src/loops.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index ca61c97e3e3..502bd42214e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -772,8 +772,8 @@ fn check_for_loop<'a, 'tcx>( fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> bool { if_chain! { - if let ExprKind::Path(ref qpath) = expr.kind; - if let QPath::Resolved(None, ref path) = *qpath; + if let ExprKind::Path(qpath) = &expr.kind; + if let QPath::Resolved(None, path) = qpath; if path.segments.len() == 1; if let Res::Local(local_id) = qpath_res(cx, qpath, expr.hir_id); // our variable! @@ -821,8 +821,8 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool { fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> Option<FixedOffsetVar> { fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr<'_>, var: HirId) -> Option<String> { - match e.kind { - ExprKind::Lit(ref l) => match l.node { + match &e.kind { + ExprKind::Lit(l) => match l.node { ast::LitKind::Int(x, _ty) => Some(x.to_string()), _ => None, }, @@ -831,14 +831,14 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, v } } - if let ExprKind::Index(ref seqexpr, ref idx) = expr.kind { + if let ExprKind::Index(seqexpr, idx) = expr.kind { let ty = cx.tables.expr_ty(seqexpr); if !is_slice_like(cx, ty) { return None; } let offset = match idx.kind { - ExprKind::Binary(op, ref lhs, ref rhs) => match op.node { + ExprKind::Binary(op, lhs, rhs) => match op.node { BinOpKind::Add => { let offset_opt = if same_var(cx, lhs, var) { extract_offset(cx, rhs, var) @@ -878,7 +878,7 @@ fn fetch_cloned_fixed_offset_var<'a, 'tcx>( var: HirId, ) -> Option<FixedOffsetVar> { if_chain! { - if let ExprKind::MethodCall(ref method, _, ref args) = expr.kind; + if let ExprKind::MethodCall(method, _, args) = expr.kind; if method.ident.name == sym!(clone); if args.len() == 1; if let Some(arg) = args.get(0); @@ -900,7 +900,7 @@ fn get_indexed_assignments<'a, 'tcx>( e: &Expr<'_>, var: HirId, ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { - if let ExprKind::Assign(ref lhs, ref rhs, _) = e.kind { + if let ExprKind::Assign(lhs, rhs, _) = e.kind { match ( get_fixed_offset_var(cx, lhs, var), fetch_cloned_fixed_offset_var(cx, rhs, var), @@ -920,16 +920,14 @@ fn get_indexed_assignments<'a, 'tcx>( } } - if let ExprKind::Block(ref b, _) = body.kind { - let Block { - ref stmts, ref expr, .. - } = **b; + if let ExprKind::Block(b, _) = body.kind { + let Block { stmts, expr, .. } = *b; stmts .iter() .map(|stmt| match stmt.kind { StmtKind::Local(..) | StmtKind::Item(..) => None, - StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => Some(get_assignment(cx, e, var)), + StmtKind::Expr(e) | StmtKind::Semi(e) => Some(get_assignment(cx, e, var)), }) .chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var)))) .filter_map(|op| op) @@ -992,7 +990,7 @@ fn detect_manual_memcpy<'a, 'tcx>( let print_limit = |end: &Expr<'_>, offset: Offset, var_name: &str| { if_chain! { - if let ExprKind::MethodCall(ref method, _, ref len_args) = end.kind; + if let ExprKind::MethodCall(method, _, len_args) = end.kind; if method.ident.name == sym!(len); if len_args.len() == 1; if let Some(arg) = len_args.get(0); From 7dd0f3459f558c1b557223a042f549b378cacae9 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 18:47:24 +1200 Subject: [PATCH 005/526] Refactor `if` to use `else` and iterator combinators --- clippy_lints/src/loops.rs | 50 +++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 502bd42214e..3dd3a79b287 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -779,11 +779,11 @@ fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) - // our variable! if local_id == var; then { - return true; + true + } else { + false } } - - false } struct Offset { @@ -853,13 +853,7 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, v BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), _ => None, }, - ExprKind::Path(..) => { - if same_var(cx, idx, var) { - Some(Offset::positive("0".into())) - } else { - None - } - }, + ExprKind::Path(..) if same_var(cx, idx, var) => Some(Offset::positive("0".into())), _ => None, }; @@ -883,11 +877,11 @@ fn fetch_cloned_fixed_offset_var<'a, 'tcx>( if args.len() == 1; if let Some(arg) = args.get(0); then { - return get_fixed_offset_var(cx, arg, var); + get_fixed_offset_var(cx, arg, var) + } else { + get_fixed_offset_var(cx, expr, var) } } - - get_fixed_offset_var(cx, expr, var) } fn get_indexed_assignments<'a, 'tcx>( @@ -925,12 +919,12 @@ fn get_indexed_assignments<'a, 'tcx>( stmts .iter() - .map(|stmt| match stmt.kind { + .filter_map(|stmt| match stmt.kind { StmtKind::Local(..) | StmtKind::Item(..) => None, - StmtKind::Expr(e) | StmtKind::Semi(e) => Some(get_assignment(cx, e, var)), + StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e), }) - .chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var)))) - .filter_map(|op| op) + .chain(expr.into_iter()) + .map(|op| get_assignment(cx, op, var)) .collect::<Option<Vec<_>>>() .unwrap_or_default() } else { @@ -996,23 +990,23 @@ fn detect_manual_memcpy<'a, 'tcx>( if let Some(arg) = len_args.get(0); if snippet(cx, arg.span, "??") == var_name; then { - return if offset.negate { + if offset.negate { format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value) } else { String::new() + } + } else { + let end_str = match limits { + ast::RangeLimits::Closed => { + let end = sugg::Sugg::hir(cx, end, "<count>"); + format!("{}", end + sugg::ONE) + }, + ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), }; + + print_sum(&Offset::positive(end_str), &offset) } } - - let end_str = match limits { - ast::RangeLimits::Closed => { - let end = sugg::Sugg::hir(cx, end, "<count>"); - format!("{}", end + sugg::ONE) - }, - ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), - }; - - print_sum(&Offset::positive(end_str), &offset) }; // The only statements in the for loops can be indexed assignments from From 3f1e51b3f4a7bfb42c442caf2cb836ba62e2ba53 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 18:57:36 +1200 Subject: [PATCH 006/526] Rename `negate` to `sign` and make it strong types then make `art1` &str --- clippy_lints/src/loops.rs | 56 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3dd3a79b287..321d5265d0c 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -786,20 +786,29 @@ fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) - } } +#[derive(Clone, Copy)] +enum OffsetSign { + Positive, + Negative, +} + struct Offset { value: String, - negate: bool, + sign: OffsetSign, } impl Offset { - fn negative(s: String) -> Self { - Self { value: s, negate: true } + fn negative(value: String) -> Self { + Self { + value, + sign: OffsetSign::Negative, + } } - fn positive(s: String) -> Self { + fn positive(value: String) -> Self { Self { - value: s, - negate: false, + value, + sign: OffsetSign::Positive, } } } @@ -949,31 +958,23 @@ fn detect_manual_memcpy<'a, 'tcx>( { // the var must be a single name if let PatKind::Binding(_, canonical_id, _, _) = pat.kind { - let print_sum = |arg1: &Offset, arg2: &Offset| -> String { - match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { - ("0", _, "0", _) => "0".into(), - ("0", _, x, false) | (x, false, "0", _) => x.into(), - ("0", _, x, true) => format!("-{}", x), - (x, false, y, false) => format!("({} + {})", x, y), - (x, false, y, true) => { + let print_sum = |arg1: &str, arg2: &Offset| -> String { + match (arg1, &arg2.value[..], arg2.sign) { + ("0", "0", _) => "0".into(), + ("0", x, OffsetSign::Positive) | (x, "0", _) => x.into(), + ("0", x, OffsetSign::Negative) => format!("-{}", x), + (x, y, OffsetSign::Positive) => format!("({} + {})", x, y), + (x, y, OffsetSign::Negative) => { if x == y { "0".into() } else { format!("({} - {})", x, y) } }, - (x, true, y, false) => { - if x == y { - "0".into() - } else { - format!("({} - {})", y, x) - } - }, - (x, true, y, true) => format!("-({} + {})", x, y), } }; - let print_offset = |start_str: &Offset, inline_offset: &Offset| -> String { + let print_offset = |start_str: &str, inline_offset: &Offset| -> String { let offset = print_sum(start_str, inline_offset); if offset.as_str() == "0" { "".into() @@ -990,10 +991,9 @@ fn detect_manual_memcpy<'a, 'tcx>( if let Some(arg) = len_args.get(0); if snippet(cx, arg.span, "??") == var_name; then { - if offset.negate { - format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value) - } else { - String::new() + match offset.sign { + OffsetSign::Negative => format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value), + OffsetSign::Positive => "".into(), } } else { let end_str = match limits { @@ -1004,7 +1004,7 @@ fn detect_manual_memcpy<'a, 'tcx>( ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), }; - print_sum(&Offset::positive(end_str), &offset) + print_sum(&end_str, &offset) } } }; @@ -1016,7 +1016,7 @@ fn detect_manual_memcpy<'a, 'tcx>( let big_sugg = manual_copies .into_iter() .map(|(dst_var, src_var)| { - let start_str = Offset::positive(snippet(cx, start.span, "").to_string()); + let start_str = snippet(cx, start.span, "").to_string(); let dst_offset = print_offset(&start_str, &dst_var.offset); let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); let src_offset = print_offset(&start_str, &src_var.offset); From ecb472c052c746d87ce26f6b184f2c5f11537e0c Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:02:08 +1200 Subject: [PATCH 007/526] Use `fn` instead of closures where unnecessary --- clippy_lints/src/loops.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 321d5265d0c..e37c44dc026 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -958,7 +958,7 @@ fn detect_manual_memcpy<'a, 'tcx>( { // the var must be a single name if let PatKind::Binding(_, canonical_id, _, _) = pat.kind { - let print_sum = |arg1: &str, arg2: &Offset| -> String { + fn print_sum(arg1: &str, arg2: &Offset) -> String { match (arg1, &arg2.value[..], arg2.sign) { ("0", "0", _) => "0".into(), ("0", x, OffsetSign::Positive) | (x, "0", _) => x.into(), @@ -972,16 +972,16 @@ fn detect_manual_memcpy<'a, 'tcx>( } }, } - }; + } - let print_offset = |start_str: &str, inline_offset: &Offset| -> String { + fn print_offset(start_str: &str, inline_offset: &Offset) -> String { let offset = print_sum(start_str, inline_offset); if offset.as_str() == "0" { "".into() } else { offset } - }; + } let print_limit = |end: &Expr<'_>, offset: Offset, var_name: &str| { if_chain! { From aab80eedf3e271ada92a6509727461cc3aa6bb12 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:04:56 +1200 Subject: [PATCH 008/526] Extract `get_fixed_offset_var`` from `fetch_cloned_fixed_offset_var` --- clippy_lints/src/loops.rs | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index e37c44dc026..2dc95f53078 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -828,6 +828,16 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool { is_slice || is_type_diagnostic_item(cx, ty, sym!(vec_type)) || is_type_diagnostic_item(cx, ty, sym!(vecdeque_type)) } +fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { + if_chain! { + if let ExprKind::MethodCall(method, _, args) = expr.kind; + if method.ident.name == sym!(clone); + if args.len() == 1; + if let Some(arg) = args.get(0); + then { arg } else { expr } + } +} + fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> Option<FixedOffsetVar> { fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr<'_>, var: HirId) -> Option<String> { match &e.kind { @@ -875,24 +885,6 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, v } } -fn fetch_cloned_fixed_offset_var<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &Expr<'_>, - var: HirId, -) -> Option<FixedOffsetVar> { - if_chain! { - if let ExprKind::MethodCall(method, _, args) = expr.kind; - if method.ident.name == sym!(clone); - if args.len() == 1; - if let Some(arg) = args.get(0); - then { - get_fixed_offset_var(cx, arg, var) - } else { - get_fixed_offset_var(cx, expr, var) - } - } -} - fn get_indexed_assignments<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, body: &Expr<'_>, @@ -906,7 +898,7 @@ fn get_indexed_assignments<'a, 'tcx>( if let ExprKind::Assign(lhs, rhs, _) = e.kind { match ( get_fixed_offset_var(cx, lhs, var), - fetch_cloned_fixed_offset_var(cx, rhs, var), + get_fixed_offset_var(cx, fetch_cloned_expr(rhs), var), ) { (Some(offset_left), Some(offset_right)) => { // Source and destination must be different From 3d121d53af9a73ba11226715cd8132f6981ffee9 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:15:51 +1200 Subject: [PATCH 009/526] Extract roles getting indexes from `get_indexed_assignments` --- clippy_lints/src/loops.rs | 106 ++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2dc95f53078..0753b23e45b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -10,7 +10,6 @@ use crate::utils::{ }; use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg}; use if_chain::if_chain; -use itertools::Itertools; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; @@ -885,52 +884,39 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, v } } -fn get_indexed_assignments<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - body: &Expr<'_>, - var: HirId, -) -> Vec<(FixedOffsetVar, FixedOffsetVar)> { - fn get_assignment<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - e: &Expr<'_>, - var: HirId, - ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { +fn get_assignments<'a, 'tcx>( + body: &'tcx Expr<'tcx>, +) -> impl Iterator<Item = Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)>> { + fn get_assignment<'a, 'tcx>(e: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> { if let ExprKind::Assign(lhs, rhs, _) = e.kind { - match ( - get_fixed_offset_var(cx, lhs, var), - get_fixed_offset_var(cx, fetch_cloned_expr(rhs), var), - ) { - (Some(offset_left), Some(offset_right)) => { - // Source and destination must be different - if offset_left.var_name == offset_right.var_name { - None - } else { - Some((offset_left, offset_right)) - } - }, - _ => None, - } + Some((lhs, rhs)) } else { None } } + // This is one of few ways to return different iterators + // derived from: https://stackoverflow.com/questions/29760668/conditionally-iterate-over-one-of-several-possible-iterators/52064434#52064434 + let mut iter_a = None; + let mut iter_b = None; + if let ExprKind::Block(b, _) = body.kind { let Block { stmts, expr, .. } = *b; - stmts + iter_a = stmts .iter() .filter_map(|stmt| match stmt.kind { StmtKind::Local(..) | StmtKind::Item(..) => None, StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e), }) .chain(expr.into_iter()) - .map(|op| get_assignment(cx, op, var)) - .collect::<Option<Vec<_>>>() - .unwrap_or_default() + .map(get_assignment) + .into() } else { - get_assignment(cx, body, var).into_iter().collect() + iter_b = Some(get_assignment(body)) } + + iter_a.into_iter().flatten().chain(iter_b.into_iter()) } /// Checks for for loops that sequentially copy items from one slice-like @@ -1003,30 +989,48 @@ fn detect_manual_memcpy<'a, 'tcx>( // The only statements in the for loops can be indexed assignments from // indexed retrievals. - let manual_copies = get_indexed_assignments(cx, body, canonical_id); + let big_sugg = get_assignments(body) + .map(|o| { + o.and_then(|(lhs, rhs)| { + let rhs = fetch_cloned_expr(rhs); + if_chain! { + if let Some(offset_left) = get_fixed_offset_var(cx, lhs, canonical_id); + if let Some(offset_right) = get_fixed_offset_var(cx, rhs, canonical_id); - let big_sugg = manual_copies - .into_iter() - .map(|(dst_var, src_var)| { - let start_str = snippet(cx, start.span, "").to_string(); - let dst_offset = print_offset(&start_str, &dst_var.offset); - let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); - let src_offset = print_offset(&start_str, &src_var.offset); - let src_limit = print_limit(end, src_var.offset, &src_var.var_name); - let dst = if dst_offset == "" && dst_limit == "" { - dst_var.var_name - } else { - format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit) - }; - - format!( - "{}.clone_from_slice(&{}[{}..{}])", - dst, src_var.var_name, src_offset, src_limit - ) + // Source and destination must be different + if offset_left.var_name != offset_right.var_name; + then { + Some((offset_left, offset_right)) + } else { + return None + } + } + }) }) - .join("\n "); + .map(|o| { + o.map(|(dst_var, src_var)| { + let start_str = snippet(cx, start.span, "").to_string(); + let dst_offset = print_offset(&start_str, &dst_var.offset); + let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); + let src_offset = print_offset(&start_str, &src_var.offset); + let src_limit = print_limit(end, src_var.offset, &src_var.var_name); + let dst = if dst_offset == "" && dst_limit == "" { + dst_var.var_name + } else { + format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit) + }; - if !big_sugg.is_empty() { + format!( + "{}.clone_from_slice(&{}[{}..{}])", + dst, src_var.var_name, src_offset, src_limit + ) + }) + }) + .collect::<Option<Vec<_>>>() + .filter(|v| !v.is_empty()) + .map(|v| v.join("\n ")); + + if let Some(big_sugg) = big_sugg { span_lint_and_sugg( cx, MANUAL_MEMCPY, From 4f2617c059f693ec72e5d31ad31fd85eba019ab1 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:26:00 +1200 Subject: [PATCH 010/526] Separate getting offsets and getting index expressions --- clippy_lints/src/loops.rs | 63 +++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0753b23e45b..75955997af2 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -837,7 +837,7 @@ fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { } } -fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> Option<FixedOffsetVar> { +fn get_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, idx: &Expr<'_>, var: HirId) -> Option<Offset> { fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr<'_>, var: HirId) -> Option<String> { match &e.kind { ExprKind::Lit(l) => match l.node { @@ -849,38 +849,24 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, v } } - if let ExprKind::Index(seqexpr, idx) = expr.kind { - let ty = cx.tables.expr_ty(seqexpr); - if !is_slice_like(cx, ty) { - return None; - } + match idx.kind { + ExprKind::Binary(op, lhs, rhs) => match op.node { + BinOpKind::Add => { + let offset_opt = if same_var(cx, lhs, var) { + extract_offset(cx, rhs, var) + } else if same_var(cx, rhs, var) { + extract_offset(cx, lhs, var) + } else { + None + }; - let offset = match idx.kind { - ExprKind::Binary(op, lhs, rhs) => match op.node { - BinOpKind::Add => { - let offset_opt = if same_var(cx, lhs, var) { - extract_offset(cx, rhs, var) - } else if same_var(cx, rhs, var) { - extract_offset(cx, lhs, var) - } else { - None - }; - - offset_opt.map(Offset::positive) - }, - BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), - _ => None, + offset_opt.map(Offset::positive) }, - ExprKind::Path(..) if same_var(cx, idx, var) => Some(Offset::positive("0".into())), + BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), _ => None, - }; - - offset.map(|o| FixedOffsetVar { - var_name: snippet_opt(cx, seqexpr.span).unwrap_or_else(|| "???".into()), - offset: o, - }) - } else { - None + }, + ExprKind::Path(..) if same_var(cx, idx, var) => Some(Offset::positive("0".into())), + _ => None, } } @@ -994,15 +980,22 @@ fn detect_manual_memcpy<'a, 'tcx>( o.and_then(|(lhs, rhs)| { let rhs = fetch_cloned_expr(rhs); if_chain! { - if let Some(offset_left) = get_fixed_offset_var(cx, lhs, canonical_id); - if let Some(offset_right) = get_fixed_offset_var(cx, rhs, canonical_id); + if let ExprKind::Index(seqexpr_left, idx_left) = lhs.kind; + if let ExprKind::Index(seqexpr_right, idx_right) = rhs.kind; + if is_slice_like(cx, cx.tables.expr_ty(seqexpr_left)) + && is_slice_like(cx, cx.tables.expr_ty(seqexpr_right)); + if let Some(offset_left) = get_offset(cx, &idx_left, canonical_id); + if let Some(offset_right) = get_offset(cx, &idx_right, canonical_id); + let var_name_left = snippet_opt(cx, seqexpr_left.span).unwrap_or_else(|| "???".into()); + let var_name_right = snippet_opt(cx, seqexpr_right.span).unwrap_or_else(|| "???".into()); // Source and destination must be different - if offset_left.var_name != offset_right.var_name; + if var_name_left != var_name_right; then { - Some((offset_left, offset_right)) + Some((FixedOffsetVar { var_name: var_name_left, offset: offset_left }, + FixedOffsetVar { var_name: var_name_right, offset: offset_right })) } else { - return None + None } } }) From 9fc6f37778789de94caa280f41afdf651bf5ae10 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:34:41 +1200 Subject: [PATCH 011/526] Delay getting the snippet from slices --- clippy_lints/src/loops.rs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 75955997af2..8ab35556670 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -812,8 +812,8 @@ impl Offset { } } -struct FixedOffsetVar { - var_name: String, +struct FixedOffsetVar<'hir> { + var: &'hir Expr<'hir>, offset: Offset, } @@ -947,13 +947,13 @@ fn detect_manual_memcpy<'a, 'tcx>( } } - let print_limit = |end: &Expr<'_>, offset: Offset, var_name: &str| { + let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| { if_chain! { if let ExprKind::MethodCall(method, _, len_args) = end.kind; if method.ident.name == sym!(len); if len_args.len() == 1; if let Some(arg) = len_args.get(0); - if snippet(cx, arg.span, "??") == var_name; + if var_def_id(cx, arg) == var_def_id(cx, var); then { match offset.sign { OffsetSign::Negative => format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value), @@ -986,14 +986,12 @@ fn detect_manual_memcpy<'a, 'tcx>( && is_slice_like(cx, cx.tables.expr_ty(seqexpr_right)); if let Some(offset_left) = get_offset(cx, &idx_left, canonical_id); if let Some(offset_right) = get_offset(cx, &idx_right, canonical_id); - let var_name_left = snippet_opt(cx, seqexpr_left.span).unwrap_or_else(|| "???".into()); - let var_name_right = snippet_opt(cx, seqexpr_right.span).unwrap_or_else(|| "???".into()); // Source and destination must be different - if var_name_left != var_name_right; + if var_def_id(cx, seqexpr_left) != var_def_id(cx, seqexpr_right); then { - Some((FixedOffsetVar { var_name: var_name_left, offset: offset_left }, - FixedOffsetVar { var_name: var_name_right, offset: offset_right })) + Some((FixedOffsetVar { var: seqexpr_left, offset: offset_left }, + FixedOffsetVar { var: seqexpr_right, offset: offset_right })) } else { None } @@ -1004,18 +1002,22 @@ fn detect_manual_memcpy<'a, 'tcx>( o.map(|(dst_var, src_var)| { let start_str = snippet(cx, start.span, "").to_string(); let dst_offset = print_offset(&start_str, &dst_var.offset); - let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); + let dst_limit = print_limit(end, dst_var.offset, dst_var.var); let src_offset = print_offset(&start_str, &src_var.offset); - let src_limit = print_limit(end, src_var.offset, &src_var.var_name); + let src_limit = print_limit(end, src_var.offset, src_var.var); + + let dst_var_name = snippet_opt(cx, dst_var.var.span).unwrap_or_else(|| "???".into()); + let src_var_name = snippet_opt(cx, src_var.var.span).unwrap_or_else(|| "???".into()); + let dst = if dst_offset == "" && dst_limit == "" { - dst_var.var_name + dst_var_name } else { - format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit) + format!("{}[{}..{}]", dst_var_name, dst_offset, dst_limit) }; format!( "{}.clone_from_slice(&{}[{}..{}])", - dst, src_var.var_name, src_offset, src_limit + dst, src_var_name, src_offset, src_limit ) }) }) From 582614fbbe76fed1b06feb640229b71a1886ffd7 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:44:44 +1200 Subject: [PATCH 012/526] Extract building the suggestion of `manual_memcpy` --- clippy_lints/src/loops.rs | 154 ++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 74 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8ab35556670..7cf3e16bef9 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -905,6 +905,85 @@ fn get_assignments<'a, 'tcx>( iter_a.into_iter().flatten().chain(iter_b.into_iter()) } +fn build_manual_memcpy_suggestion<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + start: &Expr<'_>, + end: &Expr<'_>, + limits: ast::RangeLimits, + dst_var: FixedOffsetVar<'_>, + src_var: FixedOffsetVar<'_>, +) -> String { + fn print_sum(arg1: &str, arg2: &Offset) -> String { + match (arg1, &arg2.value[..], arg2.sign) { + ("0", "0", _) => "0".into(), + ("0", x, OffsetSign::Positive) | (x, "0", _) => x.into(), + ("0", x, OffsetSign::Negative) => format!("-{}", x), + (x, y, OffsetSign::Positive) => format!("({} + {})", x, y), + (x, y, OffsetSign::Negative) => { + if x == y { + "0".into() + } else { + format!("({} - {})", x, y) + } + }, + } + } + + fn print_offset(start_str: &str, inline_offset: &Offset) -> String { + let offset = print_sum(start_str, inline_offset); + if offset.as_str() == "0" { + "".into() + } else { + offset + } + } + + let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| { + if_chain! { + if let ExprKind::MethodCall(method, _, len_args) = end.kind; + if method.ident.name == sym!(len); + if len_args.len() == 1; + if let Some(arg) = len_args.get(0); + if var_def_id(cx, arg) == var_def_id(cx, var); + then { + match offset.sign { + OffsetSign::Negative => format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value), + OffsetSign::Positive => "".into(), + } + } else { + let end_str = match limits { + ast::RangeLimits::Closed => { + let end = sugg::Sugg::hir(cx, end, "<count>"); + format!("{}", end + sugg::ONE) + }, + ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), + }; + + print_sum(&end_str, &offset) + } + } + }; + + let start_str = snippet(cx, start.span, "").to_string(); + let dst_offset = print_offset(&start_str, &dst_var.offset); + let dst_limit = print_limit(end, dst_var.offset, dst_var.var); + let src_offset = print_offset(&start_str, &src_var.offset); + let src_limit = print_limit(end, src_var.offset, src_var.var); + + let dst_var_name = snippet_opt(cx, dst_var.var.span).unwrap_or_else(|| "???".into()); + let src_var_name = snippet_opt(cx, src_var.var.span).unwrap_or_else(|| "???".into()); + + let dst = if dst_offset == "" && dst_limit == "" { + dst_var_name + } else { + format!("{}[{}..{}]", dst_var_name, dst_offset, dst_limit) + }; + + format!( + "{}.clone_from_slice(&{}[{}..{}])", + dst, src_var_name, src_offset, src_limit + ) +} /// Checks for for loops that sequentially copy items from one slice-like /// object to another. fn detect_manual_memcpy<'a, 'tcx>( @@ -922,57 +1001,6 @@ fn detect_manual_memcpy<'a, 'tcx>( { // the var must be a single name if let PatKind::Binding(_, canonical_id, _, _) = pat.kind { - fn print_sum(arg1: &str, arg2: &Offset) -> String { - match (arg1, &arg2.value[..], arg2.sign) { - ("0", "0", _) => "0".into(), - ("0", x, OffsetSign::Positive) | (x, "0", _) => x.into(), - ("0", x, OffsetSign::Negative) => format!("-{}", x), - (x, y, OffsetSign::Positive) => format!("({} + {})", x, y), - (x, y, OffsetSign::Negative) => { - if x == y { - "0".into() - } else { - format!("({} - {})", x, y) - } - }, - } - } - - fn print_offset(start_str: &str, inline_offset: &Offset) -> String { - let offset = print_sum(start_str, inline_offset); - if offset.as_str() == "0" { - "".into() - } else { - offset - } - } - - let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| { - if_chain! { - if let ExprKind::MethodCall(method, _, len_args) = end.kind; - if method.ident.name == sym!(len); - if len_args.len() == 1; - if let Some(arg) = len_args.get(0); - if var_def_id(cx, arg) == var_def_id(cx, var); - then { - match offset.sign { - OffsetSign::Negative => format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value), - OffsetSign::Positive => "".into(), - } - } else { - let end_str = match limits { - ast::RangeLimits::Closed => { - let end = sugg::Sugg::hir(cx, end, "<count>"); - format!("{}", end + sugg::ONE) - }, - ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), - }; - - print_sum(&end_str, &offset) - } - } - }; - // The only statements in the for loops can be indexed assignments from // indexed retrievals. let big_sugg = get_assignments(body) @@ -998,29 +1026,7 @@ fn detect_manual_memcpy<'a, 'tcx>( } }) }) - .map(|o| { - o.map(|(dst_var, src_var)| { - let start_str = snippet(cx, start.span, "").to_string(); - let dst_offset = print_offset(&start_str, &dst_var.offset); - let dst_limit = print_limit(end, dst_var.offset, dst_var.var); - let src_offset = print_offset(&start_str, &src_var.offset); - let src_limit = print_limit(end, src_var.offset, src_var.var); - - let dst_var_name = snippet_opt(cx, dst_var.var.span).unwrap_or_else(|| "???".into()); - let src_var_name = snippet_opt(cx, src_var.var.span).unwrap_or_else(|| "???".into()); - - let dst = if dst_offset == "" && dst_limit == "" { - dst_var_name - } else { - format!("{}[{}..{}]", dst_var_name, dst_offset, dst_limit) - }; - - format!( - "{}.clone_from_slice(&{}[{}..{}])", - dst, src_var_name, src_offset, src_limit - ) - }) - }) + .map(|o| o.map(|(dst, src)| build_manual_memcpy_suggestion(cx, start, end, limits, dst, src))) .collect::<Option<Vec<_>>>() .filter(|v| !v.is_empty()) .map(|v| v.join("\n ")); From 51585a129892f42eb23b0b37fea0e729f6678994 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 20:37:21 +1200 Subject: [PATCH 013/526] Removed unused lifetimes and a needless bool --- clippy_lints/src/loops.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7cf3e16bef9..5f7f0897943 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -775,10 +775,9 @@ fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) - if let QPath::Resolved(None, path) = qpath; if path.segments.len() == 1; if let Res::Local(local_id) = qpath_res(cx, qpath, expr.hir_id); - // our variable! - if local_id == var; then { - true + // our variable! + local_id == var } else { false } @@ -870,10 +869,8 @@ fn get_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, idx: &Expr<'_>, var: HirId) } } -fn get_assignments<'a, 'tcx>( - body: &'tcx Expr<'tcx>, -) -> impl Iterator<Item = Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)>> { - fn get_assignment<'a, 'tcx>(e: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> { +fn get_assignments<'tcx>(body: &'tcx Expr<'tcx>) -> impl Iterator<Item = Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)>> { + fn get_assignment<'tcx>(e: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> { if let ExprKind::Assign(lhs, rhs, _) = e.kind { Some((lhs, rhs)) } else { From 1afb6e6e3b23bd5555f34cc4dcd20349dfd789de Mon Sep 17 00:00:00 2001 From: Stanislav Tkach <stanislav.tkach@gmail.com> Date: Tue, 28 Apr 2020 12:08:38 +0300 Subject: [PATCH 014/526] Extend example for the `unneeded_field_pattern` lint Current example is incorrect (or pseudo-code) because a struct name is omitted. I have used the code from the tests instead. Perhaps this example can be made less verbose, but I think it is more convenient to see a "real" code as an example. --- clippy_lints/src/misc_early.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index adfd8dfb1c1..62ee051624b 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -24,8 +24,25 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```ignore - /// let { a: _, b: ref b, c: _ } = .. + /// ```rust + /// # struct Foo { + /// # a: i32, + /// # b: i32, + /// # c: i32, + /// # } + /// let f = Foo { a: 0, b: 0, c: 0 }; + /// + /// // Bad + /// match f { + /// Foo { a: _, b: 0, .. } => {}, + /// Foo { a: _, b: _, c: _ } => {}, + /// } + /// + /// // Good + /// match f { + /// Foo { b: 0, .. } => {}, + /// Foo { .. } => {}, + /// } /// ``` pub UNNEEDED_FIELD_PATTERN, restriction, From 461f4a34660691675434a318ac4fd61a83444428 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Thu, 30 Apr 2020 17:32:37 +1200 Subject: [PATCH 015/526] Add missing tests --- tests/ui/manual_memcpy.rs | 10 ++++++++++ tests/ui/manual_memcpy.stderr | 16 ++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/tests/ui/manual_memcpy.rs b/tests/ui/manual_memcpy.rs index 1f41838fa16..9c24d6d4db1 100644 --- a/tests/ui/manual_memcpy.rs +++ b/tests/ui/manual_memcpy.rs @@ -99,6 +99,16 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { dst[i] = src[i - from]; } + #[allow(clippy::identity_op)] + for i in 0..5 { + dst[i - 0] = src[i]; + } + + #[allow(clippy::reverse_range_loop)] + for i in 0..0 { + dst[i] = src[i]; + } + // `RangeTo` `for` loop - don't trigger lint for i in 0.. { dst[i] = src[i]; diff --git a/tests/ui/manual_memcpy.stderr b/tests/ui/manual_memcpy.stderr index 95114c46f36..bad84a58900 100644 --- a/tests/ui/manual_memcpy.stderr +++ b/tests/ui/manual_memcpy.stderr @@ -67,10 +67,22 @@ LL | for i in from..from + 3 { | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/manual_memcpy.rs:110:14 + --> $DIR/manual_memcpy.rs:103:14 + | +LL | for i in 0..5 { + | ^^^^ help: try replacing the loop by: `dst[..5].clone_from_slice(&src[..5])` + +error: it looks like you're manually copying between slices + --> $DIR/manual_memcpy.rs:108:14 + | +LL | for i in 0..0 { + | ^^^^ help: try replacing the loop by: `dst[..0].clone_from_slice(&src[..0])` + +error: it looks like you're manually copying between slices + --> $DIR/manual_memcpy.rs:120:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` -error: aborting due to 11 previous errors +error: aborting due to 13 previous errors From f072ded3bf6286668ff8eade5b58e471dbe66f2a Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Fri, 1 May 2020 01:44:17 +0200 Subject: [PATCH 016/526] Implement the manual_non_exhaustive lint --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 + clippy_lints/src/manual_non_exhaustive.rs | 167 ++++++++++++++++++++++ src/lintlist/mod.rs | 7 + tests/ui/manual_non_exhaustive.rs | 124 ++++++++++++++++ tests/ui/manual_non_exhaustive.stderr | 48 +++++++ 6 files changed, 352 insertions(+) create mode 100644 clippy_lints/src/manual_non_exhaustive.rs create mode 100644 tests/ui/manual_non_exhaustive.rs create mode 100644 tests/ui/manual_non_exhaustive.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 575773580c0..facf363e371 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1423,6 +1423,7 @@ Released 2018-09-13 [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy +[`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c995be5edc2..64f3a8a0ebb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -247,6 +247,7 @@ mod literal_representation; mod loops; mod macro_use; mod main_recursion; +mod manual_non_exhaustive; mod map_clone; mod map_unit_fn; mod match_on_vec_items; @@ -628,6 +629,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::WHILE_LET_ON_ITERATOR, ¯o_use::MACRO_USE_IMPORTS, &main_recursion::MAIN_RECURSION, + &manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, &map_clone::MAP_CLONE, &map_unit_fn::OPTION_MAP_UNIT_FN, &map_unit_fn::RESULT_MAP_UNIT_FN, @@ -1064,6 +1066,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls); store.register_late_pass(|| box if_let_mutex::IfLetMutex); store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems); + store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1280,6 +1283,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::WHILE_LET_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), LintId::of(&main_recursion::MAIN_RECURSION), + LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), LintId::of(&map_clone::MAP_CLONE), LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN), LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN), @@ -1474,6 +1478,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::NEEDLESS_RANGE_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), LintId::of(&main_recursion::MAIN_RECURSION), + LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), LintId::of(&map_clone::MAP_CLONE), LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), LintId::of(&matches::MATCH_OVERLAPPING_ARM), diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs new file mode 100644 index 00000000000..ca2a2cf2e1e --- /dev/null +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -0,0 +1,167 @@ +use crate::utils::{snippet_opt, span_lint_and_then}; +use if_chain::if_chain; +use rustc_ast::ast::{Attribute, Ident, Item, ItemKind, StructField, TyKind, Variant, VariantData, VisibilityKind}; +use rustc_attr as attr; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Checks for manual implementations of the non-exhaustive pattern. + /// + /// **Why is this bad?** Using the #[non_exhaustive] attribute expresses better the intent + /// and allows possible optimizations when applied to enums. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// struct S { + /// pub a: i32, + /// pub b: i32, + /// _c: (), + /// } + /// + /// enum E { + /// A, + /// B, + /// #[doc(hidden)] + /// _C, + /// } + /// + /// struct T(pub i32, pub i32, ()); + /// ``` + /// Use instead: + /// ```rust + /// #[non_exhaustive] + /// struct S { + /// pub a: i32, + /// pub b: i32, + /// } + /// + /// #[non_exhaustive] + /// enum E { + /// A, + /// B, + /// } + /// + /// #[non_exhaustive] + /// struct T(pub i32, pub i32); + /// ``` + pub MANUAL_NON_EXHAUSTIVE, + style, + "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]" +} + +declare_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]); + +impl EarlyLintPass for ManualNonExhaustive { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + match &item.kind { + ItemKind::Enum(def, _) => { + check_manual_non_exhaustive_enum(cx, item, &def.variants); + }, + ItemKind::Struct(variant_data, _) => { + if let VariantData::Unit(..) = variant_data { + return; + } + + check_manual_non_exhaustive_struct(cx, item, variant_data); + }, + _ => {}, + } + } +} + +fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) { + fn is_non_exhaustive_marker(variant: &Variant) -> bool { + matches!(variant.data, VariantData::Unit(_)) + && variant.ident.as_str().starts_with('_') + && variant.attrs.iter().any(|a| is_doc_hidden(a)) + } + + fn is_doc_hidden(attr: &Attribute) -> bool { + attr.check_name(sym!(doc)) + && match attr.meta_item_list() { + Some(l) => attr::list_contains_name(&l, sym!(hidden)), + None => false, + } + } + + if_chain! { + if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); + let markers = variants.iter().filter(|v| is_non_exhaustive_marker(v)).count(); + if markers == 1 && variants.len() > markers; + if let Some(variant) = variants.last(); + if is_non_exhaustive_marker(variant); + then { + span_lint_and_then( + cx, + MANUAL_NON_EXHAUSTIVE, + item.span, + "this seems like a manual implementation of the non-exhaustive pattern", + |diag| { + let header_span = cx.sess.source_map().span_until_char(item.span, '{'); + + if let Some(snippet) = snippet_opt(cx, header_span) { + diag.span_suggestion( + item.span, + "add the attribute", + format!("#[non_exhaustive] {}", snippet), + Applicability::Unspecified, + ); + diag.span_help(variant.span, "and remove this variant"); + } + }); + } + } +} + +fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: &VariantData) { + fn is_private(field: &StructField) -> bool { + matches!(field.vis.node, VisibilityKind::Inherited) + } + + fn is_non_exhaustive_marker(name: &Option<Ident>) -> bool { + name.map(|n| n.as_str().starts_with('_')).unwrap_or(true) + } + + let fields = data.fields(); + let private_fields = fields.iter().filter(|f| is_private(f)).count(); + let public_fields = fields.iter().filter(|f| f.vis.node.is_pub()).count(); + + if_chain! { + if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); + if private_fields == 1 && public_fields >= private_fields && public_fields == fields.len() - 1; + if let Some(field) = fields.iter().find(|f| is_private(f)); + if is_non_exhaustive_marker(&field.ident); + if let TyKind::Tup(tup_fields) = &field.ty.kind; + if tup_fields.is_empty(); + then { + span_lint_and_then( + cx, + MANUAL_NON_EXHAUSTIVE, + item.span, + "this seems like a manual implementation of the non-exhaustive pattern", + |diag| { + let delimiter = match data { + VariantData::Struct(..) => '{', + VariantData::Tuple(..) => '(', + _ => unreachable!(), + }; + let header_span = cx.sess.source_map().span_until_char(item.span, delimiter); + + if let Some(snippet) = snippet_opt(cx, header_span) { + diag.span_suggestion( + item.span, + "add the attribute", + format!("#[non_exhaustive] {}", snippet), + Applicability::Unspecified, + ); + diag.span_help(field.span, "and remove this field"); + } + }); + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 72675c25175..c5360002fa0 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1088,6 +1088,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "loops", }, + Lint { + name: "manual_non_exhaustive", + group: "style", + desc: "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]", + deprecation: None, + module: "manual_non_exhaustive", + }, Lint { name: "manual_saturating_arithmetic", group: "style", diff --git a/tests/ui/manual_non_exhaustive.rs b/tests/ui/manual_non_exhaustive.rs new file mode 100644 index 00000000000..9c239db6e00 --- /dev/null +++ b/tests/ui/manual_non_exhaustive.rs @@ -0,0 +1,124 @@ +#![warn(clippy::manual_non_exhaustive)] +#![allow(unused)] + +mod enums { + enum E { + A, + B, + #[doc(hidden)] + _C, + } + + // last variant does not have doc hidden attribute, should be ignored + enum NoDocHidden { + A, + B, + _C, + } + + // name of variant with doc hidden does not start with underscore, should be ignored + enum NoUnderscore { + A, + B, + #[doc(hidden)] + C, + } + + // variant with doc hidden is not unit, should be ignored + enum NotUnit { + A, + B, + #[doc(hidden)] + _C(bool), + } + + // variant with doc hidden is not the last one, should be ignored + enum NotLast { + A, + #[doc(hidden)] + _B, + C, + } + + // variant with doc hidden is the only one, should be ignored + enum OnlyMarker { + #[doc(hidden)] + _A, + } + + // variant with multiple non-exhaustive "markers", should be ignored + enum MultipleMarkers { + A, + #[doc(hidden)] + _B, + #[doc(hidden)] + _C, + } + + // already non_exhaustive, should be ignored + #[non_exhaustive] + enum NonExhaustive { + A, + B, + } +} + +mod structs { + struct S { + pub a: i32, + pub b: i32, + _c: (), + } + + // some other fields are private, should be ignored + struct PrivateFields { + a: i32, + pub b: i32, + _c: (), + } + + // private field name does not start with underscore, should be ignored + struct NoUnderscore { + pub a: i32, + pub b: i32, + c: (), + } + + // private field is not unit type, should be ignored + struct NotUnit { + pub a: i32, + pub b: i32, + _c: i32, + } + + // private field is the only field, should be ignored + struct OnlyMarker { + _a: (), + } + + // already non exhaustive, should be ignored + #[non_exhaustive] + struct NonExhaustive { + pub a: i32, + pub b: i32, + } +} + +mod tuple_structs { + struct T(pub i32, pub i32, ()); + + // some other fields are private, should be ignored + struct PrivateFields(pub i32, i32, ()); + + // private field is not unit type, should be ignored + struct NotUnit(pub i32, pub i32, i32); + + // private field is the only field, should be ignored + struct OnlyMarker(()); + + // already non exhaustive, should be ignored + #[non_exhaustive] + struct NonExhaustive(pub i32, pub i32); +} + +fn main() {} diff --git a/tests/ui/manual_non_exhaustive.stderr b/tests/ui/manual_non_exhaustive.stderr new file mode 100644 index 00000000000..d6719bca0d4 --- /dev/null +++ b/tests/ui/manual_non_exhaustive.stderr @@ -0,0 +1,48 @@ +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:5:5 + | +LL | / enum E { +LL | | A, +LL | | B, +LL | | #[doc(hidden)] +LL | | _C, +LL | | } + | |_____^ help: add the attribute: `#[non_exhaustive] enum E` + | + = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings` +help: and remove this variant + --> $DIR/manual_non_exhaustive.rs:9:9 + | +LL | _C, + | ^^ + +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:67:5 + | +LL | / struct S { +LL | | pub a: i32, +LL | | pub b: i32, +LL | | _c: (), +LL | | } + | |_____^ help: add the attribute: `#[non_exhaustive] struct S` + | +help: and remove this field + --> $DIR/manual_non_exhaustive.rs:70:9 + | +LL | _c: (), + | ^^^^^^ + +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:108:5 + | +LL | struct T(pub i32, pub i32, ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[non_exhaustive] struct T` + | +help: and remove this field + --> $DIR/manual_non_exhaustive.rs:108:32 + | +LL | struct T(pub i32, pub i32, ()); + | ^^ + +error: aborting due to 3 previous errors + From 42b0b4754c881101cefb0307c489d6159c19b2f3 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Fri, 1 May 2020 22:37:14 +0200 Subject: [PATCH 017/526] Apply suggestions from PR review --- clippy_lints/src/manual_non_exhaustive.rs | 84 ++++++++++++----------- tests/ui/manual_non_exhaustive.rs | 39 +++++++---- tests/ui/manual_non_exhaustive.stderr | 81 ++++++++++++++++++---- 3 files changed, 139 insertions(+), 65 deletions(-) diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index ca2a2cf2e1e..a4273da1d74 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -1,10 +1,11 @@ use crate::utils::{snippet_opt, span_lint_and_then}; use if_chain::if_chain; -use rustc_ast::ast::{Attribute, Ident, Item, ItemKind, StructField, TyKind, Variant, VariantData, VisibilityKind}; +use rustc_ast::ast::{Attribute, Item, ItemKind, StructField, Variant, VariantData, VisibilityKind}; use rustc_attr as attr; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Span; declare_clippy_lint! { /// **What it does:** Checks for manual implementations of the non-exhaustive pattern. @@ -90,11 +91,9 @@ fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants } if_chain! { - if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); - let markers = variants.iter().filter(|v| is_non_exhaustive_marker(v)).count(); - if markers == 1 && variants.len() > markers; - if let Some(variant) = variants.last(); - if is_non_exhaustive_marker(variant); + let mut markers = variants.iter().filter(|v| is_non_exhaustive_marker(v)); + if let Some(marker) = markers.next(); + if markers.count() == 0 && variants.len() > 1; then { span_lint_and_then( cx, @@ -102,17 +101,20 @@ fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants item.span, "this seems like a manual implementation of the non-exhaustive pattern", |diag| { - let header_span = cx.sess.source_map().span_until_char(item.span, '{'); - - if let Some(snippet) = snippet_opt(cx, header_span) { - diag.span_suggestion( - item.span, - "add the attribute", - format!("#[non_exhaustive] {}", snippet), - Applicability::Unspecified, - ); - diag.span_help(variant.span, "and remove this variant"); + if_chain! { + if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); + let header_span = cx.sess.source_map().span_until_char(item.span, '{'); + if let Some(snippet) = snippet_opt(cx, header_span); + then { + diag.span_suggestion( + header_span, + "add the attribute", + format!("#[non_exhaustive] {}", snippet), + Applicability::Unspecified, + ); + } } + diag.span_help(marker.span, "remove this variant"); }); } } @@ -123,8 +125,18 @@ fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: matches!(field.vis.node, VisibilityKind::Inherited) } - fn is_non_exhaustive_marker(name: &Option<Ident>) -> bool { - name.map(|n| n.as_str().starts_with('_')).unwrap_or(true) + fn is_non_exhaustive_marker(field: &StructField) -> bool { + is_private(field) && field.ty.kind.is_unit() && field.ident.map_or(true, |n| n.as_str().starts_with('_')) + } + + fn find_header_span(cx: &EarlyContext<'_>, item: &Item, data: &VariantData) -> Span { + let delimiter = match data { + VariantData::Struct(..) => '{', + VariantData::Tuple(..) => '(', + _ => unreachable!("`VariantData::Unit` is already handled above"), + }; + + cx.sess.source_map().span_until_char(item.span, delimiter) } let fields = data.fields(); @@ -132,12 +144,8 @@ fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: let public_fields = fields.iter().filter(|f| f.vis.node.is_pub()).count(); if_chain! { - if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); - if private_fields == 1 && public_fields >= private_fields && public_fields == fields.len() - 1; - if let Some(field) = fields.iter().find(|f| is_private(f)); - if is_non_exhaustive_marker(&field.ident); - if let TyKind::Tup(tup_fields) = &field.ty.kind; - if tup_fields.is_empty(); + if private_fields == 1 && public_fields >= 1 && public_fields == fields.len() - 1; + if let Some(marker) = fields.iter().find(|f| is_non_exhaustive_marker(f)); then { span_lint_and_then( cx, @@ -145,22 +153,20 @@ fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: item.span, "this seems like a manual implementation of the non-exhaustive pattern", |diag| { - let delimiter = match data { - VariantData::Struct(..) => '{', - VariantData::Tuple(..) => '(', - _ => unreachable!(), - }; - let header_span = cx.sess.source_map().span_until_char(item.span, delimiter); - - if let Some(snippet) = snippet_opt(cx, header_span) { - diag.span_suggestion( - item.span, - "add the attribute", - format!("#[non_exhaustive] {}", snippet), - Applicability::Unspecified, - ); - diag.span_help(field.span, "and remove this field"); + if_chain! { + if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); + let header_span = find_header_span(cx, item, data); + if let Some(snippet) = snippet_opt(cx, header_span); + then { + diag.span_suggestion( + header_span, + "add the attribute", + format!("#[non_exhaustive] {}", snippet), + Applicability::Unspecified, + ); + } } + diag.span_help(marker.span, "remove this field"); }); } } diff --git a/tests/ui/manual_non_exhaustive.rs b/tests/ui/manual_non_exhaustive.rs index 9c239db6e00..7a788f48520 100644 --- a/tests/ui/manual_non_exhaustive.rs +++ b/tests/ui/manual_non_exhaustive.rs @@ -9,7 +9,16 @@ mod enums { _C, } - // last variant does not have doc hidden attribute, should be ignored + // user forgot to remove the marker + #[non_exhaustive] + enum Ep { + A, + B, + #[doc(hidden)] + _C, + } + + // marker variant does not have doc hidden attribute, should be ignored enum NoDocHidden { A, B, @@ -32,21 +41,13 @@ mod enums { _C(bool), } - // variant with doc hidden is not the last one, should be ignored - enum NotLast { - A, - #[doc(hidden)] - _B, - C, - } - // variant with doc hidden is the only one, should be ignored enum OnlyMarker { #[doc(hidden)] _A, } - // variant with multiple non-exhaustive "markers", should be ignored + // variant with multiple markers, should be ignored enum MultipleMarkers { A, #[doc(hidden)] @@ -55,7 +56,7 @@ mod enums { _C, } - // already non_exhaustive, should be ignored + // already non_exhaustive and no markers, should be ignored #[non_exhaustive] enum NonExhaustive { A, @@ -70,6 +71,14 @@ mod structs { _c: (), } + // user forgot to remove the private field + #[non_exhaustive] + struct Sp { + pub a: i32, + pub b: i32, + _c: (), + } + // some other fields are private, should be ignored struct PrivateFields { a: i32, @@ -96,7 +105,7 @@ mod structs { _a: (), } - // already non exhaustive, should be ignored + // already non exhaustive and no private fields, should be ignored #[non_exhaustive] struct NonExhaustive { pub a: i32, @@ -107,6 +116,10 @@ mod structs { mod tuple_structs { struct T(pub i32, pub i32, ()); + // user forgot to remove the private field + #[non_exhaustive] + struct Tp(pub i32, pub i32, ()); + // some other fields are private, should be ignored struct PrivateFields(pub i32, i32, ()); @@ -116,7 +129,7 @@ mod tuple_structs { // private field is the only field, should be ignored struct OnlyMarker(()); - // already non exhaustive, should be ignored + // already non exhaustive and no private fields, should be ignored #[non_exhaustive] struct NonExhaustive(pub i32, pub i32); } diff --git a/tests/ui/manual_non_exhaustive.stderr b/tests/ui/manual_non_exhaustive.stderr index d6719bca0d4..613c5e8ca1d 100644 --- a/tests/ui/manual_non_exhaustive.stderr +++ b/tests/ui/manual_non_exhaustive.stderr @@ -1,48 +1,103 @@ error: this seems like a manual implementation of the non-exhaustive pattern --> $DIR/manual_non_exhaustive.rs:5:5 | -LL | / enum E { +LL | enum E { + | ^----- + | | + | _____help: add the attribute: `#[non_exhaustive] enum E` + | | LL | | A, LL | | B, LL | | #[doc(hidden)] LL | | _C, LL | | } - | |_____^ help: add the attribute: `#[non_exhaustive] enum E` + | |_____^ | = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings` -help: and remove this variant +help: remove this variant --> $DIR/manual_non_exhaustive.rs:9:9 | LL | _C, | ^^ error: this seems like a manual implementation of the non-exhaustive pattern - --> $DIR/manual_non_exhaustive.rs:67:5 + --> $DIR/manual_non_exhaustive.rs:14:5 | -LL | / struct S { +LL | / enum Ep { +LL | | A, +LL | | B, +LL | | #[doc(hidden)] +LL | | _C, +LL | | } + | |_____^ + | +help: remove this variant + --> $DIR/manual_non_exhaustive.rs:18:9 + | +LL | _C, + | ^^ + +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:68:5 + | +LL | struct S { + | ^------- + | | + | _____help: add the attribute: `#[non_exhaustive] struct S` + | | LL | | pub a: i32, LL | | pub b: i32, LL | | _c: (), LL | | } - | |_____^ help: add the attribute: `#[non_exhaustive] struct S` + | |_____^ | -help: and remove this field - --> $DIR/manual_non_exhaustive.rs:70:9 +help: remove this field + --> $DIR/manual_non_exhaustive.rs:71:9 | LL | _c: (), | ^^^^^^ error: this seems like a manual implementation of the non-exhaustive pattern - --> $DIR/manual_non_exhaustive.rs:108:5 + --> $DIR/manual_non_exhaustive.rs:76:5 + | +LL | / struct Sp { +LL | | pub a: i32, +LL | | pub b: i32, +LL | | _c: (), +LL | | } + | |_____^ + | +help: remove this field + --> $DIR/manual_non_exhaustive.rs:79:9 + | +LL | _c: (), + | ^^^^^^ + +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:117:5 | LL | struct T(pub i32, pub i32, ()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[non_exhaustive] struct T` + | --------^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: add the attribute: `#[non_exhaustive] struct T` | -help: and remove this field - --> $DIR/manual_non_exhaustive.rs:108:32 +help: remove this field + --> $DIR/manual_non_exhaustive.rs:117:32 | LL | struct T(pub i32, pub i32, ()); | ^^ -error: aborting due to 3 previous errors +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:121:5 + | +LL | struct Tp(pub i32, pub i32, ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove this field + --> $DIR/manual_non_exhaustive.rs:121:33 + | +LL | struct Tp(pub i32, pub i32, ()); + | ^^ + +error: aborting due to 6 previous errors From 10e3f9bdb854e3cabbc4fda69ed713388344d524 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Fri, 1 May 2020 23:02:31 +0200 Subject: [PATCH 018/526] Move match_on_vec_items to pedantic --- clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/match_on_vec_items.rs | 2 +- src/lintlist/mod.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c995be5edc2..06e21a5272e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1138,6 +1138,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP), LintId::of(&loops::EXPLICIT_ITER_LOOP), LintId::of(¯o_use::MACRO_USE_IMPORTS), + LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), LintId::of(&matches::MATCH_BOOL), LintId::of(&matches::SINGLE_MATCH_ELSE), LintId::of(&methods::FILTER_MAP), @@ -1283,7 +1284,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&map_clone::MAP_CLONE), LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN), LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN), - LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), LintId::of(&matches::MATCH_AS_REF), LintId::of(&matches::MATCH_OVERLAPPING_ARM), @@ -1647,7 +1647,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::NEVER_LOOP), LintId::of(&loops::REVERSE_RANGE_LOOP), LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), - LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT), LintId::of(&methods::CLONE_DOUBLE_REF), diff --git a/clippy_lints/src/match_on_vec_items.rs b/clippy_lints/src/match_on_vec_items.rs index 4071406cc84..421571d2f2f 100644 --- a/clippy_lints/src/match_on_vec_items.rs +++ b/clippy_lints/src/match_on_vec_items.rs @@ -38,7 +38,7 @@ declare_clippy_lint! { /// } /// ``` pub MATCH_ON_VEC_ITEMS, - correctness, + pedantic, "matching on vector elements can panic" } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 72675c25175..f337db72ba0 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1146,7 +1146,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ }, Lint { name: "match_on_vec_items", - group: "correctness", + group: "pedantic", desc: "matching on vector elements can panic", deprecation: None, module: "match_on_vec_items", From 350c17de24c0bc7ee1b17981fe02f88ca6ec50a4 Mon Sep 17 00:00:00 2001 From: ebroto <ebroto@tutanota.com> Date: Fri, 1 May 2020 23:00:16 +0200 Subject: [PATCH 019/526] Use the only variant left instead of a wildcard Co-authored-by: Philipp Krones <hello@philkrones.com> --- clippy_lints/src/manual_non_exhaustive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index a4273da1d74..f3b8902e26f 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -133,7 +133,7 @@ fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: let delimiter = match data { VariantData::Struct(..) => '{', VariantData::Tuple(..) => '(', - _ => unreachable!("`VariantData::Unit` is already handled above"), + VariantData::Unit(_) => unreachable!("`VariantData::Unit` is already handled above"), }; cx.sess.source_map().span_until_char(item.span, delimiter) From 72ce6d5be9c54775b847bc0641f8d909b2977126 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Fri, 24 Apr 2020 16:46:56 +0200 Subject: [PATCH 020/526] Fix unwrap lint when checks are done in parameters --- clippy_lints/src/unwrap.rs | 21 ++++++++++----- .../ui/checked_unwrap/simple_conditionals.rs | 27 +++++++++++++++++++ .../checked_unwrap/simple_conditionals.stderr | 24 ++++++++--------- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 5235c98efab..f3844c7d3b6 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,4 +1,7 @@ -use crate::utils::{higher::if_block, is_type_diagnostic_item, span_lint_and_then, usage::is_potentially_mutated}; +use crate::utils::{ + differing_macro_contexts, higher::if_block, is_type_diagnostic_item, span_lint_and_then, + usage::is_potentially_mutated, +}; use if_chain::if_chain; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnOp}; @@ -73,6 +76,8 @@ struct UnwrapInfo<'tcx> { ident: &'tcx Path<'tcx>, /// The check, like `x.is_ok()` check: &'tcx Expr<'tcx>, + /// The branch where the check takes place, like `if x.is_ok() { .. }` + branch: &'tcx Expr<'tcx>, /// Whether `is_some()` or `is_ok()` was called (as opposed to `is_err()` or `is_none()`). safe_to_unwrap: bool, } @@ -82,19 +87,20 @@ struct UnwrapInfo<'tcx> { fn collect_unwrap_info<'a, 'tcx>( cx: &'a LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, + branch: &'tcx Expr<'_>, invert: bool, ) -> Vec<UnwrapInfo<'tcx>> { if let ExprKind::Binary(op, left, right) = &expr.kind { match (invert, op.node) { (false, BinOpKind::And) | (false, BinOpKind::BitAnd) | (true, BinOpKind::Or) | (true, BinOpKind::BitOr) => { - let mut unwrap_info = collect_unwrap_info(cx, left, invert); - unwrap_info.append(&mut collect_unwrap_info(cx, right, invert)); + let mut unwrap_info = collect_unwrap_info(cx, left, branch, invert); + unwrap_info.append(&mut collect_unwrap_info(cx, right, branch, invert)); return unwrap_info; }, _ => (), } } else if let ExprKind::Unary(UnOp::UnNot, expr) = &expr.kind { - return collect_unwrap_info(cx, expr, !invert); + return collect_unwrap_info(cx, expr, branch, !invert); } else { if_chain! { if let ExprKind::MethodCall(method_name, _, args) = &expr.kind; @@ -111,7 +117,7 @@ fn collect_unwrap_info<'a, 'tcx>( _ => unreachable!(), }; let safe_to_unwrap = unwrappable != invert; - return vec![UnwrapInfo { ident: path, check: expr, safe_to_unwrap }]; + return vec![UnwrapInfo { ident: path, check: expr, branch, safe_to_unwrap }]; } } } @@ -121,7 +127,7 @@ fn collect_unwrap_info<'a, 'tcx>( impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> { fn visit_branch(&mut self, cond: &'tcx Expr<'_>, branch: &'tcx Expr<'_>, else_branch: bool) { let prev_len = self.unwrappables.len(); - for unwrap_info in collect_unwrap_info(self.cx, cond, else_branch) { + for unwrap_info in collect_unwrap_info(self.cx, cond, branch, else_branch) { if is_potentially_mutated(unwrap_info.ident, cond, self.cx) || is_potentially_mutated(unwrap_info.ident, branch, self.cx) { @@ -158,6 +164,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { let call_to_unwrap = method_name.ident.name == sym!(unwrap); if let Some(unwrappable) = self.unwrappables.iter() .find(|u| u.ident.res == path.res); + // Span contexts should not differ with the conditional branch + if !differing_macro_contexts(unwrappable.branch.span, expr.span); + if !differing_macro_contexts(unwrappable.branch.span, unwrappable.check.span); then { if call_to_unwrap == unwrappable.safe_to_unwrap { span_lint_and_then( diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs index b0fc26ff76d..3e7b4b390ba 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/tests/ui/checked_unwrap/simple_conditionals.rs @@ -9,6 +9,30 @@ macro_rules! m { }; } +macro_rules! checks_in_param { + ($a:expr, $b:expr) => { + if $a { + $b; + } + }; +} + +macro_rules! checks_unwrap { + ($a:expr, $b:expr) => { + if $a.is_some() { + $b; + } + }; +} + +macro_rules! checks_some { + ($a:expr, $b:expr) => { + if $a { + $b.unwrap(); + } + }; +} + fn main() { let x = Some(()); if x.is_some() { @@ -22,6 +46,9 @@ fn main() { x.unwrap(); // unnecessary } m!(x); + checks_in_param!(x.is_some(), x.unwrap()); // ok + checks_unwrap!(x, x.unwrap()); // ok + checks_some!(x.is_some(), x); // ok let mut x: Result<(), ()> = Ok(()); if x.is_ok() { x.unwrap(); // unnecessary diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr index e40542e2e4f..4013d1ed667 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -1,5 +1,5 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:15:9 + --> $DIR/simple_conditionals.rs:39:9 | LL | if x.is_some() { | ----------- the check is happening here @@ -13,7 +13,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/simple_conditionals.rs:17:9 + --> $DIR/simple_conditionals.rs:41:9 | LL | if x.is_some() { | ----------- because of this check @@ -28,7 +28,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/simple_conditionals.rs:20:9 + --> $DIR/simple_conditionals.rs:44:9 | LL | if x.is_none() { | ----------- because of this check @@ -36,7 +36,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:22:9 + --> $DIR/simple_conditionals.rs:46:9 | LL | if x.is_none() { | ----------- the check is happening here @@ -58,7 +58,7 @@ LL | m!(x); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:27:9 + --> $DIR/simple_conditionals.rs:54:9 | LL | if x.is_ok() { | --------- the check is happening here @@ -66,7 +66,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/simple_conditionals.rs:28:9 + --> $DIR/simple_conditionals.rs:55:9 | LL | if x.is_ok() { | --------- because of this check @@ -75,7 +75,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/simple_conditionals.rs:30:9 + --> $DIR/simple_conditionals.rs:57:9 | LL | if x.is_ok() { | --------- because of this check @@ -84,7 +84,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:31:9 + --> $DIR/simple_conditionals.rs:58:9 | LL | if x.is_ok() { | --------- the check is happening here @@ -93,7 +93,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/simple_conditionals.rs:34:9 + --> $DIR/simple_conditionals.rs:61:9 | LL | if x.is_err() { | ---------- because of this check @@ -101,7 +101,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:35:9 + --> $DIR/simple_conditionals.rs:62:9 | LL | if x.is_err() { | ---------- the check is happening here @@ -110,7 +110,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:37:9 + --> $DIR/simple_conditionals.rs:64:9 | LL | if x.is_err() { | ---------- the check is happening here @@ -119,7 +119,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/simple_conditionals.rs:38:9 + --> $DIR/simple_conditionals.rs:65:9 | LL | if x.is_err() { | ---------- because of this check From d0c1f8ada2306801f2a6ce193e1f9f75471dbb3c Mon Sep 17 00:00:00 2001 From: Aleksei Latyshev <alex_700_95@mail.ru> Date: Sat, 2 May 2020 14:18:27 +0300 Subject: [PATCH 021/526] fix fp on while-let-on-iterator - fix `is_refutable` for slice patterns - fix `is_refutable` for bindings - add some TODO-s for cases, which can not be fixed easily --- clippy_lints/src/utils/mod.rs | 34 ++++++++++------ tests/ui/while_let_on_iterator.fixed | 58 +++++++++++++++++++++++++++ tests/ui/while_let_on_iterator.rs | 58 +++++++++++++++++++++++++++ tests/ui/while_let_on_iterator.stderr | 28 ++++++++++--- 4 files changed, 160 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 04b4b423761..1c7b40fa908 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -933,6 +933,7 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_, '_>, expr: &Exp } /// Returns `true` if a pattern is refutable. +// TODO: should be implemented using rustc/mir_build/hair machinery pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat<'_>) -> bool { fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, id: HirId) -> bool { matches!( @@ -946,27 +947,34 @@ pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat<'_>) -> bool { } match pat.kind { - PatKind::Binding(..) | PatKind::Wild => false, + PatKind::Wild => false, + PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)), PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat), PatKind::Lit(..) | PatKind::Range(..) => true, PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id), - PatKind::Or(ref pats) | PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), + PatKind::Or(ref pats) => { + // TODO: should be the honest check, that pats is exhaustive set + are_refutable(cx, pats.iter().map(|pat| &**pat)) + }, + PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), PatKind::Struct(ref qpath, ref fields, _) => { - if is_enum_variant(cx, qpath, pat.hir_id) { - true - } else { - are_refutable(cx, fields.iter().map(|field| &*field.pat)) - } + is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat)) }, PatKind::TupleStruct(ref qpath, ref pats, _) => { - if is_enum_variant(cx, qpath, pat.hir_id) { - true - } else { - are_refutable(cx, pats.iter().map(|pat| &**pat)) - } + is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats.iter().map(|pat| &**pat)) }, PatKind::Slice(ref head, ref middle, ref tail) => { - are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat)) + match &cx.tables.node_type(pat.hir_id).kind { + ty::Slice(..) => { + // [..] is the only irrefutable slice pattern. + !head.is_empty() || middle.is_none() || !tail.is_empty() + }, + ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat)), + _ => { + // unreachable!() + true + }, + } }, } } diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed index f5fcabf63fd..e99c98ac79f 100644 --- a/tests/ui/while_let_on_iterator.fixed +++ b/tests/ui/while_let_on_iterator.fixed @@ -2,6 +2,7 @@ #![warn(clippy::while_let_on_iterator)] #![allow(clippy::never_loop, unreachable_code, unused_mut)] +#![feature(or_patterns)] fn base() { let mut iter = 1..20; @@ -77,6 +78,62 @@ fn refutable() { // */ } +fn refutable2() { + // Issue 3780 + { + let v = vec![1, 2, 3]; + let mut it = v.windows(2); + while let Some([x, y]) = it.next() { + println!("x: {}", x); + println!("y: {}", y); + } + + let mut it = v.windows(2); + while let Some([x, ..]) = it.next() { + println!("x: {}", x); + } + + let mut it = v.windows(2); + while let Some([.., y]) = it.next() { + println!("y: {}", y); + } + + let mut it = v.windows(2); + for [..] in it {} + + let v = vec![[1], [2], [3]]; + let mut it = v.iter(); + while let Some([1]) = it.next() {} + + let mut it = v.iter(); + for [_x] in it {} + } + + // binding + { + let v = vec![1, 2, 3]; + let mut it = v.iter(); + while let Some(x @ 1) = it.next() { + println!("{}", x); + } + + let v = vec![[1], [2], [3]]; + let mut it = v.iter(); + for x @ [_] in it { + println!("{:?}", x); + } + } + + // false negative + { + let v = vec![1, 2, 3]; + let mut it = v.iter().map(Some); + while let Some(Some(_) | None) = it.next() { + println!("1"); + } + } +} + fn nested_loops() { let a = [42, 1337]; let mut y = a.iter(); @@ -152,6 +209,7 @@ fn issue1654() { fn main() { base(); refutable(); + refutable2(); nested_loops(); issue1121(); issue2965(); diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index 04dce8a0289..ba13172428e 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -2,6 +2,7 @@ #![warn(clippy::while_let_on_iterator)] #![allow(clippy::never_loop, unreachable_code, unused_mut)] +#![feature(or_patterns)] fn base() { let mut iter = 1..20; @@ -77,6 +78,62 @@ fn refutable() { // */ } +fn refutable2() { + // Issue 3780 + { + let v = vec![1, 2, 3]; + let mut it = v.windows(2); + while let Some([x, y]) = it.next() { + println!("x: {}", x); + println!("y: {}", y); + } + + let mut it = v.windows(2); + while let Some([x, ..]) = it.next() { + println!("x: {}", x); + } + + let mut it = v.windows(2); + while let Some([.., y]) = it.next() { + println!("y: {}", y); + } + + let mut it = v.windows(2); + while let Some([..]) = it.next() {} + + let v = vec![[1], [2], [3]]; + let mut it = v.iter(); + while let Some([1]) = it.next() {} + + let mut it = v.iter(); + while let Some([_x]) = it.next() {} + } + + // binding + { + let v = vec![1, 2, 3]; + let mut it = v.iter(); + while let Some(x @ 1) = it.next() { + println!("{}", x); + } + + let v = vec![[1], [2], [3]]; + let mut it = v.iter(); + while let Some(x @ [_]) = it.next() { + println!("{:?}", x); + } + } + + // false negative + { + let v = vec![1, 2, 3]; + let mut it = v.iter().map(Some); + while let Some(Some(_) | None) = it.next() { + println!("1"); + } + } +} + fn nested_loops() { let a = [42, 1337]; let mut y = a.iter(); @@ -152,6 +209,7 @@ fn issue1654() { fn main() { base(); refutable(); + refutable2(); nested_loops(); issue1121(); issue2965(); diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr index 6de138d7227..aa980d9965c 100644 --- a/tests/ui/while_let_on_iterator.stderr +++ b/tests/ui/while_let_on_iterator.stderr @@ -1,5 +1,5 @@ error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:8:5 + --> $DIR/while_let_on_iterator.rs:9:5 | LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` @@ -7,22 +7,40 @@ LL | while let Option::Some(x) = iter.next() { = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:13:5 + --> $DIR/while_let_on_iterator.rs:14:5 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:18:5 + --> $DIR/while_let_on_iterator.rs:19:5 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:97:9 + --> $DIR/while_let_on_iterator.rs:102:9 + | +LL | while let Some([..]) = it.next() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it` + +error: this loop could be written as a `for` loop + --> $DIR/while_let_on_iterator.rs:109:9 + | +LL | while let Some([_x]) = it.next() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it` + +error: this loop could be written as a `for` loop + --> $DIR/while_let_on_iterator.rs:122:9 + | +LL | while let Some(x @ [_]) = it.next() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it` + +error: this loop could be written as a `for` loop + --> $DIR/while_let_on_iterator.rs:154:9 | LL | while let Some(_) = y.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y` -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors From e7138e06291d13163e8ab2a57fe2465451fac193 Mon Sep 17 00:00:00 2001 From: CrazyRoka <RokaRostuk@gmail.com> Date: Sat, 2 May 2020 14:25:45 +0300 Subject: [PATCH 022/526] Fix match on vec items: match on vec[..] - Added new tests - Fixed false positive when matching on full range, which will never panic --- clippy_lints/src/match_on_vec_items.rs | 21 ++++++++++++++++----- tests/ui/match_on_vec_items.rs | 22 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/match_on_vec_items.rs b/clippy_lints/src/match_on_vec_items.rs index 421571d2f2f..236362130e5 100644 --- a/clippy_lints/src/match_on_vec_items.rs +++ b/clippy_lints/src/match_on_vec_items.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_type_diagnostic_item, snippet, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::{is_type_diagnostic_item, match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, MatchSource}; @@ -75,10 +75,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchOnVecItems { fn is_vec_indexing<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { if_chain! { - if let ExprKind::Index(ref array, _) = expr.kind; - let ty = cx.tables.expr_ty(array); - let ty = walk_ptrs_ty(ty); - if is_type_diagnostic_item(cx, ty, sym!(vec_type)); + if let ExprKind::Index(ref array, ref index) = expr.kind; + if is_vector(cx, array); + if !is_full_range(cx, index); then { return Some(expr); @@ -87,3 +86,15 @@ fn is_vec_indexing<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) None } + +fn is_vector(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + let ty = cx.tables.expr_ty(expr); + let ty = walk_ptrs_ty(ty); + is_type_diagnostic_item(cx, ty, sym!(vec_type)) +} + +fn is_full_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + let ty = cx.tables.expr_ty(expr); + let ty = walk_ptrs_ty(ty); + match_type(cx, ty, &["core", "ops", "range", "RangeFull"]) +} diff --git a/tests/ui/match_on_vec_items.rs b/tests/ui/match_on_vec_items.rs index 0bb39d77e46..30415e3b94d 100644 --- a/tests/ui/match_on_vec_items.rs +++ b/tests/ui/match_on_vec_items.rs @@ -120,6 +120,27 @@ fn match_with_array() { } } +fn match_with_endless_range() { + let arr = vec![0, 1, 2, 3]; + let range = ..; + + // Ok + match arr[range] { + [0, 1] => println!("0 1"), + [1, 2] => println!("1 2"), + [0, 1, 2, 3] => println!("0, 1, 2, 3"), + _ => {}, + } + + // Ok + match arr[..] { + [0, 1] => println!("0 1"), + [1, 2] => println!("1 2"), + [0, 1, 2, 3] => println!("0, 1, 2, 3"), + _ => {}, + } +} + fn main() { match_with_wildcard(); match_without_wildcard(); @@ -127,4 +148,5 @@ fn main() { match_vec_ref(); match_with_get(); match_with_array(); + match_with_endless_range(); } From de58c5644de0d9ffe46e7e2923d2301eaf4dd347 Mon Sep 17 00:00:00 2001 From: CrazyRoka <RokaRostuk@gmail.com> Date: Sat, 2 May 2020 17:36:26 +0300 Subject: [PATCH 023/526] Changed RANGE_FULL constant in utils --- clippy_lints/src/match_on_vec_items.rs | 4 ++-- clippy_lints/src/utils/paths.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/match_on_vec_items.rs b/clippy_lints/src/match_on_vec_items.rs index 236362130e5..ee69628e9f0 100644 --- a/clippy_lints/src/match_on_vec_items.rs +++ b/clippy_lints/src/match_on_vec_items.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_type_diagnostic_item, match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::{self, is_type_diagnostic_item, match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, MatchSource}; @@ -96,5 +96,5 @@ fn is_vector(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { fn is_full_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { let ty = cx.tables.expr_ty(expr); let ty = walk_ptrs_ty(ty); - match_type(cx, ty, &["core", "ops", "range", "RangeFull"]) + match_type(cx, ty, &utils::paths::RANGE_FULL) } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index ca2c4ade155..79ca6845c6f 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -85,7 +85,7 @@ pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"]; -pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"]; +pub const RANGE_FULL: [&str; 4] = ["core", "ops", "range", "RangeFull"]; pub const RANGE_FULL_STD: [&str; 3] = ["std", "ops", "RangeFull"]; pub const RANGE_INCLUSIVE_NEW: [&str; 4] = ["core", "ops", "RangeInclusive", "new"]; pub const RANGE_INCLUSIVE_STD_NEW: [&str; 4] = ["std", "ops", "RangeInclusive", "new"]; From 17d877cce28b22b9b345ec7ef8b14859d8b165c4 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sun, 3 May 2020 15:59:57 +0200 Subject: [PATCH 024/526] Update contributing section about syncing Clippy --- CONTRIBUTING.md | 62 +++++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 50a5ee8bbf3..079a51eae3b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -155,47 +155,37 @@ That's why the `else_if_without_else` example uses the `register_early_pass` fun ## Fixing build failures caused by Rust -Clippy will sometimes fail to build from source because building it depends on unstable internal Rust features. Most of -the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. Fixing build failures -caused by Rust updates, can be a good way to learn about Rust internals. +Clippy currently gets build with `rustc` of the `rust-lang/rust` `master` +branch. Most of the times we have to adapt to the changes and only very rarely +there's an actual bug in Rust. -In order to find out why Clippy does not work properly with a new Rust commit, you can use the [rust-toolstate commit -history][toolstate_commit_history]. You will then have to look for the last commit that contains -`test-pass -> build-fail` or `test-pass -> test-fail` for the `clippy-driver` component. -[Here][toolstate_commit] is an example. +If you decide to make Clippy work again with a Rust commit that breaks it, you +have to sync the `rust-lang/rust-clippy` repository with the `subtree` copy of +Clippy in the `rust-lang/rust` repository. -The commit message contains a link to the PR. The PRs are usually small enough to discover the breaking API change and -if they are bigger, they likely include some discussion that may help you to fix Clippy. +For general information about `subtree`s in the Rust repository see [Rust's +`CONTRIBUTING.md`][subtree]. -To check if Clippy is available for a specific target platform, you can check -the [rustup component history][rustup_component_history]. +Here is a TL;DR version of the sync process: -If you decide to make Clippy work again with a Rust commit that breaks it, -you probably want to install the latest Rust from master locally and run Clippy -using that version of Rust. +1. Clone the [`rust-lang/rust`] repository (all of the following commands have + to be run inside the `rust` directory) +2. Sync the changes to the copy of Clippy to your fork of the Clippy repository: + ```bash + # Make sure to change `your-github-name` to your github name in the following command + git subtree push -P src/tools/clippy git@github.com:your-github-name/rust-clippy sync-from-rust + ``` +3. Open a PR to `rust-lang/rust-clippy` and wait for it to get merged (to + accelerate the process ping the `@rust-lang/clippy` team in your PR and/or + ~~annoy~~ ask them in the [Discord] channel.) +4. Sync the `rust-lang/rust-clippy` master to the copy of Clippy: + ```bash + git checkout -b sync-from-clippy + git subtree pull -P src/tools/clippy https://github.com/rust-lang/rust-clippy master + ``` +5. Open a PR to [`rust-lang/rust`] -You can set up the master toolchain by running `./setup-toolchain.sh`. That script will install -[rustup-toolchain-install-master][rtim] and master toolchain, then run `rustup override set master`. - -After fixing the build failure on this repository, we can submit a pull request -to [`rust-lang/rust`] to fix the toolstate. - -To submit a pull request, you should follow these steps: - -```bash -# Assuming you already cloned the rust-lang/rust repo and you're in the correct directory -git submodule update --remote src/tools/clippy -cargo update -p clippy -git add -u -git commit -m "Update Clippy" -./x.py test -i --stage 1 src/tools/clippy # This is optional and should succeed anyway -# Open a PR in rust-lang/rust -``` - -[rustup_component_history]: https://rust-lang.github.io/rustup-components-history -[toolstate_commit_history]: https://github.com/rust-lang-nursery/rust-toolstate/commits/master -[toolstate_commit]: https://github.com/rust-lang-nursery/rust-toolstate/commit/aad74d8294e198a7cf8ac81a91aebb7f3bbcf727 -[rtim]: https://github.com/kennytm/rustup-toolchain-install-master +[subtree]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#external-dependencies-subtree [`rust-lang/rust`]: https://github.com/rust-lang/rust ## Issue and PR triage From c1698fedeb69109f9b1aebc0bfccd9bf3112ccad Mon Sep 17 00:00:00 2001 From: Philipp Krones <hello@philkrones.com> Date: Sun, 3 May 2020 16:47:57 +0200 Subject: [PATCH 025/526] Apply suggestions from code review Co-authored-by: Phil Hansch <dev@phansch.net> --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 079a51eae3b..f7a60938374 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -155,7 +155,7 @@ That's why the `else_if_without_else` example uses the `register_early_pass` fun ## Fixing build failures caused by Rust -Clippy currently gets build with `rustc` of the `rust-lang/rust` `master` +Clippy currently gets built with `rustc` of the `rust-lang/rust` `master` branch. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. @@ -170,7 +170,7 @@ Here is a TL;DR version of the sync process: 1. Clone the [`rust-lang/rust`] repository (all of the following commands have to be run inside the `rust` directory) -2. Sync the changes to the copy of Clippy to your fork of the Clippy repository: +2. Sync the changes to the rust-copy of Clippy to your Clippy fork: ```bash # Make sure to change `your-github-name` to your github name in the following command git subtree push -P src/tools/clippy git@github.com:your-github-name/rust-clippy sync-from-rust @@ -178,7 +178,7 @@ Here is a TL;DR version of the sync process: 3. Open a PR to `rust-lang/rust-clippy` and wait for it to get merged (to accelerate the process ping the `@rust-lang/clippy` team in your PR and/or ~~annoy~~ ask them in the [Discord] channel.) -4. Sync the `rust-lang/rust-clippy` master to the copy of Clippy: +4. Sync the `rust-lang/rust-clippy` master to the rust-copy of Clippy: ```bash git checkout -b sync-from-clippy git subtree pull -P src/tools/clippy https://github.com/rust-lang/rust-clippy master From 7744cf4e53c4e19e5753e2063be420b9d0c0d38a Mon Sep 17 00:00:00 2001 From: Oliver Scherer <github35764891676564198441@oli-obk.de> Date: Mon, 4 May 2020 15:13:07 +0200 Subject: [PATCH 026/526] Update to rustc changes --- clippy_lints/src/redundant_clone.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index d5cace0c647..d563eb886ae 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -591,7 +591,7 @@ struct PossibleBorrowerMap<'a, 'tcx> { impl PossibleBorrowerMap<'_, '_> { /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`. fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool { - self.maybe_live.seek_after(at); + self.maybe_live.seek_after_primary_effect(at); self.bitset.0.clear(); let maybe_live = &mut self.maybe_live; From 780a63a1ba84597eaf33e4d546bcf0edd6225836 Mon Sep 17 00:00:00 2001 From: Oliver Scherer <github35764891676564198441@oli-obk.de> Date: Tue, 5 May 2020 15:11:59 +0200 Subject: [PATCH 027/526] Update ui tests --- tests/ui/builtin-type-shadow.stderr | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index b6a4adde848..bc785b075e0 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -18,8 +18,6 @@ LL | 42 | = note: expected type parameter `u32` found type `{integer}` - = help: type parameters must be constrained to match other types - = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to 2 previous errors From 3b58d66b22fe9107a78b99c267c71322276aa15a Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 7 May 2020 21:41:23 +0200 Subject: [PATCH 028/526] Add the manual_async_fn lint --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 + clippy_lints/src/manual_async_fn.rs | 160 ++++++++++++++++++++++++++++ clippy_lints/src/utils/paths.rs | 3 + src/lintlist/mod.rs | 7 ++ tests/ui/future_not_send.rs | 1 + tests/ui/future_not_send.stderr | 6 +- tests/ui/manual_async_fn.fixed | 55 ++++++++++ tests/ui/manual_async_fn.rs | 67 ++++++++++++ tests/ui/manual_async_fn.stderr | 93 ++++++++++++++++ 10 files changed, 395 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/manual_async_fn.rs create mode 100644 tests/ui/manual_async_fn.fixed create mode 100644 tests/ui/manual_async_fn.rs create mode 100644 tests/ui/manual_async_fn.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index facf363e371..8457d6ad05c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1422,6 +1422,7 @@ Released 2018-09-13 [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion +[`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 97785cba883..fb2e9932b8e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -247,6 +247,7 @@ mod literal_representation; mod loops; mod macro_use; mod main_recursion; +mod manual_async_fn; mod manual_non_exhaustive; mod map_clone; mod map_unit_fn; @@ -629,6 +630,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::WHILE_LET_ON_ITERATOR, ¯o_use::MACRO_USE_IMPORTS, &main_recursion::MAIN_RECURSION, + &manual_async_fn::MANUAL_ASYNC_FN, &manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, &map_clone::MAP_CLONE, &map_unit_fn::OPTION_MAP_UNIT_FN, @@ -1067,6 +1069,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box if_let_mutex::IfLetMutex); store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems); store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive); + store.register_late_pass(|| box manual_async_fn::ManualAsyncFn); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1284,6 +1287,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::WHILE_LET_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), LintId::of(&main_recursion::MAIN_RECURSION), + LintId::of(&manual_async_fn::MANUAL_ASYNC_FN), LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), LintId::of(&map_clone::MAP_CLONE), LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN), @@ -1478,6 +1482,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::NEEDLESS_RANGE_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), LintId::of(&main_recursion::MAIN_RECURSION), + LintId::of(&manual_async_fn::MANUAL_ASYNC_FN), LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), LintId::of(&map_clone::MAP_CLONE), LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs new file mode 100644 index 00000000000..ab8829abbf2 --- /dev/null +++ b/clippy_lints/src/manual_async_fn.rs @@ -0,0 +1,160 @@ +use crate::utils::paths::{FUTURE_CORE, FUTURE_FROM_GENERATOR, FUTURE_STD}; +use crate::utils::{match_function_call, match_path, snippet_block, snippet_opt, span_lint_and_then}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::intravisit::FnKind; +use rustc_hir::{ + AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericBound, HirId, IsAsync, + ItemKind, TraitRef, Ty, TyKind, TypeBindingKind, +}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Span; + +declare_clippy_lint! { + /// **What it does:** It checks for manual implementations of `async` functions. + /// + /// **Why is this bad?** It's more idiomatic to use the dedicated syntax. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// use std::future::Future; + /// + /// fn foo() -> Future<Output = i32> { async { 42 } } + /// ``` + /// Use instead: + /// ```rust + /// use std::future::Future; + /// + /// async fn foo() -> i32 { 42 } + /// ``` + pub MANUAL_ASYNC_FN, + style, + "manual implementations of `async` functions can be simplified using the dedicated syntax" +} + +declare_lint_pass!(ManualAsyncFn => [MANUAL_ASYNC_FN]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ManualAsyncFn { + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + kind: FnKind<'tcx>, + decl: &'tcx FnDecl<'_>, + body: &'tcx Body<'_>, + span: Span, + _: HirId, + ) { + if_chain! { + if let Some(header) = kind.header(); + if let IsAsync::NotAsync = header.asyncness; + // Check that this function returns `impl Future` + if let FnRetTy::Return(ret_ty) = decl.output; + if let Some(trait_ref) = future_trait_ref(cx, ret_ty); + if let Some(output) = future_output_ty(trait_ref); + // Check that the body of the function consists of one async block + if let ExprKind::Block(block, _) = body.value.kind; + if block.stmts.is_empty(); + if let Some(closure_body) = desugared_async_block(cx, block); + then { + let header_span = span.with_hi(ret_ty.span.hi()); + + span_lint_and_then( + cx, + MANUAL_ASYNC_FN, + header_span, + "this function can be simplified using async syntax", + |diag| { + if_chain! { + if let Some(header_snip) = snippet_opt(cx, header_span); + if let Some(ret_pos) = header_snip.rfind("->"); + if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output); + then { + let help = format!("make the function `async` and {}", ret_sugg); + diag.span_suggestion( + header_span, + &help, + format!("async {}{}", &header_snip[..ret_pos], ret_snip), + Applicability::MachineApplicable + ); + + let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span)); + diag.span_suggestion( + block.span, + "move the body of the async block to the enclosing function", + body_snip.to_string(), + Applicability::MachineApplicable + ); + } + } + }, + ); + } + } + } +} + +fn future_trait_ref<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &'tcx Ty<'tcx>) -> Option<&'tcx TraitRef<'tcx>> { + if_chain! { + if let TyKind::Def(item_id, _) = ty.kind; + let item = cx.tcx.hir().item(item_id.id); + if let ItemKind::OpaqueTy(opaque) = &item.kind; + if opaque.bounds.len() == 1; + if let GenericBound::Trait(poly, _) = &opaque.bounds[0]; + let path = poly.trait_ref.path; + if match_path(&path, &FUTURE_CORE) || match_path(&path, &FUTURE_STD); + then { + return Some(&poly.trait_ref); + } + } + + None +} + +fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'tcx>> { + if_chain! { + if let Some(segment) = trait_ref.path.segments.last(); + if let Some(args) = segment.args; + if args.bindings.len() == 1; + let binding = &args.bindings[0]; + if binding.ident.as_str() == "Output"; + if let TypeBindingKind::Equality{ty: output} = binding.kind; + then { + return Some(output) + } + } + + None +} + +fn desugared_async_block<'tcx>(cx: &LateContext<'_, 'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> { + if_chain! { + if let Some(block_expr) = block.expr; + if let Some(args) = match_function_call(cx, block_expr, &FUTURE_FROM_GENERATOR); + if args.len() == 1; + if let Expr{kind: ExprKind::Closure(_, _, body_id, ..), ..} = args[0]; + let closure_body = cx.tcx.hir().body(body_id); + if let Some(GeneratorKind::Async(AsyncGeneratorKind::Block)) = closure_body.generator_kind; + then { + return Some(closure_body); + } + } + + None +} + +fn suggested_ret(cx: &LateContext<'_, '_>, output: &Ty<'_>) -> Option<(&'static str, String)> { + match output.kind { + TyKind::Tup(tys) if tys.is_empty() => { + let sugg = "remove the return type"; + Some((sugg, "".into())) + }, + _ => { + let sugg = "return the output of the future directly"; + snippet_opt(cx, output.span).map(|snip| (sugg, format!("-> {}", snip))) + }, + } +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 79ca6845c6f..74040a96c78 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -42,6 +42,9 @@ pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; +pub const FUTURE_CORE: [&str; 3] = ["core", "future", "Future"]; +pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"]; +pub const FUTURE_STD: [&str; 3] = ["std", "future", "Future"]; pub const HASH: [&str; 2] = ["hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index a7685f67211..51d1cb2216a 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1081,6 +1081,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "main_recursion", }, + Lint { + name: "manual_async_fn", + group: "style", + desc: "manual implementations of `async` functions can be simplified using the dedicated syntax", + deprecation: None, + module: "manual_async_fn", + }, Lint { name: "manual_memcpy", group: "perf", diff --git a/tests/ui/future_not_send.rs b/tests/ui/future_not_send.rs index 6d09d71a630..d3a920de4b6 100644 --- a/tests/ui/future_not_send.rs +++ b/tests/ui/future_not_send.rs @@ -41,6 +41,7 @@ impl Dummy { self.private_future().await; } + #[allow(clippy::manual_async_fn)] pub fn public_send(&self) -> impl std::future::Future<Output = bool> { async { false } } diff --git a/tests/ui/future_not_send.stderr b/tests/ui/future_not_send.stderr index 3b4968ef0a6..d1863701bfe 100644 --- a/tests/ui/future_not_send.stderr +++ b/tests/ui/future_not_send.stderr @@ -96,13 +96,13 @@ LL | } = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:49:37 + --> $DIR/future_not_send.rs:50:37 | LL | async fn generic_future<T>(t: T) -> T | ^ future returned by `generic_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:54:5 + --> $DIR/future_not_send.rs:55:5 | LL | let rt = &t; | -- has type `&T` which is not `Send` @@ -114,7 +114,7 @@ LL | } = note: `T` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:65:34 + --> $DIR/future_not_send.rs:66:34 | LL | async fn unclear_future<T>(t: T) {} | ^ diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed new file mode 100644 index 00000000000..84c02bba4dc --- /dev/null +++ b/tests/ui/manual_async_fn.fixed @@ -0,0 +1,55 @@ +// run-rustfix +// edition:2018 +#![warn(clippy::manual_async_fn)] +#![allow(unused)] + +use std::future::Future; + +async fn fut() -> i32 { 42 } + +async fn empty_fut() {} + +async fn core_fut() -> i32 { 42 } + +// should be ignored +fn has_other_stmts() -> impl core::future::Future<Output = i32> { + let _ = 42; + async move { 42 } +} + +// should be ignored +fn not_fut() -> i32 { + 42 +} + +// should be ignored +async fn already_async() -> impl Future<Output = i32> { + async { 42 } +} + +struct S {} +impl S { + async fn inh_fut() -> i32 { 42 } + + async fn meth_fut(&self) -> i32 { 42 } + + async fn empty_fut(&self) {} + + // should be ignored + fn not_fut(&self) -> i32 { + 42 + } + + // should be ignored + fn has_other_stmts() -> impl core::future::Future<Output = i32> { + let _ = 42; + async move { 42 } + } + + // should be ignored + async fn already_async(&self) -> impl Future<Output = i32> { + async { 42 } + } +} + +fn main() {} diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs new file mode 100644 index 00000000000..bd5f9d1cf5f --- /dev/null +++ b/tests/ui/manual_async_fn.rs @@ -0,0 +1,67 @@ +// run-rustfix +// edition:2018 +#![warn(clippy::manual_async_fn)] +#![allow(unused)] + +use std::future::Future; + +fn fut() -> impl Future<Output = i32> { + async { 42 } +} + +fn empty_fut() -> impl Future<Output = ()> { + async {} +} + +fn core_fut() -> impl core::future::Future<Output = i32> { + async move { 42 } +} + +// should be ignored +fn has_other_stmts() -> impl core::future::Future<Output = i32> { + let _ = 42; + async move { 42 } +} + +// should be ignored +fn not_fut() -> i32 { + 42 +} + +// should be ignored +async fn already_async() -> impl Future<Output = i32> { + async { 42 } +} + +struct S {} +impl S { + fn inh_fut() -> impl Future<Output = i32> { + async { 42 } + } + + fn meth_fut(&self) -> impl Future<Output = i32> { + async { 42 } + } + + fn empty_fut(&self) -> impl Future<Output = ()> { + async {} + } + + // should be ignored + fn not_fut(&self) -> i32 { + 42 + } + + // should be ignored + fn has_other_stmts() -> impl core::future::Future<Output = i32> { + let _ = 42; + async move { 42 } + } + + // should be ignored + async fn already_async(&self) -> impl Future<Output = i32> { + async { 42 } + } +} + +fn main() {} diff --git a/tests/ui/manual_async_fn.stderr b/tests/ui/manual_async_fn.stderr new file mode 100644 index 00000000000..016fdf95977 --- /dev/null +++ b/tests/ui/manual_async_fn.stderr @@ -0,0 +1,93 @@ +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:8:1 + | +LL | fn fut() -> impl Future<Output = i32> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::manual-async-fn` implied by `-D warnings` +help: make the function `async` and return the output of the future directly + | +LL | async fn fut() -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn fut() -> impl Future<Output = i32> { 42 } + | ^^^^^^ + +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:12:1 + | +LL | fn empty_fut() -> impl Future<Output = ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `async` and remove the return type + | +LL | async fn empty_fut() { + | ^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn empty_fut() -> impl Future<Output = ()> {} + | ^^ + +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:16:1 + | +LL | fn core_fut() -> impl core::future::Future<Output = i32> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `async` and return the output of the future directly + | +LL | async fn core_fut() -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn core_fut() -> impl core::future::Future<Output = i32> { 42 } + | ^^^^^^ + +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:38:5 + | +LL | fn inh_fut() -> impl Future<Output = i32> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `async` and return the output of the future directly + | +LL | async fn inh_fut() -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn inh_fut() -> impl Future<Output = i32> { 42 } + | ^^^^^^ + +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:42:5 + | +LL | fn meth_fut(&self) -> impl Future<Output = i32> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `async` and return the output of the future directly + | +LL | async fn meth_fut(&self) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn meth_fut(&self) -> impl Future<Output = i32> { 42 } + | ^^^^^^ + +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:46:5 + | +LL | fn empty_fut(&self) -> impl Future<Output = ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `async` and remove the return type + | +LL | async fn empty_fut(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn empty_fut(&self) -> impl Future<Output = ()> {} + | ^^ + +error: aborting due to 6 previous errors + From 4ac348b30849ec472564a81797b7e9ae42985460 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 7 May 2020 22:03:38 +0200 Subject: [PATCH 029/526] Fix doc comment in lint declaration --- clippy_lints/src/manual_async_fn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs index ab8829abbf2..b4be3ecfd16 100644 --- a/clippy_lints/src/manual_async_fn.rs +++ b/clippy_lints/src/manual_async_fn.rs @@ -23,7 +23,7 @@ declare_clippy_lint! { /// ```rust /// use std::future::Future; /// - /// fn foo() -> Future<Output = i32> { async { 42 } } + /// fn foo() -> impl Future<Output = i32> { async { 42 } } /// ``` /// Use instead: /// ```rust From 3e4bc026e2706b1cb21bad6d55726f8b5a1d4cf1 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 7 May 2020 22:40:28 +0200 Subject: [PATCH 030/526] Apply suggestions from PR review --- clippy_lints/src/manual_async_fn.rs | 9 ++++----- clippy_lints/src/utils/paths.rs | 2 -- tests/ui/manual_async_fn.fixed | 14 +++++++++++++- tests/ui/manual_async_fn.rs | 14 +++++++++++++- tests/ui/manual_async_fn.stderr | 25 +++++++++++++++---------- 5 files changed, 45 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs index b4be3ecfd16..cb72a240582 100644 --- a/clippy_lints/src/manual_async_fn.rs +++ b/clippy_lints/src/manual_async_fn.rs @@ -1,5 +1,5 @@ -use crate::utils::paths::{FUTURE_CORE, FUTURE_FROM_GENERATOR, FUTURE_STD}; -use crate::utils::{match_function_call, match_path, snippet_block, snippet_opt, span_lint_and_then}; +use crate::utils::paths::FUTURE_FROM_GENERATOR; +use crate::utils::{match_function_call, snippet_block, snippet_opt, span_lint_and_then}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; @@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ManualAsyncFn { cx, MANUAL_ASYNC_FN, header_span, - "this function can be simplified using async syntax", + "this function can be simplified using the `async fn` syntax", |diag| { if_chain! { if let Some(header_snip) = snippet_opt(cx, header_span); @@ -104,8 +104,7 @@ fn future_trait_ref<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &'tcx Ty<'tcx>) -> Opt if let ItemKind::OpaqueTy(opaque) = &item.kind; if opaque.bounds.len() == 1; if let GenericBound::Trait(poly, _) = &opaque.bounds[0]; - let path = poly.trait_ref.path; - if match_path(&path, &FUTURE_CORE) || match_path(&path, &FUTURE_STD); + if poly.trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait(); then { return Some(&poly.trait_ref); } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 74040a96c78..b3ad2ad9d99 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -42,9 +42,7 @@ pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; -pub const FUTURE_CORE: [&str; 3] = ["core", "future", "Future"]; pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"]; -pub const FUTURE_STD: [&str; 3] = ["std", "future", "Future"]; pub const HASH: [&str; 2] = ["hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed index 84c02bba4dc..6bb1032a172 100644 --- a/tests/ui/manual_async_fn.fixed +++ b/tests/ui/manual_async_fn.fixed @@ -29,7 +29,19 @@ async fn already_async() -> impl Future<Output = i32> { struct S {} impl S { - async fn inh_fut() -> i32 { 42 } + async fn inh_fut() -> i32 { + // NOTE: this code is here just to check that the identation is correct in the suggested fix + let a = 42; + let b = 21; + if a < b { + let c = 21; + let d = 42; + if c < d { + let _ = 42; + } + } + 42 + } async fn meth_fut(&self) -> i32 { 42 } diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs index bd5f9d1cf5f..d50c919188b 100644 --- a/tests/ui/manual_async_fn.rs +++ b/tests/ui/manual_async_fn.rs @@ -36,7 +36,19 @@ async fn already_async() -> impl Future<Output = i32> { struct S {} impl S { fn inh_fut() -> impl Future<Output = i32> { - async { 42 } + async { + // NOTE: this code is here just to check that the identation is correct in the suggested fix + let a = 42; + let b = 21; + if a < b { + let c = 21; + let d = 42; + if c < d { + let _ = 42; + } + } + 42 + } } fn meth_fut(&self) -> impl Future<Output = i32> { diff --git a/tests/ui/manual_async_fn.stderr b/tests/ui/manual_async_fn.stderr index 016fdf95977..f278ee41aa3 100644 --- a/tests/ui/manual_async_fn.stderr +++ b/tests/ui/manual_async_fn.stderr @@ -1,4 +1,4 @@ -error: this function can be simplified using async syntax +error: this function can be simplified using the `async fn` syntax --> $DIR/manual_async_fn.rs:8:1 | LL | fn fut() -> impl Future<Output = i32> { @@ -14,7 +14,7 @@ help: move the body of the async block to the enclosing function LL | fn fut() -> impl Future<Output = i32> { 42 } | ^^^^^^ -error: this function can be simplified using async syntax +error: this function can be simplified using the `async fn` syntax --> $DIR/manual_async_fn.rs:12:1 | LL | fn empty_fut() -> impl Future<Output = ()> { @@ -29,7 +29,7 @@ help: move the body of the async block to the enclosing function LL | fn empty_fut() -> impl Future<Output = ()> {} | ^^ -error: this function can be simplified using async syntax +error: this function can be simplified using the `async fn` syntax --> $DIR/manual_async_fn.rs:16:1 | LL | fn core_fut() -> impl core::future::Future<Output = i32> { @@ -44,7 +44,7 @@ help: move the body of the async block to the enclosing function LL | fn core_fut() -> impl core::future::Future<Output = i32> { 42 } | ^^^^^^ -error: this function can be simplified using async syntax +error: this function can be simplified using the `async fn` syntax --> $DIR/manual_async_fn.rs:38:5 | LL | fn inh_fut() -> impl Future<Output = i32> { @@ -56,11 +56,16 @@ LL | async fn inh_fut() -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: move the body of the async block to the enclosing function | -LL | fn inh_fut() -> impl Future<Output = i32> { 42 } - | ^^^^^^ +LL | fn inh_fut() -> impl Future<Output = i32> { +LL | // NOTE: this code is here just to check that the identation is correct in the suggested fix +LL | let a = 42; +LL | let b = 21; +LL | if a < b { +LL | let c = 21; + ... -error: this function can be simplified using async syntax - --> $DIR/manual_async_fn.rs:42:5 +error: this function can be simplified using the `async fn` syntax + --> $DIR/manual_async_fn.rs:54:5 | LL | fn meth_fut(&self) -> impl Future<Output = i32> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,8 +79,8 @@ help: move the body of the async block to the enclosing function LL | fn meth_fut(&self) -> impl Future<Output = i32> { 42 } | ^^^^^^ -error: this function can be simplified using async syntax - --> $DIR/manual_async_fn.rs:46:5 +error: this function can be simplified using the `async fn` syntax + --> $DIR/manual_async_fn.rs:58:5 | LL | fn empty_fut(&self) -> impl Future<Output = ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 438877380a2bf591fc1294ab31bc7fb2598738ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Sat, 9 May 2020 01:27:30 +0200 Subject: [PATCH 031/526] deps: remove unused regex dependency from root crate --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 63ce2cd8cad..6999b6bd740 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,6 @@ path = "src/driver.rs" # begin automatic update clippy_lints = { version = "0.0.212", path = "clippy_lints" } # end automatic update -regex = "1" semver = "0.9" rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} tempfile = { version = "3.1.0", optional = true } From 0c14ea8ed79ebf0b7368659282136e876f247cc9 Mon Sep 17 00:00:00 2001 From: Glenn Hope <glenn.alexander.hope@gmail.com> Date: Sun, 3 May 2020 10:56:25 -0700 Subject: [PATCH 032/526] Allow 'use super::*;' imports --- clippy_lints/src/wildcard_imports.rs | 19 +++++++++++--- tests/ui/wildcard_imports.fixed | 38 ++++++++++++++++++++++++++++ tests/ui/wildcard_imports.rs | 38 ++++++++++++++++++++++++++++ tests/ui/wildcard_imports.stderr | 20 ++++++++++++++- 4 files changed, 111 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index f3038861cee..70ad9a60a02 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -3,7 +3,7 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ def::{DefKind, Res}, - Item, ItemKind, UseKind, + Item, ItemKind, PathSegment, UseKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -83,8 +83,8 @@ impl LateLintPass<'_, '_> for WildcardImports { if_chain! { if !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; - // don't lint prelude glob imports - if !use_path.segments.iter().last().map_or(false, |ps| ps.ident.as_str() == "prelude"); + if !is_prelude_import(use_path.segments); + if !is_super_only_import_in_test(use_path.segments); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner); if !used_imports.is_empty(); // Already handled by `unused_imports` then { @@ -154,3 +154,16 @@ impl LateLintPass<'_, '_> for WildcardImports { } } } + +// Allow "...prelude::*" imports. +// Many crates have a prelude, and it is imported as a glob by design. +fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { + segments.iter().last().map_or(false, |ps| ps.ident.as_str() == "prelude") +} + +// Allow "super::*" imports. +// This is intended primarily to ease the process of writing unit tests. +fn is_super_only_import_in_test(segments: &[PathSegment<'_>]) -> bool { + segments.iter().len() == 1 && + segments.first().map_or(false, |ps| ps.ident.as_str() == "super") +} diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index ed6cc00ef04..003f11009a0 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -155,3 +155,41 @@ fn test_weird_formatting() { exported(); foo(); } + +mod test_super_imports { + fn foofoo() {} + + mod use_super { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod use_explicit { + use test_super_imports::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } + + mod use_double_super { + mod inner { + use super::super::foofoo; + + fn with_double_super() { + let _ = foofoo(); + } + } + } + + mod use_super_explicit { + use super::super::test_super_imports::foofoo; + + fn with_super_explicit() { + let _ = foofoo(); + } + } +} diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index c6d6efaece8..7bd57c7965a 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -156,3 +156,41 @@ fn test_weird_formatting() { exported(); foo(); } + +mod test_super_imports { + fn foofoo() {} + + mod use_super { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod use_explicit { + use test_super_imports::*; + + fn with_explicit() { + let _ = foofoo(); + } + } + + mod use_double_super { + mod inner { + use super::super::*; + + fn with_double_super() { + let _ = foofoo(); + } + } + } + + mod use_super_explicit { + use super::super::test_super_imports::*; + + fn with_super_explicit() { + let _ = foofoo(); + } + } +} diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 050e4c6304f..858dc28797f 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -92,5 +92,23 @@ LL | use crate:: fn_mod:: LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` -error: aborting due to 15 previous errors +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:172:13 + | +LL | use test_super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `test_super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:181:17 + | +LL | use super::super::*; + | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:190:13 + | +LL | use super::super::test_super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::test_super_imports::foofoo` + +error: aborting due to 18 previous errors From bdc75dbb7bbdc379b1f8cc346151fac4e63d7deb Mon Sep 17 00:00:00 2001 From: Glenn Hope <glenn.alexander.hope@gmail.com> Date: Sun, 3 May 2020 11:18:10 -0700 Subject: [PATCH 033/526] Run `cargo dev fmt` --- clippy_lints/src/wildcard_imports.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 70ad9a60a02..e7400642b07 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -158,12 +158,14 @@ impl LateLintPass<'_, '_> for WildcardImports { // Allow "...prelude::*" imports. // Many crates have a prelude, and it is imported as a glob by design. fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { - segments.iter().last().map_or(false, |ps| ps.ident.as_str() == "prelude") + segments + .iter() + .last() + .map_or(false, |ps| ps.ident.as_str() == "prelude") } // Allow "super::*" imports. // This is intended primarily to ease the process of writing unit tests. fn is_super_only_import_in_test(segments: &[PathSegment<'_>]) -> bool { - segments.iter().len() == 1 && - segments.first().map_or(false, |ps| ps.ident.as_str() == "super") + segments.iter().len() == 1 && segments.first().map_or(false, |ps| ps.ident.as_str() == "super") } From 56f4e1c3a8be54c1c80de366618e83d8d7a6e9eb Mon Sep 17 00:00:00 2001 From: Glenn Hope <glenn.alexander.hope@gmail.com> Date: Thu, 7 May 2020 08:06:30 -0700 Subject: [PATCH 034/526] Check if the parent module name contains "test" --- clippy_lints/src/wildcard_imports.rs | 19 ++++++++++++------- tests/ui/wildcard_imports.fixed | 16 ++++++++++++---- tests/ui/wildcard_imports.rs | 16 ++++++++++++---- tests/ui/wildcard_imports.stderr | 14 ++++++++++---- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index e7400642b07..a22d0e6775d 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -84,7 +84,7 @@ impl LateLintPass<'_, '_> for WildcardImports { if !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; if !is_prelude_import(use_path.segments); - if !is_super_only_import_in_test(use_path.segments); + if !(is_super_only_import(use_path.segments) && is_in_test_module(cx, item)); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner); if !used_imports.is_empty(); // Already handled by `unused_imports` then { @@ -109,8 +109,7 @@ impl LateLintPass<'_, '_> for WildcardImports { span = use_path.span.with_hi(item.span.hi() - BytePos(1)); } ( - span, - false, + span, false, ) }; @@ -164,8 +163,14 @@ fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { .map_or(false, |ps| ps.ident.as_str() == "prelude") } -// Allow "super::*" imports. -// This is intended primarily to ease the process of writing unit tests. -fn is_super_only_import_in_test(segments: &[PathSegment<'_>]) -> bool { - segments.iter().len() == 1 && segments.first().map_or(false, |ps| ps.ident.as_str() == "super") +// Allow "super::*" imports in tests. +fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { + segments.len() == 1 && segments[0].ident.as_str() == "super" +} + +fn is_in_test_module(cx: &LateContext<'_, '_>, item: &Item<'_>) -> bool { + let parent = cx.tcx.hir().get_parent_node(item.hir_id); + let parent_item = cx.tcx.hir().expect_item(parent); + let parent_name = parent_item.ident.name.as_str(); + parent_name.contains("test") } diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 003f11009a0..1c5c01f65d1 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -159,7 +159,15 @@ fn test_weird_formatting() { mod test_super_imports { fn foofoo() {} - mod use_super { + mod use_super_should_be_replaced { + use super::foofoo; + + fn with_super() { + let _ = foofoo(); + } + } + + mod use_super_in_test_should_pass { use super::*; fn with_super() { @@ -167,7 +175,7 @@ mod test_super_imports { } } - mod use_explicit { + mod use_explicit_should_be_replaced { use test_super_imports::foofoo; fn with_explicit() { @@ -175,7 +183,7 @@ mod test_super_imports { } } - mod use_double_super { + mod use_double_super_should_be_replaced { mod inner { use super::super::foofoo; @@ -185,7 +193,7 @@ mod test_super_imports { } } - mod use_super_explicit { + mod use_super_explicit_should_be_replaced { use super::super::test_super_imports::foofoo; fn with_super_explicit() { diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 7bd57c7965a..f783149ef93 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -160,7 +160,7 @@ fn test_weird_formatting() { mod test_super_imports { fn foofoo() {} - mod use_super { + mod use_super_should_be_replaced { use super::*; fn with_super() { @@ -168,7 +168,15 @@ mod test_super_imports { } } - mod use_explicit { + mod use_super_in_test_should_pass { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod use_explicit_should_be_replaced { use test_super_imports::*; fn with_explicit() { @@ -176,7 +184,7 @@ mod test_super_imports { } } - mod use_double_super { + mod use_double_super_should_be_replaced { mod inner { use super::super::*; @@ -186,7 +194,7 @@ mod test_super_imports { } } - mod use_super_explicit { + mod use_super_explicit_should_be_replaced { use super::super::test_super_imports::*; fn with_super_explicit() { diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 858dc28797f..649d550a88d 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -93,22 +93,28 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:172:13 + --> $DIR/wildcard_imports.rs:164:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:180:13 | LL | use test_super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^ help: try: `test_super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:181:17 + --> $DIR/wildcard_imports.rs:189:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:190:13 + --> $DIR/wildcard_imports.rs:198:13 | LL | use super::super::test_super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::test_super_imports::foofoo` -error: aborting due to 18 previous errors +error: aborting due to 19 previous errors From ad92486d52fdede5c712dd27c868c942d8240704 Mon Sep 17 00:00:00 2001 From: Glenn Hope <glenn.alexander.hope@gmail.com> Date: Thu, 7 May 2020 14:41:54 -0700 Subject: [PATCH 035/526] Add check for "test" in parent name. Include flag for disabling wildcard import exceptions --- clippy_lints/src/lib.rs | 3 +- clippy_lints/src/utils/conf.rs | 2 + clippy_lints/src/wildcard_imports.rs | 48 +++++++++++++++---- .../toml_unknown_key/conf_unknown_key.stderr | 2 +- tests/ui/wildcard_imports.fixed | 17 +++++-- tests/ui/wildcard_imports.rs | 17 +++++-- tests/ui/wildcard_imports.stderr | 14 +++--- 7 files changed, 75 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index fb2e9932b8e..4b67c84e38e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1058,7 +1058,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let max_struct_bools = conf.max_struct_bools; store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools)); store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); - store.register_late_pass(|| box wildcard_imports::WildcardImports); + let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports; + store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)); store.register_early_pass(|| box macro_use::MacroUseImports); store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default()); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 4b81ff33495..57b9eafd14d 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -158,6 +158,8 @@ define_Conf! { (max_struct_bools, "max_struct_bools": u64, 3), /// Lint: FN_PARAMS_EXCESSIVE_BOOLS. The maximum number of bools function parameters can have (max_fn_params_bools, "max_fn_params_bools": u64, 3), + /// Lint: WILDCARD_IMPORTS. Whether to allow certain wildcard imports (prelude, super in tests). + (warn_on_all_wildcard_imports, "warn_on_all_wildcard_imports": bool, false), } impl Default for Conf { diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index a22d0e6775d..43d0d1b9e96 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -6,7 +6,7 @@ use rustc_hir::{ Item, ItemKind, PathSegment, UseKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::BytePos; declare_clippy_lint! { @@ -73,18 +73,38 @@ declare_clippy_lint! { "lint `use _::*` statements" } -declare_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]); +#[derive(Default)] +pub struct WildcardImports { + warn_on_all: bool, + is_test_module: bool, + test_modules_deep: u32, +} + +impl WildcardImports { + pub fn new(warn_on_all: bool) -> Self { + Self { + warn_on_all, + is_test_module: false, + test_modules_deep: 0, + } + } +} + +impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]); impl LateLintPass<'_, '_> for WildcardImports { fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) { if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { return; } + if is_test_module(item) { + self.is_test_module = true; + self.test_modules_deep += 1; + } if_chain! { if !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; - if !is_prelude_import(use_path.segments); - if !(is_super_only_import(use_path.segments) && is_in_test_module(cx, item)); + if self.warn_on_all || !self.check_exceptions(use_path.segments); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner); if !used_imports.is_empty(); // Already handled by `unused_imports` then { @@ -152,6 +172,19 @@ impl LateLintPass<'_, '_> for WildcardImports { } } } + + fn check_item_post(&mut self, _: &LateContext<'_, '_>, _: &Item<'_>) { + if self.is_test_module { + self.is_test_module = false; + self.test_modules_deep -= 1; + } + } +} + +impl WildcardImports { + fn check_exceptions(&self, segments: &[PathSegment<'_>]) -> bool { + is_prelude_import(segments) || (is_super_only_import(segments) && self.test_modules_deep > 0) + } } // Allow "...prelude::*" imports. @@ -168,9 +201,6 @@ fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { segments.len() == 1 && segments[0].ident.as_str() == "super" } -fn is_in_test_module(cx: &LateContext<'_, '_>, item: &Item<'_>) -> bool { - let parent = cx.tcx.hir().get_parent_node(item.hir_id); - let parent_item = cx.tcx.hir().expect_item(parent); - let parent_name = parent_item.ident.name.as_str(); - parent_name.contains("test") +fn is_test_module(item: &Item<'_>) -> bool { + item.ident.name.as_str().contains("test") } diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 18f5d994ba8..53970af4107 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,4 +1,4 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-struct-bools`, `max-fn-params-bools`, `third-party` at line 5 column 1 +error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `third-party` at line 5 column 1 error: aborting due to previous error diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 1c5c01f65d1..98bf6acfe55 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -156,10 +156,10 @@ fn test_weird_formatting() { foo(); } -mod test_super_imports { +mod super_imports { fn foofoo() {} - mod use_super_should_be_replaced { + mod should_be_replaced { use super::foofoo; fn with_super() { @@ -167,7 +167,7 @@ mod test_super_imports { } } - mod use_super_in_test_should_pass { + mod test_should_pass { use super::*; fn with_super() { @@ -175,8 +175,15 @@ mod test_super_imports { } } + mod inner { + fn test_should_pass() { + use super::*; + let _ = foofoo(); + } + } + mod use_explicit_should_be_replaced { - use test_super_imports::foofoo; + use super_imports::foofoo; fn with_explicit() { let _ = foofoo(); @@ -194,7 +201,7 @@ mod test_super_imports { } mod use_super_explicit_should_be_replaced { - use super::super::test_super_imports::foofoo; + use super::super::super_imports::foofoo; fn with_super_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index f783149ef93..9275c5a0928 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -157,10 +157,10 @@ fn test_weird_formatting() { foo(); } -mod test_super_imports { +mod super_imports { fn foofoo() {} - mod use_super_should_be_replaced { + mod should_be_replaced { use super::*; fn with_super() { @@ -168,7 +168,7 @@ mod test_super_imports { } } - mod use_super_in_test_should_pass { + mod test_should_pass { use super::*; fn with_super() { @@ -176,8 +176,15 @@ mod test_super_imports { } } + mod inner { + fn test_should_pass() { + use super::*; + let _ = foofoo(); + } + } + mod use_explicit_should_be_replaced { - use test_super_imports::*; + use super_imports::*; fn with_explicit() { let _ = foofoo(); @@ -195,7 +202,7 @@ mod test_super_imports { } mod use_super_explicit_should_be_replaced { - use super::super::test_super_imports::*; + use super::super::super_imports::*; fn with_super_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 649d550a88d..bd000ce8161 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -99,22 +99,22 @@ LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:180:13 + --> $DIR/wildcard_imports.rs:187:13 | -LL | use test_super_imports::*; - | ^^^^^^^^^^^^^^^^^^^^^ help: try: `test_super_imports::foofoo` +LL | use super_imports::*; + | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:189:17 + --> $DIR/wildcard_imports.rs:196:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:198:13 + --> $DIR/wildcard_imports.rs:205:13 | -LL | use super::super::test_super_imports::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::test_super_imports::foofoo` +LL | use super::super::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: aborting due to 19 previous errors From a42a2bdac2a6c881f85ebdbce66e84d977c74cfa Mon Sep 17 00:00:00 2001 From: Glenn Hope <glenn.alexander.hope@gmail.com> Date: Thu, 7 May 2020 14:48:27 -0700 Subject: [PATCH 036/526] Also have flag disable macro check --- clippy_lints/src/wildcard_imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 43d0d1b9e96..843ddda0356 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -102,7 +102,7 @@ impl LateLintPass<'_, '_> for WildcardImports { self.test_modules_deep += 1; } if_chain! { - if !in_macro(item.span); + if self.warn_on_all || !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; if self.warn_on_all || !self.check_exceptions(use_path.segments); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner); From 152cdcb45be7a8f0f24dbcd4177e0858d94516b6 Mon Sep 17 00:00:00 2001 From: Glenn Hope <glenn.alexander.hope@gmail.com> Date: Fri, 8 May 2020 18:22:27 -0700 Subject: [PATCH 037/526] Remove unnecessary field, check for Mod/Fn ItemKind --- clippy_lints/src/wildcard_imports.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 843ddda0356..48405a00d55 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -76,7 +76,6 @@ declare_clippy_lint! { #[derive(Default)] pub struct WildcardImports { warn_on_all: bool, - is_test_module: bool, test_modules_deep: u32, } @@ -84,7 +83,6 @@ impl WildcardImports { pub fn new(warn_on_all: bool) -> Self { Self { warn_on_all, - is_test_module: false, test_modules_deep: 0, } } @@ -97,8 +95,7 @@ impl LateLintPass<'_, '_> for WildcardImports { if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { return; } - if is_test_module(item) { - self.is_test_module = true; + if is_test_module_or_function(item) { self.test_modules_deep += 1; } if_chain! { @@ -173,9 +170,8 @@ impl LateLintPass<'_, '_> for WildcardImports { } } - fn check_item_post(&mut self, _: &LateContext<'_, '_>, _: &Item<'_>) { - if self.is_test_module { - self.is_test_module = false; + fn check_item_post(&mut self, _: &LateContext<'_, '_>, item: &Item<'_>) { + if is_test_module_or_function(item) { self.test_modules_deep -= 1; } } @@ -201,6 +197,6 @@ fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { segments.len() == 1 && segments[0].ident.as_str() == "super" } -fn is_test_module(item: &Item<'_>) -> bool { - item.ident.name.as_str().contains("test") +fn is_test_module_or_function(item: &Item<'_>) -> bool { + matches!(item.kind, ItemKind::Fn(..) | ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") } From 4db6abcd50eb07a7fa8349a059f80792b7b19a2e Mon Sep 17 00:00:00 2001 From: Glenn Hope <glenn.alexander.hope@gmail.com> Date: Sat, 9 May 2020 08:04:07 -0700 Subject: [PATCH 038/526] Remove check for Fn, reflect this in test cases, make test cases more robust/explicit --- clippy_lints/src/wildcard_imports.rs | 13 +++++++++---- tests/ui/wildcard_imports.fixed | 25 +++++++++++++++++++++++-- tests/ui/wildcard_imports.rs | 24 ++++++++++++++++++++++-- tests/ui/wildcard_imports.stderr | 14 ++++++++++---- 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 48405a00d55..e12a6659ab5 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -43,9 +43,14 @@ declare_clippy_lint! { /// /// This can lead to confusing error messages at best and to unexpected behavior at worst. /// - /// Note that this will not warn about wildcard imports from modules named `prelude`; many - /// crates (including the standard library) provide modules named "prelude" specifically - /// designed for wildcard import. + /// **Exceptions:** + /// + /// Wildcard imports are allowed from modules named `prelude`. Many crates (including the standard library) + /// provide modules named "prelude" specifically designed for wildcard import. + /// + /// `use super::*` is allowed in test modules. This is defined as any module with "test" in the name. + /// + /// These exceptions can be disabled using the `warn-on-all-wildcard-imports` configuration flag. /// /// **Known problems:** If macros are imported through the wildcard, this macro is not included /// by the suggestion and has to be added by hand. @@ -198,5 +203,5 @@ fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { } fn is_test_module_or_function(item: &Item<'_>) -> bool { - matches!(item.kind, ItemKind::Fn(..) | ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") + matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") } diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 98bf6acfe55..b47c8f23e24 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -175,13 +175,34 @@ mod super_imports { } } - mod inner { - fn test_should_pass() { + mod test_should_pass_inside_function { + fn with_super_inside_function() { use super::*; let _ = foofoo(); } } + mod test_should_pass_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod should_be_replaced_futher_inside { + fn insidefoo() {} + mod inner { + use super::insidefoo; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod use_explicit_should_be_replaced { use super_imports::foofoo; diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 9275c5a0928..3ad1a29aeba 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -176,13 +176,33 @@ mod super_imports { } } - mod inner { - fn test_should_pass() { + mod test_should_pass_inside_function { + fn with_super_inside_function() { use super::*; let _ = foofoo(); } } + mod test_should_pass_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod should_be_replaced_futher_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + mod use_explicit_should_be_replaced { use super_imports::*; diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index bd000ce8161..de07bd1d69b 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -99,22 +99,28 @@ LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:187:13 + --> $DIR/wildcard_imports.rs:199:17 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::insidefoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:208:13 | LL | use super_imports::*; | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:196:17 + --> $DIR/wildcard_imports.rs:217:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:205:13 + --> $DIR/wildcard_imports.rs:226:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors From a339766136a183327faaf13b987be30b2940872e Mon Sep 17 00:00:00 2001 From: Glenn Hope <glenn.alexander.hope@gmail.com> Date: Sat, 9 May 2020 08:33:35 -0700 Subject: [PATCH 039/526] Fix test from auto-formatter fix --- tests/ui/wildcard_imports.fixed | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index b47c8f23e24..67423e6ec1d 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -202,7 +202,6 @@ mod super_imports { } } - mod use_explicit_should_be_replaced { use super_imports::foofoo; From 0ba61c612ee873314d252ca1f747c14a2f0161ba Mon Sep 17 00:00:00 2001 From: Glenn Hope <glenn.alexander.hope@gmail.com> Date: Sat, 9 May 2020 10:14:29 -0700 Subject: [PATCH 040/526] Check is_macro inside check_exceptions, update references to fix test --- clippy_lints/src/wildcard_imports.rs | 13 +++++++------ tests/ui/wildcard_imports.stderr | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index e12a6659ab5..2c4e24780e7 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -101,12 +101,11 @@ impl LateLintPass<'_, '_> for WildcardImports { return; } if is_test_module_or_function(item) { - self.test_modules_deep += 1; + self.test_modules_deep = self.test_modules_deep.saturating_add(1); } if_chain! { - if self.warn_on_all || !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; - if self.warn_on_all || !self.check_exceptions(use_path.segments); + if self.warn_on_all || !self.check_exceptions(item, use_path.segments); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner); if !used_imports.is_empty(); // Already handled by `unused_imports` then { @@ -177,14 +176,16 @@ impl LateLintPass<'_, '_> for WildcardImports { fn check_item_post(&mut self, _: &LateContext<'_, '_>, item: &Item<'_>) { if is_test_module_or_function(item) { - self.test_modules_deep -= 1; + self.test_modules_deep = self.test_modules_deep.saturating_sub(1); } } } impl WildcardImports { - fn check_exceptions(&self, segments: &[PathSegment<'_>]) -> bool { - is_prelude_import(segments) || (is_super_only_import(segments) && self.test_modules_deep > 0) + fn check_exceptions(&self, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool { + in_macro(item.span) + || is_prelude_import(segments) + || (is_super_only_import(segments) && self.test_modules_deep > 0) } } diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index de07bd1d69b..fab43b738eb 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -105,19 +105,19 @@ LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:208:13 + --> $DIR/wildcard_imports.rs:207:13 | LL | use super_imports::*; | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:217:17 + --> $DIR/wildcard_imports.rs:216:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:226:13 + --> $DIR/wildcard_imports.rs:225:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` From b69200b8468434bc3f5b9ef8468733e5d40f4e01 Mon Sep 17 00:00:00 2001 From: Glenn Hope <glenn.alexander.hope@gmail.com> Date: Sat, 9 May 2020 10:16:47 -0700 Subject: [PATCH 041/526] Move is_test_module check to top of function --- clippy_lints/src/wildcard_imports.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 2c4e24780e7..32d9a45c37d 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -97,12 +97,12 @@ impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]); impl LateLintPass<'_, '_> for WildcardImports { fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) { - if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { - return; - } if is_test_module_or_function(item) { self.test_modules_deep = self.test_modules_deep.saturating_add(1); } + if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { + return; + } if_chain! { if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; if self.warn_on_all || !self.check_exceptions(item, use_path.segments); From 318b8b6aabb2ef0fae0c0aafbba2c7ad97fb3a2a Mon Sep 17 00:00:00 2001 From: Mark Rousskov <mark.simulacrum@gmail.com> Date: Sun, 10 May 2020 22:15:04 -0400 Subject: [PATCH 042/526] Add hint for collect type --- clippy_lints/src/utils/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index f7a91fcdd21..8d75e126963 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1390,7 +1390,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_, '_>, did: DefId) -> bool .predicates .iter() .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }) - .collect(); + .collect::<Vec<_>>(); !traits::normalize_and_test_predicates( cx.tcx, traits::elaborate_predicates(cx.tcx, predicates) From 01662d3a23fcd39f41fd15a8254fed814592e0c3 Mon Sep 17 00:00:00 2001 From: Jack Huey <jack.huey@umassmed.edu> Date: Thu, 7 May 2020 17:46:31 -0400 Subject: [PATCH 043/526] Fix nit and cargo.lock --- util/dev | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 util/dev diff --git a/util/dev b/util/dev new file mode 100755 index 00000000000..319de217e0d --- /dev/null +++ b/util/dev @@ -0,0 +1,7 @@ +#!/bin/sh +CARGO_TARGET_DIR=$(pwd)/target/ +export CARGO_TARGET_DIR + +echo 'Deprecated! `util/dev` usage is deprecated, please use `cargo dev` instead.' + +cd clippy_dev && cargo run -- "$@" From 8ab3224b3b273f4911943800c56dc4aa925bc4c5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Fri, 8 May 2020 13:57:01 +0200 Subject: [PATCH 044/526] Fix clippy. --- clippy_lints/src/bytecount.rs | 7 ++++--- clippy_lints/src/inline_fn_without_body.rs | 5 +++-- clippy_lints/src/len_zero.rs | 6 +++--- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/map_clone.rs | 4 ++-- clippy_lints/src/non_expressive_names.rs | 4 ++-- clippy_lints/src/unsafe_removed_from_name.rs | 4 ++-- clippy_lints/src/utils/hir_utils.rs | 4 ++-- clippy_lints/src/utils/internal_lints.rs | 10 +++++----- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/ptr.rs | 9 ++++----- clippy_lints/src/utils/usage.rs | 5 ++--- 12 files changed, 31 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 91d3e47d787..278d043732f 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -3,12 +3,13 @@ use crate::utils::{ span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; -use rustc_ast::ast::{Name, UintTy}; +use rustc_ast::ast::{UintTy}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Symbol; declare_clippy_lint! { /// **What it does:** Checks for naive byte counts @@ -95,11 +96,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { } } -fn check_arg(name: Name, arg: Name, needle: &Expr<'_>) -> bool { +fn check_arg(name: Symbol, arg: Symbol, needle: &Expr<'_>) -> bool { name == arg && !contains_name(name, needle) } -fn get_path_name(expr: &Expr<'_>) -> Option<Name> { +fn get_path_name(expr: &Expr<'_>) -> Option<Symbol> { match expr.kind { ExprKind::Box(ref e) | ExprKind::AddrOf(BorrowKind::Ref, _, ref e) | ExprKind::Unary(UnOp::UnDeref, ref e) => { get_path_name(e) diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 1ebfb3c8162..475610dda47 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -2,11 +2,12 @@ use crate::utils::span_lint_and_then; use crate::utils::sugg::DiagnosticBuilderExt; -use rustc_ast::ast::{Attribute, Name}; +use rustc_ast::ast::Attribute; use rustc_errors::Applicability; use rustc_hir::{TraitFn, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Symbol; declare_clippy_lint! { /// **What it does:** Checks for `#[inline]` on trait methods without bodies @@ -38,7 +39,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InlineFnWithoutBody { } } -fn check_attrs(cx: &LateContext<'_, '_>, name: Name, attrs: &[Attribute]) { +fn check_attrs(cx: &LateContext<'_, '_>, name: Symbol, attrs: &[Attribute]) { for attr in attrs { if !attr.check_name(sym!(inline)) { continue; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 1d86ca9696f..2ec0b5a8d6f 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,5 +1,5 @@ use crate::utils::{get_item_name, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; -use rustc_ast::ast::{LitKind, Name}; +use rustc_ast::ast::LitKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; @@ -7,7 +7,7 @@ use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, ImplItemRef, Item, Ite use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::{Span, Spanned}; +use rustc_span::source_map::{Span, Spanned, Symbol}; declare_clippy_lint! { /// **What it does:** Checks for getting the length of something via `.len()` @@ -226,7 +226,7 @@ fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr<'_>, lit: &Expr fn check_len( cx: &LateContext<'_, '_>, span: Span, - method_name: Name, + method_name: Symbol, args: &[Expr<'_>], lit: &LitKind, op: &str, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4b67c84e38e..51b5401da7d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -335,7 +335,7 @@ mod zero_div_zero; pub use crate::utils::conf::Conf; mod reexport { - pub use rustc_ast::ast::Name; + pub use rustc_span::Symbol as Name; } /// Register all pre expansion lints diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 0b346393ac3..0163b3f8dbc 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -3,14 +3,14 @@ use crate::utils::{ is_copy, is_type_diagnostic_item, match_trait_method, remove_blocks, snippet_with_applicability, span_lint_and_sugg, }; use if_chain::if_chain; -use rustc_ast::ast::Ident; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::Mutability; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; +use rustc_span::Span; +use rustc_span::symbol::Ident; declare_clippy_lint! { /// **What it does:** Checks for usage of `iterator.map(|x| x.clone())` and suggests diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 45809b35986..2b51b732075 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,13 +1,13 @@ use crate::utils::{span_lint, span_lint_and_then}; use rustc_ast::ast::{ - Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Ident, Item, ItemKind, Local, MacCall, Pat, PatKind, + Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, MacCall, Pat, PatKind, }; use rustc_ast::attr; use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; -use rustc_span::symbol::SymbolStr; +use rustc_span::symbol::{Ident, SymbolStr}; use std::cmp::Ordering; declare_clippy_lint! { diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 86c469a4dcc..735800e7e74 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,9 +1,9 @@ use crate::utils::span_lint; -use rustc_ast::ast::{Ident, Item, ItemKind, UseTree, UseTreeKind}; +use rustc_ast::ast::{Item, ItemKind, UseTree, UseTreeKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::symbol::SymbolStr; +use rustc_span::symbol::{Ident, SymbolStr}; declare_clippy_lint! { /// **What it does:** Checks for imports that remove "unsafe" from an item's diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 02b721fd378..bd7da57c665 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -1,6 +1,5 @@ use crate::consts::{constant_context, constant_simple}; use crate::utils::differing_macro_contexts; -use rustc_ast::ast::Name; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::{ BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprKind, Field, FnRetTy, GenericArg, @@ -10,6 +9,7 @@ use rustc_hir::{ use rustc_lint::LateContext; use rustc_middle::ich::StableHashingContextProvider; use rustc_middle::ty::TypeckTables; +use rustc_span::Symbol; use std::hash::Hash; /// Type used to check whether two ast are the same. This is different from the @@ -544,7 +544,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } - pub fn hash_name(&mut self, n: Name) { + pub fn hash_name(&mut self, n: Symbol) { n.as_str().hash(&mut self.s); } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 5bf9acdc5f7..8e1b047f6f8 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -4,7 +4,7 @@ use crate::utils::{ span_lint_and_help, span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; -use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, Name, NodeId}; +use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, NodeId}; use rustc_ast::visit::FnKind; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; @@ -17,7 +17,7 @@ use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{Span, Spanned}; -use rustc_span::symbol::SymbolStr; +use rustc_span::symbol::{Symbol, SymbolStr}; use std::borrow::{Borrow, Cow}; @@ -245,8 +245,8 @@ impl EarlyLintPass for ClippyLintsInternal { #[derive(Clone, Debug, Default)] pub struct LintWithoutLintPass { - declared_lints: FxHashMap<Name, Span>, - registered_lints: FxHashSet<Name>, + declared_lints: FxHashMap<Symbol, Span>, + registered_lints: FxHashSet<Symbol>, } impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS]); @@ -357,7 +357,7 @@ fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty<'_>) -> bool { } struct LintCollector<'a, 'tcx> { - output: &'a mut FxHashSet<Name>, + output: &'a mut FxHashSet<Symbol>, cx: &'a LateContext<'a, 'tcx>, } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 1c7b40fa908..3b8ef18bfab 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1077,7 +1077,7 @@ pub fn is_allowed(cx: &LateContext<'_, '_>, lint: &'static Lint, id: HirId) -> b cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow } -pub fn get_arg_name(pat: &Pat<'_>) -> Option<ast::Name> { +pub fn get_arg_name(pat: &Pat<'_>) -> Option<Name> { match pat.kind { PatKind::Binding(.., ident, None) => Some(ident.name), PatKind::Ref(ref subpat, _) => get_arg_name(subpat), diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 240bf2449cb..fb6bd5e8158 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -1,10 +1,9 @@ use crate::utils::{get_pat_name, match_var, snippet}; -use rustc_ast::ast::Name; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{Body, BodyId, Expr, ExprKind, Param}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; -use rustc_span::source_map::Span; +use rustc_span::{Span, Symbol}; use std::borrow::Cow; pub fn get_spans( @@ -25,7 +24,7 @@ pub fn get_spans( fn extract_clone_suggestions<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - name: Name, + name: Symbol, replace: &[(&'static str, &'static str)], body: &'tcx Body<'_>, ) -> Option<Vec<(Span, Cow<'static, str>)>> { @@ -46,7 +45,7 @@ fn extract_clone_suggestions<'a, 'tcx>( struct PtrCloneVisitor<'a, 'tcx> { cx: &'a LateContext<'a, 'tcx>, - name: Name, + name: Symbol, replace: &'a [(&'static str, &'static str)], spans: Vec<(Span, Cow<'static, str>)>, abort: bool, @@ -83,6 +82,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { } } -fn get_binding_name(arg: &Param<'_>) -> Option<Name> { +fn get_binding_name(arg: &Param<'_>) -> Option<Symbol> { get_pat_name(&arg.pat) } diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index c14da6aacea..e8535677987 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -1,5 +1,4 @@ use crate::utils::match_var; -use rustc_ast::ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; @@ -8,7 +7,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; use rustc_middle::ty; -use rustc_span::symbol::Ident; +use rustc_span::symbol::{Ident, Symbol}; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined. @@ -78,7 +77,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { } pub struct UsedVisitor { - pub var: ast::Name, // var to look for + pub var: Symbol, // var to look for pub used: bool, // has the var been used otherwise? } From 33a3d852f53d38e738719c294c83bd03d50d2ac6 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 11 May 2020 21:28:14 +0200 Subject: [PATCH 045/526] Fix fallout Re-remove util/dev file --- util/dev | 7 ------- 1 file changed, 7 deletions(-) delete mode 100755 util/dev diff --git a/util/dev b/util/dev deleted file mode 100755 index 319de217e0d..00000000000 --- a/util/dev +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -CARGO_TARGET_DIR=$(pwd)/target/ -export CARGO_TARGET_DIR - -echo 'Deprecated! `util/dev` usage is deprecated, please use `cargo dev` instead.' - -cd clippy_dev && cargo run -- "$@" From 505280b108f777ae941d4056a87f77fb7f513a7e Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 11 May 2020 21:31:01 +0200 Subject: [PATCH 046/526] Run cargo dev fmt --- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/utils/usage.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 278d043732f..90c00ad098f 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -3,7 +3,7 @@ use crate::utils::{ span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; -use rustc_ast::ast::{UintTy}; +use rustc_ast::ast::UintTy; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 0163b3f8dbc..d5adf6b0f0d 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -9,8 +9,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::Mutability; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; use rustc_span::symbol::Ident; +use rustc_span::Span; declare_clippy_lint! { /// **What it does:** Checks for usage of `iterator.map(|x| x.clone())` and suggests diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index e8535677987..904d948ad29 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -77,8 +77,8 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { } pub struct UsedVisitor { - pub var: Symbol, // var to look for - pub used: bool, // has the var been used otherwise? + pub var: Symbol, // var to look for + pub used: bool, // has the var been used otherwise? } impl<'tcx> Visitor<'tcx> for UsedVisitor { From eec17d2c21605655188eaa13fd73d43c99162805 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 11 May 2020 21:40:33 +0200 Subject: [PATCH 047/526] Update failing test --- tests/ui/implicit_saturating_sub.fixed | 4 ++-- tests/ui/implicit_saturating_sub.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ui/implicit_saturating_sub.fixed b/tests/ui/implicit_saturating_sub.fixed index e0b5b31a00c..859765d08a7 100644 --- a/tests/ui/implicit_saturating_sub.fixed +++ b/tests/ui/implicit_saturating_sub.fixed @@ -29,8 +29,8 @@ fn main() { // Lint u_16 = u_16.saturating_sub(1); - let mut end_32: u32 = 7000; - let mut start_32: u32 = 7010; + let mut end_32: u32 = 7010; + let mut start_32: u32 = 7000; let mut u_32: u32 = end_32 - start_32; diff --git a/tests/ui/implicit_saturating_sub.rs b/tests/ui/implicit_saturating_sub.rs index 39d81608922..24cb216e79b 100644 --- a/tests/ui/implicit_saturating_sub.rs +++ b/tests/ui/implicit_saturating_sub.rs @@ -35,8 +35,8 @@ fn main() { u_16 -= 1; } - let mut end_32: u32 = 7000; - let mut start_32: u32 = 7010; + let mut end_32: u32 = 7010; + let mut start_32: u32 = 7000; let mut u_32: u32 = end_32 - start_32; From f20b96277397db2c9021d06cf8647014ccdc0a39 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Wed, 13 May 2020 01:04:16 +0200 Subject: [PATCH 048/526] unused_unit: lint also in type parameters and where clauses --- clippy_lints/src/returns.rs | 64 ++++++++++++++++++++----------- tests/ui/unused_unit.fixed | 21 ++++++++-- tests/ui/unused_unit.rs | 18 +++++++-- tests/ui/unused_unit.stderr | 76 +++++++++++++++++++++++++++++++------ 4 files changed, 138 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 5c9117d5b81..35464f629c3 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -248,28 +248,7 @@ impl EarlyLintPass for Return { if let ast::TyKind::Tup(ref vals) = ty.kind; if vals.is_empty() && !ty.span.from_expansion() && get_def(span) == get_def(ty.span); then { - let (rspan, appl) = if let Ok(fn_source) = - cx.sess().source_map() - .span_to_snippet(span.with_hi(ty.span.hi())) { - if let Some(rpos) = fn_source.rfind("->") { - #[allow(clippy::cast_possible_truncation)] - (ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), - Applicability::MachineApplicable) - } else { - (ty.span, Applicability::MaybeIncorrect) - } - } else { - (ty.span, Applicability::MaybeIncorrect) - }; - span_lint_and_sugg( - cx, - UNUSED_UNIT, - rspan, - "unneeded unit return type", - "remove the `-> ()`", - String::new(), - appl, - ); + lint_unneeded_unit_return(cx, ty, span); } } } @@ -313,6 +292,22 @@ impl EarlyLintPass for Return { _ => (), } } + + fn check_poly_trait_ref(&mut self, cx: &EarlyContext<'_>, poly: &ast::PolyTraitRef, _: &ast::TraitBoundModifier) { + let segments = &poly.trait_ref.path.segments; + + if_chain! { + if segments.len() == 1; + if ["Fn", "FnMut", "FnOnce"].contains(&&*segments[0].ident.name.as_str()); + if let Some(args) = &segments[0].args; + if let ast::GenericArgs::Parenthesized(generic_args) = &**args; + if let ast::FnRetTy::Ty(ty) = &generic_args.output; + if ty.kind.is_unit(); + then { + lint_unneeded_unit_return(cx, ty, generic_args.span); + } + } + } } fn attr_is_cfg(attr: &ast::Attribute) -> bool { @@ -337,3 +332,28 @@ fn is_unit_expr(expr: &ast::Expr) -> bool { false } } + +fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) { + let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) { + if let Some(rpos) = fn_source.rfind("->") { + #[allow(clippy::cast_possible_truncation)] + ( + ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), + Applicability::MachineApplicable, + ) + } else { + (ty.span, Applicability::MaybeIncorrect) + } + } else { + (ty.span, Applicability::MaybeIncorrect) + }; + span_lint_and_sugg( + cx, + UNUSED_UNIT, + ret_span, + "unneeded unit return type", + "remove the `-> ()`", + String::new(), + appl, + ); +} diff --git a/tests/ui/unused_unit.fixed b/tests/ui/unused_unit.fixed index 3f63624720f..07f2791786d 100644 --- a/tests/ui/unused_unit.fixed +++ b/tests/ui/unused_unit.fixed @@ -14,11 +14,10 @@ struct Unitter; impl Unitter { - // try to disorient the lint with multiple unit returns and newlines #[allow(clippy::no_effect)] - pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) - where G: Fn() -> () { - let _y: &dyn Fn() -> () = &f; + pub fn get_unit<F: Fn() , G>(&self, f: F, _g: G) + where G: Fn() { + let _y: &dyn Fn() = &f; (); // this should not lint, as it's not in return type position } } @@ -30,6 +29,20 @@ impl Into<()> for Unitter { } } +trait Trait { + fn redundant<F: FnOnce() , G, H>(&self, _f: F, _g: G, _h: H) + where + G: FnMut() , + H: Fn() ; +} + +impl Trait for Unitter { + fn redundant<F: FnOnce() , G, H>(&self, _f: F, _g: G, _h: H) + where + G: FnMut() , + H: Fn() {} +} + fn return_unit() { } #[allow(clippy::needless_return)] diff --git a/tests/ui/unused_unit.rs b/tests/ui/unused_unit.rs index 8fc072ebd69..e2c6afb020f 100644 --- a/tests/ui/unused_unit.rs +++ b/tests/ui/unused_unit.rs @@ -14,10 +14,8 @@ struct Unitter; impl Unitter { - // try to disorient the lint with multiple unit returns and newlines #[allow(clippy::no_effect)] - pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> - () + pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> () where G: Fn() -> () { let _y: &dyn Fn() -> () = &f; (); // this should not lint, as it's not in return type position @@ -31,6 +29,20 @@ impl Into<()> for Unitter { } } +trait Trait { + fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H) + where + G: FnMut() -> (), + H: Fn() -> (); +} + +impl Trait for Unitter { + fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H) + where + G: FnMut() -> (), + H: Fn() -> () {} +} + fn return_unit() -> () { () } #[allow(clippy::needless_return)] diff --git a/tests/ui/unused_unit.stderr b/tests/ui/unused_unit.stderr index a013d2b3495..81e6738e6bf 100644 --- a/tests/ui/unused_unit.stderr +++ b/tests/ui/unused_unit.stderr @@ -1,10 +1,8 @@ error: unneeded unit return type - --> $DIR/unused_unit.rs:19:59 + --> $DIR/unused_unit.rs:18:29 | -LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> - | ___________________________________________________________^ -LL | | () - | |__________^ help: remove the `-> ()` +LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> () + | ^^^^^ help: remove the `-> ()` | note: the lint level is defined here --> $DIR/unused_unit.rs:12:9 @@ -13,40 +11,94 @@ LL | #![deny(clippy::unused_unit)] | ^^^^^^^^^^^^^^^^^^^ error: unneeded unit return type - --> $DIR/unused_unit.rs:29:19 + --> $DIR/unused_unit.rs:19:19 + | +LL | where G: Fn() -> () { + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> $DIR/unused_unit.rs:18:59 + | +LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> () + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> $DIR/unused_unit.rs:20:27 + | +LL | let _y: &dyn Fn() -> () = &f; + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> $DIR/unused_unit.rs:27:19 | LL | fn into(self) -> () { | ^^^^^ help: remove the `-> ()` error: unneeded unit expression - --> $DIR/unused_unit.rs:30:9 + --> $DIR/unused_unit.rs:28:9 | LL | () | ^^ help: remove the final `()` error: unneeded unit return type - --> $DIR/unused_unit.rs:34:18 + --> $DIR/unused_unit.rs:33:30 + | +LL | fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H) + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> $DIR/unused_unit.rs:35:20 + | +LL | G: FnMut() -> (), + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> $DIR/unused_unit.rs:36:17 + | +LL | H: Fn() -> (); + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> $DIR/unused_unit.rs:40:30 + | +LL | fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H) + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> $DIR/unused_unit.rs:42:20 + | +LL | G: FnMut() -> (), + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> $DIR/unused_unit.rs:43:17 + | +LL | H: Fn() -> () {} + | ^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> $DIR/unused_unit.rs:46:18 | LL | fn return_unit() -> () { () } | ^^^^^ help: remove the `-> ()` error: unneeded unit expression - --> $DIR/unused_unit.rs:34:26 + --> $DIR/unused_unit.rs:46:26 | LL | fn return_unit() -> () { () } | ^^ help: remove the final `()` error: unneeded `()` - --> $DIR/unused_unit.rs:44:14 + --> $DIR/unused_unit.rs:56:14 | LL | break(); | ^^ help: remove the `()` error: unneeded `()` - --> $DIR/unused_unit.rs:46:11 + --> $DIR/unused_unit.rs:58:11 | LL | return(); | ^^ help: remove the `()` -error: aborting due to 7 previous errors +error: aborting due to 16 previous errors From 8ffa0bfaa2452eb9c80bf0f1909b039efc8dd0c3 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 11 May 2020 00:52:33 +0200 Subject: [PATCH 049/526] New lint: reversed_empty_ranges --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 3 + clippy_lints/src/ranges.rs | 112 +++++++++++++++++- tests/ui/reversed_empty_ranges_fixable.fixed | 24 ++++ tests/ui/reversed_empty_ranges_fixable.rs | 24 ++++ tests/ui/reversed_empty_ranges_fixable.stderr | 47 ++++++++ tests/ui/reversed_empty_ranges_unfixable.rs | 15 +++ .../ui/reversed_empty_ranges_unfixable.stderr | 34 ++++++ 8 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 tests/ui/reversed_empty_ranges_fixable.fixed create mode 100644 tests/ui/reversed_empty_ranges_fixable.rs create mode 100644 tests/ui/reversed_empty_ranges_fixable.stderr create mode 100644 tests/ui/reversed_empty_ranges_unfixable.rs create mode 100644 tests/ui/reversed_empty_ranges_unfixable.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 8457d6ad05c..33b277fbd31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1546,6 +1546,7 @@ Released 2018-09-13 [`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else [`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used [`reverse_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#reverse_range_loop +[`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges [`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 51b5401da7d..e1cb10a4651 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -770,6 +770,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &ranges::RANGE_MINUS_ONE, &ranges::RANGE_PLUS_ONE, &ranges::RANGE_ZIP_WITH_LEN, + &ranges::REVERSED_EMPTY_RANGES, &redundant_clone::REDUNDANT_CLONE, &redundant_field_names::REDUNDANT_FIELD_NAMES, &redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING, @@ -1384,6 +1385,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&question_mark::QUESTION_MARK), LintId::of(&ranges::RANGE_MINUS_ONE), LintId::of(&ranges::RANGE_ZIP_WITH_LEN), + LintId::of(&ranges::REVERSED_EMPTY_RANGES), LintId::of(&redundant_clone::REDUNDANT_CLONE), LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES), LintId::of(&redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING), @@ -1675,6 +1677,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS), LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP), LintId::of(&ptr::MUT_FROM_REF), + LintId::of(&ranges::REVERSED_EMPTY_RANGES), LintId::of(®ex::INVALID_REGEX), LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index d7ce2e66d69..86d55ccabb6 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,14 +1,17 @@ +use crate::consts::{constant, Constant}; use if_chain::if_chain; use rustc_ast::ast::RangeLimits; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; +use std::cmp::Ordering; use crate::utils::sugg::Sugg; +use crate::utils::{get_parent_expr, is_integer_const, snippet, snippet_opt, span_lint, span_lint_and_then}; use crate::utils::{higher, SpanlessEq}; -use crate::utils::{is_integer_const, snippet, snippet_opt, span_lint, span_lint_and_then}; declare_clippy_lint! { /// **What it does:** Checks for zipping a collection with the range of @@ -84,10 +87,44 @@ declare_clippy_lint! { "`x..=(y-1)` reads better as `x..y`" } +declare_clippy_lint! { + /// **What it does:** Checks for range expressions `x..y` where both `x` and `y` + /// are constant and `x` is greater or equal to `y`. + /// + /// **Why is this bad?** Empty ranges yield no values so iterating them is a no-op. + /// Moreover, trying to use a reversed range to index a slice will panic at run-time. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// fn main() { + /// (10..=0).for_each(|x| println!("{}", x)); + /// + /// let arr = [1, 2, 3, 4, 5]; + /// let sub = &arr[3..1]; + /// } + /// ``` + /// Use instead: + /// ```rust + /// fn main() { + /// (0..=10).rev().for_each(|x| println!("{}", x)); + /// + /// let arr = [1, 2, 3, 4, 5]; + /// let sub = &arr[1..3]; + /// } + /// ``` + pub REVERSED_EMPTY_RANGES, + correctness, + "reversing the limits of range expressions, resulting in empty ranges" +} + declare_lint_pass!(Ranges => [ RANGE_ZIP_WITH_LEN, RANGE_PLUS_ONE, - RANGE_MINUS_ONE + RANGE_MINUS_ONE, + REVERSED_EMPTY_RANGES, ]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges { @@ -124,6 +161,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges { check_exclusive_range_plus_one(cx, expr); check_inclusive_range_minus_one(cx, expr); + check_reversed_empty_range(cx, expr); } } @@ -202,6 +240,76 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } +fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + fn inside_indexing_expr(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + matches!( + get_parent_expr(cx, expr), + Some(Expr { + kind: ExprKind::Index(..), + .. + }) + ) + } + + fn is_empty_range(limits: RangeLimits, ordering: Ordering) -> bool { + match limits { + RangeLimits::HalfOpen => ordering != Ordering::Less, + RangeLimits::Closed => ordering == Ordering::Greater, + } + } + + if_chain! { + if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(cx, expr); + let ty = cx.tables.expr_ty(start); + if let ty::Int(_) | ty::Uint(_) = ty.kind; + if let Some((start_idx, _)) = constant(cx, cx.tables, start); + if let Some((end_idx, _)) = constant(cx, cx.tables, end); + if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx); + if is_empty_range(limits, ordering); + then { + if inside_indexing_expr(cx, expr) { + let (reason, outcome) = if ordering == Ordering::Equal { + ("empty", "always yield an empty slice") + } else { + ("reversed", "panic at run-time") + }; + + span_lint( + cx, + REVERSED_EMPTY_RANGES, + expr.span, + &format!("this range is {} and using it to index a slice will {}", reason, outcome), + ); + } else { + span_lint_and_then( + cx, + REVERSED_EMPTY_RANGES, + expr.span, + "this range is empty so it will yield no values", + |diag| { + if ordering != Ordering::Equal { + let start_snippet = snippet(cx, start.span, "_"); + let end_snippet = snippet(cx, end.span, "_"); + let dots = match limits { + RangeLimits::HalfOpen => "..", + RangeLimits::Closed => "..=" + }; + + diag.span_suggestion( + expr.span, + "consider using the following if you are attempting to iterate over this \ + range in reverse", + format!("({}{}{}).rev()", end_snippet, dots, start_snippet), + Applicability::MaybeIncorrect, + ); + } + }, + ); + } + } + } +} + fn y_plus_one<'t>(cx: &LateContext<'_, '_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> { match expr.kind { ExprKind::Binary( diff --git a/tests/ui/reversed_empty_ranges_fixable.fixed b/tests/ui/reversed_empty_ranges_fixable.fixed new file mode 100644 index 00000000000..ee2cbc3cf54 --- /dev/null +++ b/tests/ui/reversed_empty_ranges_fixable.fixed @@ -0,0 +1,24 @@ +// run-rustfix +#![warn(clippy::reversed_empty_ranges)] + +const ANSWER: i32 = 42; + +fn main() { + (21..=42).rev().for_each(|x| println!("{}", x)); + let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>(); + + for _ in (-42..=-21).rev() {} + for _ in (21u32..42u32).rev() {} + + // These should be ignored as they are not empty ranges: + + (21..=42).for_each(|x| println!("{}", x)); + (21..42).for_each(|x| println!("{}", x)); + + let arr = [1, 2, 3, 4, 5]; + let _ = &arr[1..=3]; + let _ = &arr[1..3]; + + for _ in 21..=42 {} + for _ in 21..42 {} +} diff --git a/tests/ui/reversed_empty_ranges_fixable.rs b/tests/ui/reversed_empty_ranges_fixable.rs new file mode 100644 index 00000000000..6ed5ca6daa0 --- /dev/null +++ b/tests/ui/reversed_empty_ranges_fixable.rs @@ -0,0 +1,24 @@ +// run-rustfix +#![warn(clippy::reversed_empty_ranges)] + +const ANSWER: i32 = 42; + +fn main() { + (42..=21).for_each(|x| println!("{}", x)); + let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>(); + + for _ in -21..=-42 {} + for _ in 42u32..21u32 {} + + // These should be ignored as they are not empty ranges: + + (21..=42).for_each(|x| println!("{}", x)); + (21..42).for_each(|x| println!("{}", x)); + + let arr = [1, 2, 3, 4, 5]; + let _ = &arr[1..=3]; + let _ = &arr[1..3]; + + for _ in 21..=42 {} + for _ in 21..42 {} +} diff --git a/tests/ui/reversed_empty_ranges_fixable.stderr b/tests/ui/reversed_empty_ranges_fixable.stderr new file mode 100644 index 00000000000..97933b8ff85 --- /dev/null +++ b/tests/ui/reversed_empty_ranges_fixable.stderr @@ -0,0 +1,47 @@ +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_fixable.rs:7:5 + | +LL | (42..=21).for_each(|x| println!("{}", x)); + | ^^^^^^^^^ + | + = note: `-D clippy::reversed-empty-ranges` implied by `-D warnings` +help: consider using the following if you are attempting to iterate over this range in reverse + | +LL | (21..=42).rev().for_each(|x| println!("{}", x)); + | ^^^^^^^^^^^^^^^ + +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_fixable.rs:8:13 + | +LL | let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>(); + | ^^^^^^^^^^^^ + | +help: consider using the following if you are attempting to iterate over this range in reverse + | +LL | let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>(); + | ^^^^^^^^^^^^^^^^^^ + +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_fixable.rs:10:14 + | +LL | for _ in -21..=-42 {} + | ^^^^^^^^^ + | +help: consider using the following if you are attempting to iterate over this range in reverse + | +LL | for _ in (-42..=-21).rev() {} + | ^^^^^^^^^^^^^^^^^ + +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_fixable.rs:11:14 + | +LL | for _ in 42u32..21u32 {} + | ^^^^^^^^^^^^ + | +help: consider using the following if you are attempting to iterate over this range in reverse + | +LL | for _ in (21u32..42u32).rev() {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/reversed_empty_ranges_unfixable.rs b/tests/ui/reversed_empty_ranges_unfixable.rs new file mode 100644 index 00000000000..c9ca4c47668 --- /dev/null +++ b/tests/ui/reversed_empty_ranges_unfixable.rs @@ -0,0 +1,15 @@ +#![warn(clippy::reversed_empty_ranges)] + +const ANSWER: i32 = 42; +const SOME_NUM: usize = 3; + +fn main() { + let _ = (42 + 10..42 + 10).map(|x| x / 2).find(|&x| x == 21); + + let arr = [1, 2, 3, 4, 5]; + let _ = &arr[3usize..=1usize]; + let _ = &arr[SOME_NUM..1]; + let _ = &arr[3..3]; + + for _ in ANSWER..ANSWER {} +} diff --git a/tests/ui/reversed_empty_ranges_unfixable.stderr b/tests/ui/reversed_empty_ranges_unfixable.stderr new file mode 100644 index 00000000000..12e5483ecdf --- /dev/null +++ b/tests/ui/reversed_empty_ranges_unfixable.stderr @@ -0,0 +1,34 @@ +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_unfixable.rs:7:13 + | +LL | let _ = (42 + 10..42 + 10).map(|x| x / 2).find(|&x| x == 21); + | ^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::reversed-empty-ranges` implied by `-D warnings` + +error: this range is reversed and using it to index a slice will panic at run-time + --> $DIR/reversed_empty_ranges_unfixable.rs:10:18 + | +LL | let _ = &arr[3usize..=1usize]; + | ^^^^^^^^^^^^^^^ + +error: this range is reversed and using it to index a slice will panic at run-time + --> $DIR/reversed_empty_ranges_unfixable.rs:11:18 + | +LL | let _ = &arr[SOME_NUM..1]; + | ^^^^^^^^^^^ + +error: this range is empty and using it to index a slice will always yield an empty slice + --> $DIR/reversed_empty_ranges_unfixable.rs:12:18 + | +LL | let _ = &arr[3..3]; + | ^^^^ + +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_unfixable.rs:14:14 + | +LL | for _ in ANSWER..ANSWER {} + | ^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + From 0f2b1193f9501ffd06f9bf2ea8ab85a4db92f47b Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 11 May 2020 00:53:31 +0200 Subject: [PATCH 050/526] Remove reverse_range_loop lint --- CHANGELOG.md | 1 - clippy_lints/src/lib.rs | 7 +- clippy_lints/src/loops.rs | 102 +---------------------------- src/lintlist/mod.rs | 6 +- tests/ui/for_loop_fixable.fixed | 54 --------------- tests/ui/for_loop_fixable.rs | 54 --------------- tests/ui/for_loop_fixable.stderr | 88 +++++-------------------- tests/ui/for_loop_unfixable.rs | 18 ----- tests/ui/for_loop_unfixable.stderr | 11 ++-- tests/ui/manual_memcpy.rs | 2 +- 10 files changed, 32 insertions(+), 311 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33b277fbd31..b25ef049356 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1545,7 +1545,6 @@ Released 2018-09-13 [`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn [`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else [`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used -[`reverse_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#reverse_range_loop [`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges [`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e1cb10a4651..0c4daeb731f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -624,7 +624,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::NEEDLESS_COLLECT, &loops::NEEDLESS_RANGE_LOOP, &loops::NEVER_LOOP, - &loops::REVERSE_RANGE_LOOP, &loops::WHILE_IMMUTABLE_CONDITION, &loops::WHILE_LET_LOOP, &loops::WHILE_LET_ON_ITERATOR, @@ -1284,7 +1283,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::NEEDLESS_COLLECT), LintId::of(&loops::NEEDLESS_RANGE_LOOP), LintId::of(&loops::NEVER_LOOP), - LintId::of(&loops::REVERSE_RANGE_LOOP), LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), LintId::of(&loops::WHILE_LET_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), @@ -1658,7 +1656,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::FOR_LOOP_OVER_RESULT), LintId::of(&loops::ITER_NEXT_LOOP), LintId::of(&loops::NEVER_LOOP), - LintId::of(&loops::REVERSE_RANGE_LOOP), LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT), @@ -1788,6 +1785,10 @@ fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) { "unsafe_vector_initialization", "the replacement suggested by this lint had substantially different behavior", ); + store.register_removed( + "reverse_range_loop", + "this lint is now included in reversed_empty_ranges", + ); } /// Register renamed lints. diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2bbf4dba614..0bc6b70855b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use crate::consts::constant; use crate::reexport::Name; use crate::utils::paths; use crate::utils::usage::{is_unused, mutated_variables}; @@ -8,7 +8,7 @@ use crate::utils::{ multispan_sugg, snippet, snippet_opt, snippet_with_applicability, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, SpanlessEq, }; -use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg}; +use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sugg}; use if_chain::if_chain; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -270,30 +270,6 @@ declare_clippy_lint! { "collecting an iterator when collect is not needed" } -declare_clippy_lint! { - /// **What it does:** Checks for loops over ranges `x..y` where both `x` and `y` - /// are constant and `x` is greater or equal to `y`, unless the range is - /// reversed or has a negative `.step_by(_)`. - /// - /// **Why is it bad?** Such loops will either be skipped or loop until - /// wrap-around (in debug code, this may `panic!()`). Both options are probably - /// not intended. - /// - /// **Known problems:** The lint cannot catch loops over dynamically defined - /// ranges. Doing this would require simulating all possible inputs and code - /// paths through the program, which would be complex and error-prone. - /// - /// **Example:** - /// ```ignore - /// for x in 5..10 - 5 { - /// .. - /// } // oops, stray `-` - /// ``` - pub REVERSE_RANGE_LOOP, - correctness, - "iteration over an empty range, such as `10..0` or `5..5`" -} - declare_clippy_lint! { /// **What it does:** Checks `for` loops over slices with an explicit counter /// and suggests the use of `.enumerate()`. @@ -463,7 +439,6 @@ declare_lint_pass!(Loops => [ FOR_LOOP_OVER_OPTION, WHILE_LET_LOOP, NEEDLESS_COLLECT, - REVERSE_RANGE_LOOP, EXPLICIT_COUNTER_LOOP, EMPTY_LOOP, WHILE_LET_ON_ITERATOR, @@ -761,7 +736,6 @@ fn check_for_loop<'a, 'tcx>( expr: &'tcx Expr<'_>, ) { check_for_loop_range(cx, pat, arg, body, expr); - check_for_loop_reverse_range(cx, arg, expr); check_for_loop_arg(cx, pat, arg, expr); check_for_loop_explicit_counter(cx, pat, arg, body, expr); check_for_loop_over_map_kv(cx, pat, arg, body, expr); @@ -1248,78 +1222,6 @@ fn is_end_eq_array_len<'tcx>( false } -fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) { - // if this for loop is iterating over a two-sided range... - if let Some(higher::Range { - start: Some(start), - end: Some(end), - limits, - }) = higher::range(cx, arg) - { - // ...and both sides are compile-time constant integers... - if let Some((start_idx, _)) = constant(cx, cx.tables, start) { - if let Some((end_idx, _)) = constant(cx, cx.tables, end) { - // ...and the start index is greater than the end index, - // this loop will never run. This is often confusing for developers - // who think that this will iterate from the larger value to the - // smaller value. - let ty = cx.tables.expr_ty(start); - let (sup, eq) = match (start_idx, end_idx) { - (Constant::Int(start_idx), Constant::Int(end_idx)) => ( - match ty.kind { - ty::Int(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity), - ty::Uint(_) => start_idx > end_idx, - _ => false, - }, - start_idx == end_idx, - ), - _ => (false, false), - }; - - if sup { - let start_snippet = snippet(cx, start.span, "_"); - let end_snippet = snippet(cx, end.span, "_"); - let dots = if limits == ast::RangeLimits::Closed { - "..=" - } else { - ".." - }; - - span_lint_and_then( - cx, - REVERSE_RANGE_LOOP, - expr.span, - "this range is empty so this for loop will never run", - |diag| { - diag.span_suggestion( - arg.span, - "consider using the following if you are attempting to iterate over this \ - range in reverse", - format!( - "({end}{dots}{start}).rev()", - end = end_snippet, - dots = dots, - start = start_snippet - ), - Applicability::MaybeIncorrect, - ); - }, - ); - } else if eq && limits != ast::RangeLimits::Closed { - // if they are equal, it's also problematic - this loop - // will never run. - span_lint( - cx, - REVERSE_RANGE_LOOP, - expr.span, - "this range is empty so this for loop will never run", - ); - } - } - } - } -} - fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr<'_>], arg: &Expr<'_>, method_name: &str) { let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 51d1cb2216a..e1a6d4bdd31 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1922,11 +1922,11 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ module: "methods", }, Lint { - name: "reverse_range_loop", + name: "reversed_empty_ranges", group: "correctness", - desc: "iteration over an empty range, such as `10..0` or `5..5`", + desc: "reversing the limits of range expressions, resulting in empty ranges", deprecation: None, - module: "loops", + module: "ranges", }, Lint { name: "same_functions_in_if_condition", diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed index 5fc84ada9ef..249a88a0b39 100644 --- a/tests/ui/for_loop_fixable.fixed +++ b/tests/ui/for_loop_fixable.fixed @@ -21,7 +21,6 @@ impl Unrelated { clippy::explicit_iter_loop, clippy::explicit_into_iter_loop, clippy::iter_next_loop, - clippy::reverse_range_loop, clippy::for_kv_map )] #[allow( @@ -32,61 +31,8 @@ impl Unrelated { )] #[allow(clippy::many_single_char_names, unused_variables)] fn main() { - const MAX_LEN: usize = 42; let mut vec = vec![1, 2, 3, 4]; - for i in (0..10).rev() { - println!("{}", i); - } - - for i in (0..=10).rev() { - println!("{}", i); - } - - for i in (0..MAX_LEN).rev() { - println!("{}", i); - } - - for i in 5..=5 { - // not an error, this is the range with only one element “5” - println!("{}", i); - } - - for i in 0..10 { - // not an error, the start index is less than the end index - println!("{}", i); - } - - for i in -10..0 { - // not an error - println!("{}", i); - } - - for i in (10..0).map(|x| x * 2) { - // not an error, it can't be known what arbitrary methods do to a range - println!("{}", i); - } - - // testing that the empty range lint folds constants - for i in (5 + 4..10).rev() { - println!("{}", i); - } - - for i in ((3 - 1)..(5 + 2)).rev() { - println!("{}", i); - } - - for i in (2 * 2)..(2 * 3) { - // no error, 4..6 is fine - println!("{}", i); - } - - let x = 42; - for i in x..10 { - // no error, not constant-foldable - println!("{}", i); - } - // See #601 for i in 0..10 { // no error, id_col does not exist outside the loop diff --git a/tests/ui/for_loop_fixable.rs b/tests/ui/for_loop_fixable.rs index 4165b0dc004..306d85a6351 100644 --- a/tests/ui/for_loop_fixable.rs +++ b/tests/ui/for_loop_fixable.rs @@ -21,7 +21,6 @@ impl Unrelated { clippy::explicit_iter_loop, clippy::explicit_into_iter_loop, clippy::iter_next_loop, - clippy::reverse_range_loop, clippy::for_kv_map )] #[allow( @@ -32,61 +31,8 @@ impl Unrelated { )] #[allow(clippy::many_single_char_names, unused_variables)] fn main() { - const MAX_LEN: usize = 42; let mut vec = vec![1, 2, 3, 4]; - for i in 10..0 { - println!("{}", i); - } - - for i in 10..=0 { - println!("{}", i); - } - - for i in MAX_LEN..0 { - println!("{}", i); - } - - for i in 5..=5 { - // not an error, this is the range with only one element “5” - println!("{}", i); - } - - for i in 0..10 { - // not an error, the start index is less than the end index - println!("{}", i); - } - - for i in -10..0 { - // not an error - println!("{}", i); - } - - for i in (10..0).map(|x| x * 2) { - // not an error, it can't be known what arbitrary methods do to a range - println!("{}", i); - } - - // testing that the empty range lint folds constants - for i in 10..5 + 4 { - println!("{}", i); - } - - for i in (5 + 2)..(3 - 1) { - println!("{}", i); - } - - for i in (2 * 2)..(2 * 3) { - // no error, 4..6 is fine - println!("{}", i); - } - - let x = 42; - for i in x..10 { - // no error, not constant-foldable - println!("{}", i); - } - // See #601 for i in 0..10 { // no error, id_col does not exist outside the loop diff --git a/tests/ui/for_loop_fixable.stderr b/tests/ui/for_loop_fixable.stderr index cffb4b9f0a9..ddfe66d675f 100644 --- a/tests/ui/for_loop_fixable.stderr +++ b/tests/ui/for_loop_fixable.stderr @@ -1,61 +1,5 @@ -error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:38:14 - | -LL | for i in 10..0 { - | ^^^^^ - | - = note: `-D clippy::reverse-range-loop` implied by `-D warnings` -help: consider using the following if you are attempting to iterate over this range in reverse - | -LL | for i in (0..10).rev() { - | ^^^^^^^^^^^^^ - -error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:42:14 - | -LL | for i in 10..=0 { - | ^^^^^^ - | -help: consider using the following if you are attempting to iterate over this range in reverse - | -LL | for i in (0..=10).rev() { - | ^^^^^^^^^^^^^^ - -error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:46:14 - | -LL | for i in MAX_LEN..0 { - | ^^^^^^^^^^ - | -help: consider using the following if you are attempting to iterate over this range in reverse - | -LL | for i in (0..MAX_LEN).rev() { - | ^^^^^^^^^^^^^^^^^^ - -error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:71:14 - | -LL | for i in 10..5 + 4 { - | ^^^^^^^^^ - | -help: consider using the following if you are attempting to iterate over this range in reverse - | -LL | for i in (5 + 4..10).rev() { - | ^^^^^^^^^^^^^^^^^ - -error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:75:14 - | -LL | for i in (5 + 2)..(3 - 1) { - | ^^^^^^^^^^^^^^^^ - | -help: consider using the following if you are attempting to iterate over this range in reverse - | -LL | for i in ((3 - 1)..(5 + 2)).rev() { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:97:15 + --> $DIR/for_loop_fixable.rs:43:15 | LL | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` @@ -63,13 +7,13 @@ LL | for _v in vec.iter() {} = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:99:15 + --> $DIR/for_loop_fixable.rs:45:15 | LL | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:102:15 + --> $DIR/for_loop_fixable.rs:48:15 | LL | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` @@ -77,76 +21,76 @@ LL | for _v in out_vec.into_iter() {} = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:107:15 + --> $DIR/for_loop_fixable.rs:53:15 | LL | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:111:15 + --> $DIR/for_loop_fixable.rs:57:15 | LL | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:116:15 + --> $DIR/for_loop_fixable.rs:62:15 | LL | for _v in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:119:15 + --> $DIR/for_loop_fixable.rs:65:15 | LL | for _v in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:122:15 + --> $DIR/for_loop_fixable.rs:68:15 | LL | for _v in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:125:15 + --> $DIR/for_loop_fixable.rs:71:15 | LL | for _v in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:128:15 + --> $DIR/for_loop_fixable.rs:74:15 | LL | for _v in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:131:15 + --> $DIR/for_loop_fixable.rs:77:15 | LL | for _v in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:134:15 + --> $DIR/for_loop_fixable.rs:80:15 | LL | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:309:18 + --> $DIR/for_loop_fixable.rs:255:18 | LL | for i in iterator.into_iter() { | ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:329:18 + --> $DIR/for_loop_fixable.rs:275:18 | LL | for _ in t.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:331:18 + --> $DIR/for_loop_fixable.rs:277:18 | LL | for _ in r.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` -error: aborting due to 20 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/for_loop_unfixable.rs b/tests/ui/for_loop_unfixable.rs index 179b255e08c..e73536052f0 100644 --- a/tests/ui/for_loop_unfixable.rs +++ b/tests/ui/for_loop_unfixable.rs @@ -5,7 +5,6 @@ clippy::explicit_iter_loop, clippy::explicit_into_iter_loop, clippy::iter_next_loop, - clippy::reverse_range_loop, clippy::for_kv_map )] #[allow( @@ -16,25 +15,8 @@ unused, dead_code )] -#[allow(clippy::many_single_char_names, unused_variables)] fn main() { - for i in 5..5 { - println!("{}", i); - } - let vec = vec![1, 2, 3, 4]; for _v in vec.iter().next() {} - - for i in (5 + 2)..(8 - 1) { - println!("{}", i); - } - - const ZERO: usize = 0; - - for i in ZERO..vec.len() { - if f(&vec[i], &vec[i]) { - panic!("at the disco"); - } - } } diff --git a/tests/ui/for_loop_unfixable.stderr b/tests/ui/for_loop_unfixable.stderr index 1da8e0f3588..1c9287b6acb 100644 --- a/tests/ui/for_loop_unfixable.stderr +++ b/tests/ui/for_loop_unfixable.stderr @@ -1,9 +1,10 @@ -error[E0425]: cannot find function `f` in this scope - --> $DIR/for_loop_unfixable.rs:36:12 +error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want + --> $DIR/for_loop_unfixable.rs:21:15 | -LL | if f(&vec[i], &vec[i]) { - | ^ help: a local variable with a similar name exists: `i` +LL | for _v in vec.iter().next() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::iter-next-loop` implied by `-D warnings` error: aborting due to previous error -For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/manual_memcpy.rs b/tests/ui/manual_memcpy.rs index 9c24d6d4db1..0083f94798f 100644 --- a/tests/ui/manual_memcpy.rs +++ b/tests/ui/manual_memcpy.rs @@ -104,7 +104,7 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { dst[i - 0] = src[i]; } - #[allow(clippy::reverse_range_loop)] + #[allow(clippy::reversed_empty_ranges)] for i in 0..0 { dst[i] = src[i]; } From 064431d22fbc28f958a1d18da8a5e01ff99dadb0 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 11 May 2020 23:48:48 +0200 Subject: [PATCH 051/526] Re-add old tests for empty range loops --- .../reversed_empty_ranges_loops_fixable.fixed | 57 +++++++++++++++ .../ui/reversed_empty_ranges_loops_fixable.rs | 57 +++++++++++++++ ...reversed_empty_ranges_loops_fixable.stderr | 69 +++++++++++++++++++ .../reversed_empty_ranges_loops_unfixable.rs | 11 +++ ...versed_empty_ranges_loops_unfixable.stderr | 16 +++++ 5 files changed, 210 insertions(+) create mode 100644 tests/ui/reversed_empty_ranges_loops_fixable.fixed create mode 100644 tests/ui/reversed_empty_ranges_loops_fixable.rs create mode 100644 tests/ui/reversed_empty_ranges_loops_fixable.stderr create mode 100644 tests/ui/reversed_empty_ranges_loops_unfixable.rs create mode 100644 tests/ui/reversed_empty_ranges_loops_unfixable.stderr diff --git a/tests/ui/reversed_empty_ranges_loops_fixable.fixed b/tests/ui/reversed_empty_ranges_loops_fixable.fixed new file mode 100644 index 00000000000..f1503ed6d12 --- /dev/null +++ b/tests/ui/reversed_empty_ranges_loops_fixable.fixed @@ -0,0 +1,57 @@ +// run-rustfix +#![warn(clippy::reversed_empty_ranges)] + +fn main() { + const MAX_LEN: usize = 42; + + for i in (0..10).rev() { + println!("{}", i); + } + + for i in (0..=10).rev() { + println!("{}", i); + } + + for i in (0..MAX_LEN).rev() { + println!("{}", i); + } + + for i in 5..=5 { + // not an error, this is the range with only one element “5” + println!("{}", i); + } + + for i in 0..10 { + // not an error, the start index is less than the end index + println!("{}", i); + } + + for i in -10..0 { + // not an error + println!("{}", i); + } + + for i in (0..10).rev().map(|x| x * 2) { + println!("{}", i); + } + + // testing that the empty range lint folds constants + for i in (5 + 4..10).rev() { + println!("{}", i); + } + + for i in ((3 - 1)..(5 + 2)).rev() { + println!("{}", i); + } + + for i in (2 * 2)..(2 * 3) { + // no error, 4..6 is fine + println!("{}", i); + } + + let x = 42; + for i in x..10 { + // no error, not constant-foldable + println!("{}", i); + } +} diff --git a/tests/ui/reversed_empty_ranges_loops_fixable.rs b/tests/ui/reversed_empty_ranges_loops_fixable.rs new file mode 100644 index 00000000000..a733788dc22 --- /dev/null +++ b/tests/ui/reversed_empty_ranges_loops_fixable.rs @@ -0,0 +1,57 @@ +// run-rustfix +#![warn(clippy::reversed_empty_ranges)] + +fn main() { + const MAX_LEN: usize = 42; + + for i in 10..0 { + println!("{}", i); + } + + for i in 10..=0 { + println!("{}", i); + } + + for i in MAX_LEN..0 { + println!("{}", i); + } + + for i in 5..=5 { + // not an error, this is the range with only one element “5” + println!("{}", i); + } + + for i in 0..10 { + // not an error, the start index is less than the end index + println!("{}", i); + } + + for i in -10..0 { + // not an error + println!("{}", i); + } + + for i in (10..0).map(|x| x * 2) { + println!("{}", i); + } + + // testing that the empty range lint folds constants + for i in 10..5 + 4 { + println!("{}", i); + } + + for i in (5 + 2)..(3 - 1) { + println!("{}", i); + } + + for i in (2 * 2)..(2 * 3) { + // no error, 4..6 is fine + println!("{}", i); + } + + let x = 42; + for i in x..10 { + // no error, not constant-foldable + println!("{}", i); + } +} diff --git a/tests/ui/reversed_empty_ranges_loops_fixable.stderr b/tests/ui/reversed_empty_ranges_loops_fixable.stderr new file mode 100644 index 00000000000..e89e040a0ff --- /dev/null +++ b/tests/ui/reversed_empty_ranges_loops_fixable.stderr @@ -0,0 +1,69 @@ +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_loops_fixable.rs:7:14 + | +LL | for i in 10..0 { + | ^^^^^ + | + = note: `-D clippy::reversed-empty-ranges` implied by `-D warnings` +help: consider using the following if you are attempting to iterate over this range in reverse + | +LL | for i in (0..10).rev() { + | ^^^^^^^^^^^^^ + +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_loops_fixable.rs:11:14 + | +LL | for i in 10..=0 { + | ^^^^^^ + | +help: consider using the following if you are attempting to iterate over this range in reverse + | +LL | for i in (0..=10).rev() { + | ^^^^^^^^^^^^^^ + +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_loops_fixable.rs:15:14 + | +LL | for i in MAX_LEN..0 { + | ^^^^^^^^^^ + | +help: consider using the following if you are attempting to iterate over this range in reverse + | +LL | for i in (0..MAX_LEN).rev() { + | ^^^^^^^^^^^^^^^^^^ + +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_loops_fixable.rs:34:14 + | +LL | for i in (10..0).map(|x| x * 2) { + | ^^^^^^^ + | +help: consider using the following if you are attempting to iterate over this range in reverse + | +LL | for i in (0..10).rev().map(|x| x * 2) { + | ^^^^^^^^^^^^^ + +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_loops_fixable.rs:39:14 + | +LL | for i in 10..5 + 4 { + | ^^^^^^^^^ + | +help: consider using the following if you are attempting to iterate over this range in reverse + | +LL | for i in (5 + 4..10).rev() { + | ^^^^^^^^^^^^^^^^^ + +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_loops_fixable.rs:43:14 + | +LL | for i in (5 + 2)..(3 - 1) { + | ^^^^^^^^^^^^^^^^ + | +help: consider using the following if you are attempting to iterate over this range in reverse + | +LL | for i in ((3 - 1)..(5 + 2)).rev() { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/reversed_empty_ranges_loops_unfixable.rs b/tests/ui/reversed_empty_ranges_loops_unfixable.rs new file mode 100644 index 00000000000..c4c57224416 --- /dev/null +++ b/tests/ui/reversed_empty_ranges_loops_unfixable.rs @@ -0,0 +1,11 @@ +#![warn(clippy::reversed_empty_ranges)] + +fn main() { + for i in 5..5 { + println!("{}", i); + } + + for i in (5 + 2)..(8 - 1) { + println!("{}", i); + } +} diff --git a/tests/ui/reversed_empty_ranges_loops_unfixable.stderr b/tests/ui/reversed_empty_ranges_loops_unfixable.stderr new file mode 100644 index 00000000000..30095d20cfd --- /dev/null +++ b/tests/ui/reversed_empty_ranges_loops_unfixable.stderr @@ -0,0 +1,16 @@ +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_loops_unfixable.rs:4:14 + | +LL | for i in 5..5 { + | ^^^^ + | + = note: `-D clippy::reversed-empty-ranges` implied by `-D warnings` + +error: this range is empty so it will yield no values + --> $DIR/reversed_empty_ranges_loops_unfixable.rs:8:14 + | +LL | for i in (5 + 2)..(8 - 1) { + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From e4cd8e7961b553cac44671d63bc6dfc2223ea66b Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Tue, 12 May 2020 22:05:56 +0200 Subject: [PATCH 052/526] Fix ICE caused in unwrap module --- clippy_lints/src/unwrap.rs | 12 +++++++++-- .../ui/checked_unwrap/simple_conditionals.rs | 21 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index f3844c7d3b6..8b971e7064b 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -8,6 +8,7 @@ use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnO use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::Ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -90,6 +91,14 @@ fn collect_unwrap_info<'a, 'tcx>( branch: &'tcx Expr<'_>, invert: bool, ) -> Vec<UnwrapInfo<'tcx>> { + fn is_relevant_option_call(cx: &LateContext<'_, '_>, ty: Ty<'_>, method_name: &str) -> bool { + is_type_diagnostic_item(cx, ty, sym!(option_type)) && ["is_some", "is_none"].contains(&method_name) + } + + fn is_relevant_result_call(cx: &LateContext<'_, '_>, ty: Ty<'_>, method_name: &str) -> bool { + is_type_diagnostic_item(cx, ty, sym!(result_type)) && ["is_ok", "is_err"].contains(&method_name) + } + if let ExprKind::Binary(op, left, right) = &expr.kind { match (invert, op.node) { (false, BinOpKind::And) | (false, BinOpKind::BitAnd) | (true, BinOpKind::Or) | (true, BinOpKind::BitOr) => { @@ -106,9 +115,8 @@ fn collect_unwrap_info<'a, 'tcx>( if let ExprKind::MethodCall(method_name, _, args) = &expr.kind; if let ExprKind::Path(QPath::Resolved(None, path)) = &args[0].kind; let ty = cx.tables.expr_ty(&args[0]); - if is_type_diagnostic_item(cx, ty, sym!(option_type)) || is_type_diagnostic_item(cx, ty, sym!(result_type)); let name = method_name.ident.as_str(); - if ["is_some", "is_none", "is_ok", "is_err"].contains(&&*name); + if is_relevant_option_call(cx, ty, &name) || is_relevant_result_call(cx, ty, &name); then { assert!(args.len() == 1); let unwrappable = match name.as_ref() { diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs index 3e7b4b390ba..49794e0c241 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/tests/ui/checked_unwrap/simple_conditionals.rs @@ -78,3 +78,24 @@ fn main() { assert!(x.is_ok(), "{:?}", x.unwrap_err()); // ok, it's a common test pattern } + +mod issue_5579 { + trait IsErr { + fn is_err(&self, err: &str) -> bool; + } + + impl<T> IsErr for Option<T> { + fn is_err(&self, _err: &str) -> bool { + true + } + } + + #[allow(unused)] + fn boom() { + let t = Some(1); + + if t.is_err("") { + t.unwrap(); + } + } +} From 8d1029d3ca013687422b58d0e99084a4e3421089 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Wed, 13 May 2020 20:47:44 +0200 Subject: [PATCH 053/526] Move test for issue 5579 under tests/ui/crashes --- .../ui/checked_unwrap/simple_conditionals.rs | 21 ------------------- tests/ui/crashes/ice-5579.rs | 17 +++++++++++++++ 2 files changed, 17 insertions(+), 21 deletions(-) create mode 100644 tests/ui/crashes/ice-5579.rs diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs index 49794e0c241..3e7b4b390ba 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/tests/ui/checked_unwrap/simple_conditionals.rs @@ -78,24 +78,3 @@ fn main() { assert!(x.is_ok(), "{:?}", x.unwrap_err()); // ok, it's a common test pattern } - -mod issue_5579 { - trait IsErr { - fn is_err(&self, err: &str) -> bool; - } - - impl<T> IsErr for Option<T> { - fn is_err(&self, _err: &str) -> bool { - true - } - } - - #[allow(unused)] - fn boom() { - let t = Some(1); - - if t.is_err("") { - t.unwrap(); - } - } -} diff --git a/tests/ui/crashes/ice-5579.rs b/tests/ui/crashes/ice-5579.rs new file mode 100644 index 00000000000..e1842c73f0e --- /dev/null +++ b/tests/ui/crashes/ice-5579.rs @@ -0,0 +1,17 @@ +trait IsErr { + fn is_err(&self, err: &str) -> bool; +} + +impl<T> IsErr for Option<T> { + fn is_err(&self, _err: &str) -> bool { + true + } +} + +fn main() { + let t = Some(1); + + if t.is_err("") { + t.unwrap(); + } +} From 671c1e34cc11767aa4ea257b9f5c40dcee1441fd Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Wed, 13 May 2020 21:07:13 +0200 Subject: [PATCH 054/526] Avoid running doctest that is expected to panic --- clippy_lints/src/ranges.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 86d55ccabb6..83c6faac041 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -98,7 +98,7 @@ declare_clippy_lint! { /// /// **Example:** /// - /// ```rust + /// ```rust,no_run /// fn main() { /// (10..=0).for_each(|x| println!("{}", x)); /// From 9217675c7f6ccd2efa18047ebb0c86841683b6a5 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 14 May 2020 00:26:09 +0200 Subject: [PATCH 055/526] Fix comparison_chain false positive --- clippy_lints/src/comparison_chain.rs | 17 +++++-- tests/ui/comparison_chain.rs | 66 ++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index 96df3ffe3ce..93e29edcaa5 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -81,12 +81,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ComparisonChain { // Check that both sets of operands are equal let mut spanless_eq = SpanlessEq::new(cx); - if (!spanless_eq.eq_expr(lhs1, lhs2) || !spanless_eq.eq_expr(rhs1, rhs2)) - && (!spanless_eq.eq_expr(lhs1, rhs2) || !spanless_eq.eq_expr(rhs1, lhs2)) - { + let same_fixed_operands = spanless_eq.eq_expr(lhs1, lhs2) && spanless_eq.eq_expr(rhs1, rhs2); + let same_transposed_operands = spanless_eq.eq_expr(lhs1, rhs2) && spanless_eq.eq_expr(rhs1, lhs2); + + if !same_fixed_operands && !same_transposed_operands { return; } + // Check that if the operation is the same, either it's not `==` or the operands are transposed + if kind1.node == kind2.node { + if kind1.node == BinOpKind::Eq { + return; + } + if !same_transposed_operands { + return; + } + } + // Check that the type being compared implements `core::cmp::Ord` let ty = cx.tables.expr_ty(lhs1); let is_ord = get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[])); diff --git a/tests/ui/comparison_chain.rs b/tests/ui/comparison_chain.rs index 9c2128469de..3b03f8c7dfe 100644 --- a/tests/ui/comparison_chain.rs +++ b/tests/ui/comparison_chain.rs @@ -137,4 +137,70 @@ fn h<T: Ord>(x: T, y: T, z: T) { } } +// The following uses should be ignored +mod issue_5212 { + use super::{a, b, c}; + fn foo() -> u8 { + 21 + } + + fn same_operation_equals() { + // operands are fixed + + if foo() == 42 { + a() + } else if foo() == 42 { + b() + } + + if foo() == 42 { + a() + } else if foo() == 42 { + b() + } else { + c() + } + + // operands are transposed + + if foo() == 42 { + a() + } else if 42 == foo() { + b() + } + } + + fn same_operation_not_equals() { + // operands are fixed + + if foo() > 42 { + a() + } else if foo() > 42 { + b() + } + + if foo() > 42 { + a() + } else if foo() > 42 { + b() + } else { + c() + } + + if foo() < 42 { + a() + } else if foo() < 42 { + b() + } + + if foo() < 42 { + a() + } else if foo() < 42 { + b() + } else { + c() + } + } +} + fn main() {} From 945c9447093a2ca944e70bae125f2af69f8eac16 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sun, 3 May 2020 11:20:51 +0200 Subject: [PATCH 056/526] Merge `block_in_if_condition_expr` and `block_in_if_condition_stmt` lints into `block_in_if_condition` lint --- CHANGELOG.md | 3 +- clippy_lints/src/block_in_if_condition.rs | 53 +++++++++---------- clippy_lints/src/lib.rs | 9 ++-- src/lintlist/mod.rs | 11 +--- tests/ui/block_in_if_condition.fixed | 3 +- tests/ui/block_in_if_condition.rs | 3 +- tests/ui/block_in_if_condition.stderr | 10 ++-- tests/ui/block_in_if_condition_closure.rs | 5 +- tests/ui/block_in_if_condition_closure.stderr | 6 +-- 9 files changed, 42 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b25ef049356..0b270e6acd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1274,8 +1274,7 @@ Released 2018-09-13 [`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock [`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask [`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name -[`block_in_if_condition_expr`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition_expr -[`block_in_if_condition_stmt`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition_stmt +[`block_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition [`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison [`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const [`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 9e533eaa32c..8a5e595749f 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -8,43 +8,40 @@ use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { - /// **What it does:** Checks for `if` conditions that use blocks to contain an - /// expression. + /// **What it does:** Checks for `if` conditions that use blocks containing an + /// expression, statements or conditions that use closures with blocks. /// - /// **Why is this bad?** It isn't really Rust style, same as using parentheses - /// to contain expressions. + /// **Why is this bad?** Style, using blocks in the condition makes it hard to read. /// /// **Known problems:** None. /// - /// **Example:** + /// **Examples:** /// ```rust + /// // Bad /// if { true } { /* ... */ } + /// + /// // Good + /// if true { /* ... */ } /// ``` - pub BLOCK_IN_IF_CONDITION_EXPR, - style, - "braces that can be eliminated in conditions, e.g., `if { true } ...`" -} - -declare_clippy_lint! { - /// **What it does:** Checks for `if` conditions that use blocks containing - /// statements, or conditions that use closures with blocks. /// - /// **Why is this bad?** Using blocks in the condition makes it hard to read. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust,ignore - /// if { let x = somefunc(); x } {} /// // or - /// if somefunc(|x| { x == 47 }) {} + /// + /// ```rust + /// # fn somefunc() -> bool { true }; + /// + /// // Bad + /// if { let x = somefunc(); x } { /* ... */ } + /// + /// // Good + /// let res = { let x = somefunc(); x }; + /// if res { /* ... */ } /// ``` - pub BLOCK_IN_IF_CONDITION_STMT, + pub BLOCK_IN_IF_CONDITION, style, - "complex blocks in conditions, e.g., `if { let x = true; x } ...`" + "useless or complex blocks that can be eliminated in conditions" } -declare_lint_pass!(BlockInIfCondition => [BLOCK_IN_IF_CONDITION_EXPR, BLOCK_IN_IF_CONDITION_STMT]); +declare_lint_pass!(BlockInIfCondition => [BLOCK_IN_IF_CONDITION]); struct ExVisitor<'a, 'tcx> { found_block: Option<&'tcx Expr<'tcx>>, @@ -72,7 +69,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> { const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression condition"; const COMPLEX_BLOCK_MESSAGE: &str = "in an `if` condition, avoid complex blocks or closures with blocks; \ - instead, move the block or closure higher and bind it with a `let`"; + instead, move the block or closure higher and bind it with a `let`"; impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { @@ -92,7 +89,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, - BLOCK_IN_IF_CONDITION_EXPR, + BLOCK_IN_IF_CONDITION, cond.span, BRACED_EXPR_MESSAGE, "try", @@ -118,7 +115,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, - BLOCK_IN_IF_CONDITION_STMT, + BLOCK_IN_IF_CONDITION, expr.span.with_hi(cond.span.hi()), COMPLEX_BLOCK_MESSAGE, "try", @@ -140,7 +137,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { let mut visitor = ExVisitor { found_block: None, cx }; walk_expr(&mut visitor, cond); if let Some(block) = visitor.found_block { - span_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE); + span_lint(cx, BLOCK_IN_IF_CONDITION, block.span, COMPLEX_BLOCK_MESSAGE); } } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0c4daeb731f..98b696533d8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -507,8 +507,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &bit_mask::INEFFECTIVE_BIT_MASK, &bit_mask::VERBOSE_BIT_MASK, &blacklisted_name::BLACKLISTED_NAME, - &block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR, - &block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT, + &block_in_if_condition::BLOCK_IN_IF_CONDITION, &booleans::LOGIC_BUG, &booleans::NONMINIMAL_BOOL, &bytecount::NAIVE_BYTECOUNT, @@ -1209,8 +1208,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK), LintId::of(&bit_mask::VERBOSE_BIT_MASK), LintId::of(&blacklisted_name::BLACKLISTED_NAME), - LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR), - LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT), + LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION), LintId::of(&booleans::LOGIC_BUG), LintId::of(&booleans::NONMINIMAL_BOOL), LintId::of(&bytecount::NAIVE_BYTECOUNT), @@ -1456,8 +1454,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS), LintId::of(&bit_mask::VERBOSE_BIT_MASK), LintId::of(&blacklisted_name::BLACKLISTED_NAME), - LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR), - LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT), + LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION), LintId::of(&collapsible_if::COLLAPSIBLE_IF), LintId::of(&comparison_chain::COMPARISON_CHAIN), LintId::of(&doc::MISSING_SAFETY_DOC), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index e1a6d4bdd31..4ae60f7d808 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -74,16 +74,9 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ module: "blacklisted_name", }, Lint { - name: "block_in_if_condition_expr", + name: "block_in_if_condition", group: "style", - desc: "braces that can be eliminated in conditions, e.g., `if { true } ...`", - deprecation: None, - module: "block_in_if_condition", - }, - Lint { - name: "block_in_if_condition_stmt", - group: "style", - desc: "complex blocks in conditions, e.g., `if { let x = true; x } ...`", + desc: "useless or complex blocks that can be eliminated in conditions", deprecation: None, module: "block_in_if_condition", }, diff --git a/tests/ui/block_in_if_condition.fixed b/tests/ui/block_in_if_condition.fixed index 955801e40f9..ae01c6d3042 100644 --- a/tests/ui/block_in_if_condition.fixed +++ b/tests/ui/block_in_if_condition.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![warn(clippy::block_in_if_condition_expr)] -#![warn(clippy::block_in_if_condition_stmt)] +#![warn(clippy::block_in_if_condition)] #![allow(unused, clippy::let_and_return)] #![warn(clippy::nonminimal_bool)] diff --git a/tests/ui/block_in_if_condition.rs b/tests/ui/block_in_if_condition.rs index a6ea01d5fc5..88555dc47c2 100644 --- a/tests/ui/block_in_if_condition.rs +++ b/tests/ui/block_in_if_condition.rs @@ -1,6 +1,5 @@ // run-rustfix -#![warn(clippy::block_in_if_condition_expr)] -#![warn(clippy::block_in_if_condition_stmt)] +#![warn(clippy::block_in_if_condition)] #![allow(unused, clippy::let_and_return)] #![warn(clippy::nonminimal_bool)] diff --git a/tests/ui/block_in_if_condition.stderr b/tests/ui/block_in_if_condition.stderr index b0a0a276c89..89e9ad26f49 100644 --- a/tests/ui/block_in_if_condition.stderr +++ b/tests/ui/block_in_if_condition.stderr @@ -1,5 +1,5 @@ error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/block_in_if_condition.rs:27:5 + --> $DIR/block_in_if_condition.rs:26:5 | LL | / if { LL | | let x = 3; @@ -7,7 +7,7 @@ LL | | x == 3 LL | | } { | |_____^ | - = note: `-D clippy::block-in-if-condition-stmt` implied by `-D warnings` + = note: `-D clippy::block-in-if-condition` implied by `-D warnings` help: try | LL | let res = { @@ -17,15 +17,13 @@ LL | }; if res { | error: omit braces around single expression condition - --> $DIR/block_in_if_condition.rs:38:8 + --> $DIR/block_in_if_condition.rs:37:8 | LL | if { true } { | ^^^^^^^^ help: try: `true` - | - = note: `-D clippy::block-in-if-condition-expr` implied by `-D warnings` error: this boolean expression can be simplified - --> $DIR/block_in_if_condition.rs:47:8 + --> $DIR/block_in_if_condition.rs:46:8 | LL | if true && x == 3 { | ^^^^^^^^^^^^^^ help: try: `x == 3` diff --git a/tests/ui/block_in_if_condition_closure.rs b/tests/ui/block_in_if_condition_closure.rs index bac3eda5e7f..87b3fb94daf 100644 --- a/tests/ui/block_in_if_condition_closure.rs +++ b/tests/ui/block_in_if_condition_closure.rs @@ -1,5 +1,4 @@ -#![warn(clippy::block_in_if_condition_expr)] -#![warn(clippy::block_in_if_condition_stmt)] +#![warn(clippy::block_in_if_condition)] #![allow(unused, clippy::let_and_return)] fn predicate<F: FnOnce(T) -> bool, T>(pfn: F, val: T) -> bool { @@ -10,7 +9,7 @@ fn pred_test() { let v = 3; let sky = "blue"; // This is a sneaky case, where the block isn't directly in the condition, - // but is actually nside a closure that the condition is using. + // but is actually inside a closure that the condition is using. // The same principle applies -- add some extra expressions to make sure // linter isn't confused by them. if v == 3 diff --git a/tests/ui/block_in_if_condition_closure.stderr b/tests/ui/block_in_if_condition_closure.stderr index 86cd24fe763..3df25691c3c 100644 --- a/tests/ui/block_in_if_condition_closure.stderr +++ b/tests/ui/block_in_if_condition_closure.stderr @@ -1,5 +1,5 @@ error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/block_in_if_condition_closure.rs:19:17 + --> $DIR/block_in_if_condition_closure.rs:18:17 | LL | |x| { | _________________^ @@ -8,10 +8,10 @@ LL | | x == target LL | | }, | |_____________^ | - = note: `-D clippy::block-in-if-condition-stmt` implied by `-D warnings` + = note: `-D clippy::block-in-if-condition` implied by `-D warnings` error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/block_in_if_condition_closure.rs:28:13 + --> $DIR/block_in_if_condition_closure.rs:27:13 | LL | |x| { | _____________^ From 6cbdd1e49dbb2355ac1036946a5a635e22023c6f Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sun, 3 May 2020 12:28:40 +0200 Subject: [PATCH 057/526] Merge `option_map_unwrap_or`, `option_map_unwrap_or_else` and `result_map_unwrap_or_else` lints into `map_unwrap` lint --- CHANGELOG.md | 4 +- clippy_lints/src/lib.rs | 8 +- clippy_lints/src/methods/mod.rs | 94 ++++++------------- .../src/methods/option_map_unwrap_or.rs | 6 +- src/lintlist/mod.rs | 28 ++---- ...{option_map_unwrap_or.rs => map_unwrap.rs} | 23 +++-- ...map_unwrap_or.stderr => map_unwrap.stderr} | 49 +++++++--- tests/ui/result_map_unwrap_or_else.rs | 23 ----- tests/ui/result_map_unwrap_or_else.stderr | 27 ------ 9 files changed, 95 insertions(+), 167 deletions(-) rename tests/ui/{option_map_unwrap_or.rs => map_unwrap.rs} (75%) rename tests/ui/{option_map_unwrap_or.stderr => map_unwrap.stderr} (70%) delete mode 100644 tests/ui/result_map_unwrap_or_else.rs delete mode 100644 tests/ui/result_map_unwrap_or_else.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b270e6acd2..28b05044db6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1430,6 +1430,7 @@ Released 2018-09-13 [`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone [`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry [`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten +[`map_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap [`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref [`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool [`match_on_vec_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_on_vec_items @@ -1499,8 +1500,6 @@ Released 2018-09-13 [`option_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_expect_used [`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn -[`option_map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or -[`option_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or_else [`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option [`option_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_unwrap_used [`or_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call @@ -1542,7 +1541,6 @@ Released 2018-09-13 [`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used [`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_or_into_option [`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn -[`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else [`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used [`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges [`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 98b696533d8..c9a2ef49907 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -673,19 +673,17 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::ITER_SKIP_NEXT, &methods::MANUAL_SATURATING_ARITHMETIC, &methods::MAP_FLATTEN, + &methods::MAP_UNWRAP, &methods::NEW_RET_NO_SELF, &methods::OK_EXPECT, &methods::OPTION_AND_THEN_SOME, &methods::OPTION_AS_REF_DEREF, &methods::OPTION_EXPECT_USED, &methods::OPTION_MAP_OR_NONE, - &methods::OPTION_MAP_UNWRAP_OR, - &methods::OPTION_MAP_UNWRAP_OR_ELSE, &methods::OPTION_UNWRAP_USED, &methods::OR_FUN_CALL, &methods::RESULT_EXPECT_USED, &methods::RESULT_MAP_OR_INTO_OPTION, - &methods::RESULT_MAP_UNWRAP_OR_ELSE, &methods::RESULT_UNWRAP_USED, &methods::SEARCH_IS_SOME, &methods::SHOULD_IMPLEMENT_TRAIT, @@ -1152,9 +1150,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::FIND_MAP), LintId::of(&methods::INEFFICIENT_TO_STRING), LintId::of(&methods::MAP_FLATTEN), - LintId::of(&methods::OPTION_MAP_UNWRAP_OR), - LintId::of(&methods::OPTION_MAP_UNWRAP_OR_ELSE), - LintId::of(&methods::RESULT_MAP_UNWRAP_OR_ELSE), + LintId::of(&methods::MAP_UNWRAP), LintId::of(&misc::USED_UNDERSCORE_BINDING), LintId::of(&misc_early::UNSEPARATED_LITERAL_SUFFIX), LintId::of(&mut_mut::MUT_MUT), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 3676dc5b09d..401298b2d51 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -257,59 +257,40 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Checks for usage of `_.map(_).unwrap_or(_)`. + /// **What it does:** Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or + /// `result.map(_).unwrap_or_else(_)`. /// - /// **Why is this bad?** Readability, this can be written more concisely as - /// `_.map_or(_, _)`. + /// **Why is this bad?** Readability, these can be written more concisely (resp.) as + /// `option.map_or(_, _)`, `option.map_or_else(_, _)` and `result.map_or_else(_, _)`. /// /// **Known problems:** The order of the arguments is not in execution order /// - /// **Example:** + /// **Examples:** /// ```rust /// # let x = Some(1); + /// + /// // Bad /// x.map(|a| a + 1).unwrap_or(0); + /// + /// // Good + /// x.map_or(0, |a| a + 1); /// ``` - pub OPTION_MAP_UNWRAP_OR, - pedantic, - "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)`" -} - -declare_clippy_lint! { - /// **What it does:** Checks for usage of `_.map(_).unwrap_or_else(_)`. /// - /// **Why is this bad?** Readability, this can be written more concisely as - /// `_.map_or_else(_, _)`. + /// // or /// - /// **Known problems:** The order of the arguments is not in execution order. - /// - /// **Example:** - /// ```rust - /// # let x = Some(1); - /// # fn some_function() -> usize { 1 } - /// x.map(|a| a + 1).unwrap_or_else(some_function); - /// ``` - pub OPTION_MAP_UNWRAP_OR_ELSE, - pedantic, - "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`" -} - -declare_clippy_lint! { - /// **What it does:** Checks for usage of `result.map(_).unwrap_or_else(_)`. - /// - /// **Why is this bad?** Readability, this can be written more concisely as - /// `result.map_or_else(_, _)`. - /// - /// **Known problems:** None. - /// - /// **Example:** /// ```rust /// # let x: Result<usize, ()> = Ok(1); /// # fn some_function(foo: ()) -> usize { 1 } + /// + /// // Bad /// x.map(|a| a + 1).unwrap_or_else(some_function); + /// + /// // Good + /// x.map_or_else(some_function, |a| a + 1); /// ``` - pub RESULT_MAP_UNWRAP_OR_ELSE, + pub MAP_UNWRAP, pedantic, - "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.map_or_else(g, f)`" + "using `.map(f).unwrap_or(a)` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)` or `map_or_else(a, f)`" } declare_clippy_lint! { @@ -1294,9 +1275,7 @@ declare_lint_pass!(Methods => [ WRONG_SELF_CONVENTION, WRONG_PUB_SELF_CONVENTION, OK_EXPECT, - OPTION_MAP_UNWRAP_OR, - OPTION_MAP_UNWRAP_OR_ELSE, - RESULT_MAP_UNWRAP_OR_ELSE, + MAP_UNWRAP, RESULT_MAP_OR_INTO_OPTION, OPTION_MAP_OR_NONE, OPTION_AND_THEN_SOME, @@ -1503,9 +1482,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { cx, lint, first_arg.pat.span, - &format!( - "methods called `{}` usually take {}; consider choosing a less \ - ambiguous name", + &format!("methods called `{}` usually take {}; consider choosing a less ambiguous name", conv, &self_kinds .iter() @@ -1678,7 +1655,7 @@ fn lint_or_fun_call<'a, 'tcx>( let self_ty = cx.tables.expr_ty(self_expr); if let Some(&(_, fn_has_arguments, poss, suffix)) = - know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)); + know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)); if poss.contains(&name); @@ -1931,7 +1908,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir: CLONE_DOUBLE_REF, expr.span, "using `clone` on a double-reference; \ - this will copy the reference instead of cloning the inner type", + this will copy the reference instead of cloning the inner type", |diag| { if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { let mut ty = innermost; @@ -2121,7 +2098,7 @@ fn lint_iter_cloned_collect<'a, 'tcx>( ITER_CLONED_COLLECT, to_replace, "called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \ - more readable", + more readable", "try", ".to_vec()".to_string(), Applicability::MachineApplicable, @@ -2436,7 +2413,7 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hi None, &format!( "if you don't want to handle the `{}` case gracefully, consider \ - using `expect()` to provide a better panic message", + using `expect()` to provide a better panic message", none_value, ), ); @@ -2494,7 +2471,7 @@ fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr< // lint if caller of `.map().flatten()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `map(..).flatten()` on an `Iterator`. \ - This is more succinctly expressed by calling `.flat_map(..)`"; + This is more succinctly expressed by calling `.flat_map(..)`"; let self_snippet = snippet(cx, map_args[0].span, ".."); let func_snippet = snippet(cx, map_args[1].span, ".."); let hint = format!("{0}.flat_map({1})", self_snippet, func_snippet); @@ -2555,10 +2532,10 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( // lint message let msg = if is_option { "called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling \ - `map_or_else(g, f)` instead" + `map_or_else(g, f)` instead" } else { "called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling \ - `.map_or_else(g, f)` instead" + `.map_or_else(g, f)` instead" }; // get snippets for args to map() and unwrap_or_else() let map_snippet = snippet(cx, map_args[1].span, ".."); @@ -2570,11 +2547,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( if same_span && !multiline { span_lint_and_note( cx, - if is_option { - OPTION_MAP_UNWRAP_OR_ELSE - } else { - RESULT_MAP_UNWRAP_OR_ELSE - }, + MAP_UNWRAP, expr.span, msg, None, @@ -2584,16 +2557,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( ), ); } else if same_span && multiline { - span_lint( - cx, - if is_option { - OPTION_MAP_UNWRAP_OR_ELSE - } else { - RESULT_MAP_UNWRAP_OR_ELSE - }, - expr.span, - msg, - ); + span_lint(cx, MAP_UNWRAP, expr.span, msg); }; } } diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index bf9dd3c9369..fcaa9b47e64 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -9,7 +9,7 @@ use rustc_middle::hir::map::Map; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; -use super::OPTION_MAP_UNWRAP_OR; +use super::MAP_UNWRAP; /// lint use of `map().unwrap_or()` for `Option`s pub(super) fn lint<'a, 'tcx>( @@ -62,11 +62,11 @@ pub(super) fn lint<'a, 'tcx>( }; let msg = &format!( "called `map(f).unwrap_or({})` on an `Option` value. \ - This can be done more directly by calling `{}` instead", + This can be done more directly by calling `{}` instead", arg, suggest ); - span_lint_and_then(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, |diag| { + span_lint_and_then(cx, MAP_UNWRAP, expr.span, msg, |diag| { let map_arg_span = map_args[1].span; let mut suggestion = vec![ diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 4ae60f7d808..d3bd9f66e38 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1137,6 +1137,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "methods", }, + Lint { + name: "map_unwrap", + group: "pedantic", + desc: "using `.map(f).unwrap_or(a)` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)` or `map_or_else(a, f)`", + deprecation: None, + module: "methods", + }, Lint { name: "match_as_ref", group: "complexity", @@ -1613,20 +1620,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "map_unit_fn", }, - Lint { - name: "option_map_unwrap_or", - group: "pedantic", - desc: "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)`", - deprecation: None, - module: "methods", - }, - Lint { - name: "option_map_unwrap_or_else", - group: "pedantic", - desc: "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`", - deprecation: None, - module: "methods", - }, Lint { name: "option_option", group: "pedantic", @@ -1900,13 +1893,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "map_unit_fn", }, - Lint { - name: "result_map_unwrap_or_else", - group: "pedantic", - desc: "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.map_or_else(g, f)`", - deprecation: None, - module: "methods", - }, Lint { name: "result_unwrap_used", group: "restriction", diff --git a/tests/ui/option_map_unwrap_or.rs b/tests/ui/map_unwrap.rs similarity index 75% rename from tests/ui/option_map_unwrap_or.rs rename to tests/ui/map_unwrap.rs index 0364d83663a..53e50368231 100644 --- a/tests/ui/option_map_unwrap_or.rs +++ b/tests/ui/map_unwrap.rs @@ -1,21 +1,18 @@ // FIXME: Add "run-rustfix" once it's supported for multipart suggestions // aux-build:option_helpers.rs -#![warn(clippy::option_map_unwrap_or, clippy::option_map_unwrap_or_else)] +#![warn(clippy::map_unwrap)] #[macro_use] extern crate option_helpers; use std::collections::HashMap; -/// Checks implementation of the following lints: -/// * `OPTION_MAP_UNWRAP_OR` -/// * `OPTION_MAP_UNWRAP_OR_ELSE` #[rustfmt::skip] fn option_methods() { let opt = Some(1); - // Check `OPTION_MAP_UNWRAP_OR`. + // Check for `option.map(_).unwrap_or(_)` use. // Single line case. let _ = opt.map(|x| x + 1) // Should lint even though this call is on a separate line. @@ -49,7 +46,7 @@ fn option_methods() { let id: String = "identifier".to_string(); let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); - // Check OPTION_MAP_UNWRAP_OR_ELSE + // Check for `option.map(_).unwrap_or_else(_)` use. // single line case let _ = opt.map(|x| x + 1) // Should lint even though this call is on a separate line. @@ -83,6 +80,20 @@ fn option_methods() { } } +fn result_methods() { + let res: Result<i32, ()> = Ok(1); + + // Check for `result.map(_).unwrap_or_else(_)` use. + // single line case + let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + // multi line cases + let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + // macro case + let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint +} + fn main() { option_methods(); + result_methods(); } diff --git a/tests/ui/option_map_unwrap_or.stderr b/tests/ui/map_unwrap.stderr similarity index 70% rename from tests/ui/option_map_unwrap_or.stderr rename to tests/ui/map_unwrap.stderr index f05f2893de2..2610923275d 100644 --- a/tests/ui/option_map_unwrap_or.stderr +++ b/tests/ui/map_unwrap.stderr @@ -1,5 +1,5 @@ error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/option_map_unwrap_or.rs:20:13 + --> $DIR/map_unwrap.rs:17:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -7,14 +7,14 @@ LL | | // Should lint even though this call is on a separate line. LL | | .unwrap_or(0); | |_____________________^ | - = note: `-D clippy::option-map-unwrap-or` implied by `-D warnings` + = note: `-D clippy::map-unwrap` implied by `-D warnings` help: use `map_or(a, f)` instead | LL | let _ = opt.map_or(0, |x| x + 1); | ^^^^^^ ^^ -- error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/option_map_unwrap_or.rs:24:13 + --> $DIR/map_unwrap.rs:21:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -32,7 +32,7 @@ LL | ); | error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/option_map_unwrap_or.rs:28:13 + --> $DIR/map_unwrap.rs:25:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -49,7 +49,7 @@ LL | }, |x| x + 1); | error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/option_map_unwrap_or.rs:33:13 + --> $DIR/map_unwrap.rs:30:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | let _ = opt.and_then(|x| Some(x + 1)); | ^^^^^^^^ -- error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/option_map_unwrap_or.rs:35:13 + --> $DIR/map_unwrap.rs:32:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -78,7 +78,7 @@ LL | ); | error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/option_map_unwrap_or.rs:39:13 + --> $DIR/map_unwrap.rs:36:13 | LL | let _ = opt | _____________^ @@ -92,7 +92,7 @@ LL | .and_then(|x| Some(x + 1)); | ^^^^^^^^ -- error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/option_map_unwrap_or.rs:50:13 + --> $DIR/map_unwrap.rs:47:13 | LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | let _ = Some("prefix").map_or(id, |p| format!("{}.", p)); | ^^^^^^ ^^^ -- error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/option_map_unwrap_or.rs:54:13 + --> $DIR/map_unwrap.rs:51:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -111,11 +111,10 @@ LL | | // Should lint even though this call is on a separate line. LL | | .unwrap_or_else(|| 0); | |_____________________________^ | - = note: `-D clippy::option-map-unwrap-or-else` implied by `-D warnings` = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/option_map_unwrap_or.rs:58:13 + --> $DIR/map_unwrap.rs:55:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -125,7 +124,7 @@ LL | | ).unwrap_or_else(|| 0); | |__________________________^ error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/option_map_unwrap_or.rs:62:13 + --> $DIR/map_unwrap.rs:59:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -134,5 +133,29 @@ LL | | 0 LL | | ); | |_________^ -error: aborting due to 10 previous errors +error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead + --> $DIR/map_unwrap.rs:88:13 + | +LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` + +error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead + --> $DIR/map_unwrap.rs:90:13 + | +LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` + +error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead + --> $DIR/map_unwrap.rs:91:13 + | +LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` + +error: aborting due to 13 previous errors diff --git a/tests/ui/result_map_unwrap_or_else.rs b/tests/ui/result_map_unwrap_or_else.rs deleted file mode 100644 index 40751bfebe6..00000000000 --- a/tests/ui/result_map_unwrap_or_else.rs +++ /dev/null @@ -1,23 +0,0 @@ -// aux-build:option_helpers.rs - -//! Checks implementation of `RESULT_MAP_UNWRAP_OR_ELSE` - -#![warn(clippy::result_map_unwrap_or_else)] - -#[macro_use] -extern crate option_helpers; - -fn result_methods() { - let res: Result<i32, ()> = Ok(1); - - // Check RESULT_MAP_UNWRAP_OR_ELSE - // single line case - let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line - // multi line cases - let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); - let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); - // macro case - let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint -} - -fn main() {} diff --git a/tests/ui/result_map_unwrap_or_else.stderr b/tests/ui/result_map_unwrap_or_else.stderr deleted file mode 100644 index ec7bc8f1241..00000000000 --- a/tests/ui/result_map_unwrap_or_else.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead - --> $DIR/result_map_unwrap_or_else.rs:15:13 - | -LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` - = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` - -error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead - --> $DIR/result_map_unwrap_or_else.rs:17:13 - | -LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` - -error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead - --> $DIR/result_map_unwrap_or_else.rs:18:13 - | -LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` - -error: aborting due to 3 previous errors - From bcf61666bd903c0d13c081cf222b423e45cd854e Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sun, 3 May 2020 13:11:18 +0200 Subject: [PATCH 058/526] Merge `option_unwrap_used` and `result_unwrap_used` lints into `unwrap_used` lint --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 6 +-- clippy_lints/src/methods/mod.rs | 68 ++++++++++++--------------------- src/lintlist/mod.rs | 14 +++---- tests/ui/unwrap.rs | 2 +- tests/ui/unwrap.stderr | 3 +- 6 files changed, 37 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28b05044db6..78f98bba2b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1501,7 +1501,6 @@ Released 2018-09-13 [`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn [`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option -[`option_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_unwrap_used [`or_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call [`out_of_bounds_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#out_of_bounds_indexing [`overflow_check_conditional`]: https://rust-lang.github.io/rust-clippy/master/index.html#overflow_check_conditional @@ -1622,6 +1621,7 @@ Released 2018-09-13 [`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label [`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self [`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit +[`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used [`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug [`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self [`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c9a2ef49907..bb3bc0b4545 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -680,11 +680,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::OPTION_AS_REF_DEREF, &methods::OPTION_EXPECT_USED, &methods::OPTION_MAP_OR_NONE, - &methods::OPTION_UNWRAP_USED, &methods::OR_FUN_CALL, &methods::RESULT_EXPECT_USED, &methods::RESULT_MAP_OR_INTO_OPTION, - &methods::RESULT_UNWRAP_USED, &methods::SEARCH_IS_SOME, &methods::SHOULD_IMPLEMENT_TRAIT, &methods::SINGLE_CHAR_PATTERN, @@ -695,6 +693,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::UNINIT_ASSUMED_INIT, &methods::UNNECESSARY_FILTER_MAP, &methods::UNNECESSARY_FOLD, + &methods::UNWRAP_USED, &methods::USELESS_ASREF, &methods::WRONG_PUB_SELF_CONVENTION, &methods::WRONG_SELF_CONVENTION, @@ -1090,9 +1089,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::FILETYPE_IS_FILE), LintId::of(&methods::GET_UNWRAP), LintId::of(&methods::OPTION_EXPECT_USED), - LintId::of(&methods::OPTION_UNWRAP_USED), LintId::of(&methods::RESULT_EXPECT_USED), - LintId::of(&methods::RESULT_UNWRAP_USED), + LintId::of(&methods::UNWRAP_USED), LintId::of(&methods::WRONG_PUB_SELF_CONVENTION), LintId::of(&misc::FLOAT_CMP_CONST), LintId::of(&misc_early::UNNEEDED_FIELD_PATTERN), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 401298b2d51..1af4d03c7a2 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -33,40 +33,15 @@ use crate::utils::{ }; declare_clippy_lint! { - /// **What it does:** Checks for `.unwrap()` calls on `Option`s. + /// **What it does:** Checks for `.unwrap()` calls on `Option`s and on `Result`s. /// - /// **Why is this bad?** Usually it is better to handle the `None` case, or to - /// at least call `.expect(_)` with a more helpful message. Still, for a lot of + /// **Why is this bad?** It is better to handle the `None` or `Err` case, + /// or at least call `.expect(_)` with a more helpful message. Still, for a lot of /// quick-and-dirty code, `unwrap` is a good choice, which is why this lint is /// `Allow` by default. /// - /// **Known problems:** None. - /// - /// **Example:** - /// - /// Using unwrap on an `Option`: - /// - /// ```rust - /// let opt = Some(1); - /// opt.unwrap(); - /// ``` - /// - /// Better: - /// - /// ```rust - /// let opt = Some(1); - /// opt.expect("more helpful message"); - /// ``` - pub OPTION_UNWRAP_USED, - restriction, - "using `Option.unwrap()`, which should at least get a better message using `expect()`" -} - -declare_clippy_lint! { - /// **What it does:** Checks for `.unwrap()` calls on `Result`s. - /// - /// **Why is this bad?** `result.unwrap()` will let the thread panic on `Err` - /// values. Normally, you want to implement more sophisticated error handling, + /// `result.unwrap()` will let the thread panic on `Err` values. + /// Normally, you want to implement more sophisticated error handling, /// and propagate errors upwards with `?` operator. /// /// Even if you want to panic on errors, not all `Error`s implement good @@ -75,23 +50,31 @@ declare_clippy_lint! { /// /// **Known problems:** None. /// - /// **Example:** - /// Using unwrap on an `Result`: - /// + /// **Examples:** /// ```rust - /// let res: Result<usize, ()> = Ok(1); - /// res.unwrap(); + /// # let opt = Some(1); + /// + /// // Bad + /// opt.unwrap(); + /// + /// // Good + /// opt.expect("more helpful message"); /// ``` /// - /// Better: + /// // or /// /// ```rust - /// let res: Result<usize, ()> = Ok(1); + /// # let res: Result<usize, ()> = Ok(1); + /// + /// // Bad + /// res.unwrap(); + /// + /// // Good /// res.expect("more helpful message"); /// ``` - pub RESULT_UNWRAP_USED, + pub UNWRAP_USED, restriction, - "using `Result.unwrap()`, which might be better handled" + "using `.unwrap()` on `Result` or `Option`, which should at least get a better message using `expect()`" } declare_clippy_lint! { @@ -1267,8 +1250,7 @@ declare_clippy_lint! { } declare_lint_pass!(Methods => [ - OPTION_UNWRAP_USED, - RESULT_UNWRAP_USED, + UNWRAP_USED, OPTION_EXPECT_USED, RESULT_EXPECT_USED, SHOULD_IMPLEMENT_TRAIT, @@ -2397,9 +2379,9 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hi let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&unwrap_args[0])); let mess = if is_type_diagnostic_item(cx, obj_ty, sym!(option_type)) { - Some((OPTION_UNWRAP_USED, "an Option", "None")) + Some((UNWRAP_USED, "an Option", "None")) } else if is_type_diagnostic_item(cx, obj_ty, sym!(result_type)) { - Some((RESULT_UNWRAP_USED, "a Result", "Err")) + Some((UNWRAP_USED, "a Result", "Err")) } else { None }; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index d3bd9f66e38..5cbf3ef028c 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1627,13 +1627,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "types", }, - Lint { - name: "option_unwrap_used", - group: "restriction", - desc: "using `Option.unwrap()`, which should at least get a better message using `expect()`", - deprecation: None, - module: "methods", - }, Lint { name: "or_fun_call", group: "perf", @@ -2404,6 +2397,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "returns", }, + Lint { + name: "unwrap_used", + group: "restriction", + desc: "using `.unwrap()` on `Result` or `Option`, which should at least get a better message using `expect()`", + deprecation: None, + module: "methods", + }, Lint { name: "use_debug", group: "restriction", diff --git a/tests/ui/unwrap.rs b/tests/ui/unwrap.rs index fcd1fcd14d4..a4a3cd1d379 100644 --- a/tests/ui/unwrap.rs +++ b/tests/ui/unwrap.rs @@ -1,4 +1,4 @@ -#![warn(clippy::option_unwrap_used, clippy::result_unwrap_used)] +#![warn(clippy::unwrap_used)] fn unwrap_option() { let opt = Some(0); diff --git a/tests/ui/unwrap.stderr b/tests/ui/unwrap.stderr index b90ce68fa97..4f0858005f6 100644 --- a/tests/ui/unwrap.stderr +++ b/tests/ui/unwrap.stderr @@ -4,7 +4,7 @@ error: used `unwrap()` on `an Option` value LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | - = note: `-D clippy::option-unwrap-used` implied by `-D warnings` + = note: `-D clippy::unwrap-used` implied by `-D warnings` = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: used `unwrap()` on `a Result` value @@ -13,7 +13,6 @@ error: used `unwrap()` on `a Result` value LL | let _ = res.unwrap(); | ^^^^^^^^^^^^ | - = note: `-D clippy::result-unwrap-used` implied by `-D warnings` = help: if you don't want to handle the `Err` case gracefully, consider using `expect()` to provide a better panic message error: aborting due to 2 previous errors From 0e8be599cd04a8566224c63eeb07f5fa04605702 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sun, 3 May 2020 13:32:17 +0200 Subject: [PATCH 059/526] Merge `option_expect_used` and `result_expect_used` lints into `expect_used` lint --- CHANGELOG.md | 3 +- clippy_lints/src/lib.rs | 6 +-- clippy_lints/src/methods/mod.rs | 69 +++++++++++++-------------------- src/lintlist/mod.rs | 21 ++++------ tests/ui/expect.rs | 2 +- tests/ui/expect.stderr | 3 +- 6 files changed, 38 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78f98bba2b4..4eeb71fa5c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1337,6 +1337,7 @@ Released 2018-09-13 [`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision [`exit`]: https://rust-lang.github.io/rust-clippy/master/index.html#exit [`expect_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_fun_call +[`expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_used [`expl_impl_clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy [`explicit_counter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_counter_loop [`explicit_deref_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_deref_methods @@ -1497,7 +1498,6 @@ Released 2018-09-13 [`option_and_then_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_and_then_some [`option_as_ref_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref [`option_env_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_env_unwrap -[`option_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_expect_used [`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn [`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option @@ -1537,7 +1537,6 @@ Released 2018-09-13 [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro [`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts [`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs -[`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used [`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_or_into_option [`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn [`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bb3bc0b4545..eaef1f543d3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -657,6 +657,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::CLONE_ON_COPY, &methods::CLONE_ON_REF_PTR, &methods::EXPECT_FUN_CALL, + &methods::EXPECT_USED, &methods::FILETYPE_IS_FILE, &methods::FILTER_MAP, &methods::FILTER_MAP_NEXT, @@ -678,10 +679,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::OK_EXPECT, &methods::OPTION_AND_THEN_SOME, &methods::OPTION_AS_REF_DEREF, - &methods::OPTION_EXPECT_USED, &methods::OPTION_MAP_OR_NONE, &methods::OR_FUN_CALL, - &methods::RESULT_EXPECT_USED, &methods::RESULT_MAP_OR_INTO_OPTION, &methods::SEARCH_IS_SOME, &methods::SHOULD_IMPLEMENT_TRAIT, @@ -1086,10 +1085,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&matches::WILDCARD_ENUM_MATCH_ARM), LintId::of(&mem_forget::MEM_FORGET), LintId::of(&methods::CLONE_ON_REF_PTR), + LintId::of(&methods::EXPECT_USED), LintId::of(&methods::FILETYPE_IS_FILE), LintId::of(&methods::GET_UNWRAP), - LintId::of(&methods::OPTION_EXPECT_USED), - LintId::of(&methods::RESULT_EXPECT_USED), LintId::of(&methods::UNWRAP_USED), LintId::of(&methods::WRONG_PUB_SELF_CONVENTION), LintId::of(&misc::FLOAT_CMP_CONST), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 1af4d03c7a2..2e75de019b6 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -78,61 +78,45 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Checks for `.expect()` calls on `Option`s. + /// **What it does:** Checks for `.expect()` calls on `Option`s and `Result`s. /// - /// **Why is this bad?** Usually it is better to handle the `None` case. Still, - /// for a lot of quick-and-dirty code, `expect` is a good choice, which is why - /// this lint is `Allow` by default. + /// **Why is this bad?** Usually it is better to handle the `None` or `Err` case. + /// Still, for a lot of quick-and-dirty code, `expect` is a good choice, which is why + /// this lint is `Allow` by default. /// - /// **Known problems:** None. - /// - /// **Example:** - /// - /// Using expect on an `Option`: - /// - /// ```rust - /// let opt = Some(1); - /// opt.expect("one"); - /// ``` - /// - /// Better: - /// - /// ```rust,ignore - /// let opt = Some(1); - /// opt?; - /// ``` - pub OPTION_EXPECT_USED, - restriction, - "using `Option.expect()`, which might be better handled" -} - -declare_clippy_lint! { - /// **What it does:** Checks for `.expect()` calls on `Result`s. - /// - /// **Why is this bad?** `result.expect()` will let the thread panic on `Err` + /// `result.expect()` will let the thread panic on `Err` /// values. Normally, you want to implement more sophisticated error handling, /// and propagate errors upwards with `?` operator. /// /// **Known problems:** None. /// - /// **Example:** - /// Using expect on an `Result`: + /// **Examples:** + /// ```rust,ignore + /// # let opt = Some(1); /// - /// ```rust - /// let res: Result<usize, ()> = Ok(1); - /// res.expect("one"); + /// // Bad + /// opt.expect("one"); + /// + /// // Good + /// let opt = Some(1); + /// opt?; /// ``` /// - /// Better: + /// // or /// /// ```rust - /// let res: Result<usize, ()> = Ok(1); + /// # let res: Result<usize, ()> = Ok(1); + /// + /// // Bad + /// res.expect("one"); + /// + /// // Good /// res?; /// # Ok::<(), ()>(()) /// ``` - pub RESULT_EXPECT_USED, + pub EXPECT_USED, restriction, - "using `Result.expect()`, which might be better handled" + "using `.expect()` on `Result` or `Option`, which might be better handled" } declare_clippy_lint! { @@ -1251,8 +1235,7 @@ declare_clippy_lint! { declare_lint_pass!(Methods => [ UNWRAP_USED, - OPTION_EXPECT_USED, - RESULT_EXPECT_USED, + EXPECT_USED, SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION, WRONG_PUB_SELF_CONVENTION, @@ -2407,9 +2390,9 @@ fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, expect_args: &[hi let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&expect_args[0])); let mess = if is_type_diagnostic_item(cx, obj_ty, sym!(option_type)) { - Some((OPTION_EXPECT_USED, "an Option", "None")) + Some((EXPECT_USED, "an Option", "None")) } else if is_type_diagnostic_item(cx, obj_ty, sym!(result_type)) { - Some((RESULT_EXPECT_USED, "a Result", "Err")) + Some((EXPECT_USED, "a Result", "Err")) } else { None }; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 5cbf3ef028c..4e79ce96bb5 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -514,6 +514,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "methods", }, + Lint { + name: "expect_used", + group: "restriction", + desc: "using `.expect()` on `Result` or `Option`, which might be better handled", + deprecation: None, + module: "methods", + }, Lint { name: "expl_impl_clone_on_copy", group: "pedantic", @@ -1599,13 +1606,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "option_env_unwrap", }, - Lint { - name: "option_expect_used", - group: "restriction", - desc: "using `Option.expect()`, which might be better handled", - deprecation: None, - module: "methods", - }, Lint { name: "option_map_or_none", group: "style", @@ -1865,13 +1865,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "matches", }, - Lint { - name: "result_expect_used", - group: "restriction", - desc: "using `Result.expect()`, which might be better handled", - deprecation: None, - module: "methods", - }, Lint { name: "result_map_or_into_option", group: "style", diff --git a/tests/ui/expect.rs b/tests/ui/expect.rs index 0bd4252c49a..1073acf6f0c 100644 --- a/tests/ui/expect.rs +++ b/tests/ui/expect.rs @@ -1,4 +1,4 @@ -#![warn(clippy::option_expect_used, clippy::result_expect_used)] +#![warn(clippy::expect_used)] fn expect_option() { let opt = Some(0); diff --git a/tests/ui/expect.stderr b/tests/ui/expect.stderr index adf9f4f1921..9d3fc7df15c 100644 --- a/tests/ui/expect.stderr +++ b/tests/ui/expect.stderr @@ -4,7 +4,7 @@ error: used `expect()` on `an Option` value LL | let _ = opt.expect(""); | ^^^^^^^^^^^^^^ | - = note: `-D clippy::option-expect-used` implied by `-D warnings` + = note: `-D clippy::expect-used` implied by `-D warnings` = help: if this value is an `None`, it will panic error: used `expect()` on `a Result` value @@ -13,7 +13,6 @@ error: used `expect()` on `a Result` value LL | let _ = res.expect(""); | ^^^^^^^^^^^^^^ | - = note: `-D clippy::result-expect-used` implied by `-D warnings` = help: if this value is an `Err`, it will panic error: aborting due to 2 previous errors From adbdf7549c6b24c37629eabdc4be0346e0c8fd56 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sun, 3 May 2020 15:16:00 +0200 Subject: [PATCH 060/526] Merge `for_loop_over_option` and `for_loop_over_result` lints into `for_loop_over_fallible` lint --- CHANGELOG.md | 3 +- clippy_lints/src/lib.rs | 9 +-- clippy_lints/src/loops.rs | 76 ++++++++----------- src/lintlist/mod.rs | 11 +-- ...on_result.rs => for_loop_over_fallible.rs} | 10 +-- ...t.stderr => for_loop_over_fallible.stderr} | 19 +++-- 6 files changed, 52 insertions(+), 76 deletions(-) rename tests/ui/{for_loop_over_option_result.rs => for_loop_over_fallible.rs} (81%) rename tests/ui/{for_loop_over_option_result.stderr => for_loop_over_fallible.stderr} (81%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4eeb71fa5c5..3f9486e0972 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1361,8 +1361,7 @@ Released 2018-09-13 [`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast [`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation [`for_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_kv_map -[`for_loop_over_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_option -[`for_loop_over_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_result +[`for_loop_over_fallible`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_fallible [`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy [`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref [`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index eaef1f543d3..8de94d19d31 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -615,8 +615,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::EXPLICIT_INTO_ITER_LOOP, &loops::EXPLICIT_ITER_LOOP, &loops::FOR_KV_MAP, - &loops::FOR_LOOP_OVER_OPTION, - &loops::FOR_LOOP_OVER_RESULT, + &loops::FOR_LOOP_OVER_FALLIBLE, &loops::ITER_NEXT_LOOP, &loops::MANUAL_MEMCPY, &loops::MUT_RANGE_BOUND, @@ -1265,8 +1264,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::EXPLICIT_COUNTER_LOOP), LintId::of(&loops::FOR_KV_MAP), - LintId::of(&loops::FOR_LOOP_OVER_OPTION), - LintId::of(&loops::FOR_LOOP_OVER_RESULT), + LintId::of(&loops::FOR_LOOP_OVER_FALLIBLE), LintId::of(&loops::ITER_NEXT_LOOP), LintId::of(&loops::MANUAL_MEMCPY), LintId::of(&loops::MUT_RANGE_BOUND), @@ -1641,8 +1639,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY), LintId::of(&let_underscore::LET_UNDERSCORE_LOCK), LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES), - LintId::of(&loops::FOR_LOOP_OVER_OPTION), - LintId::of(&loops::FOR_LOOP_OVER_RESULT), + LintId::of(&loops::FOR_LOOP_OVER_FALLIBLE), LintId::of(&loops::ITER_NEXT_LOOP), LintId::of(&loops::NEVER_LOOP), LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0bc6b70855b..da6793a69d6 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -168,7 +168,7 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Checks for `for` loops over `Option` values. + /// **What it does:** Checks for `for` loops over `Option` or `Result` values. /// /// **Why is this bad?** Readability. This is more clearly expressed as an `if /// let`. @@ -176,47 +176,38 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```ignore - /// for x in option { - /// .. + /// ```rust + /// # let opt = Some(1); + /// + /// // Bad + /// for x in opt { + /// // .. + /// } + /// + /// // Good + /// if let Some(x) = opt { + /// // .. /// } /// ``` /// - /// This should be - /// ```ignore - /// if let Some(x) = option { - /// .. + /// // or + /// + /// ```rust + /// # let res: Result<i32, std::io::Error> = Ok(1); + /// + /// // Bad + /// for x in &res { + /// // .. + /// } + /// + /// // Good + /// if let Ok(x) = res { + /// // .. /// } /// ``` - pub FOR_LOOP_OVER_OPTION, + pub FOR_LOOP_OVER_FALLIBLE, correctness, - "for-looping over an `Option`, which is more clearly expressed as an `if let`" -} - -declare_clippy_lint! { - /// **What it does:** Checks for `for` loops over `Result` values. - /// - /// **Why is this bad?** Readability. This is more clearly expressed as an `if - /// let`. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```ignore - /// for x in result { - /// .. - /// } - /// ``` - /// - /// This should be - /// ```ignore - /// if let Ok(x) = result { - /// .. - /// } - /// ``` - pub FOR_LOOP_OVER_RESULT, - correctness, - "for-looping over a `Result`, which is more clearly expressed as an `if let`" + "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`" } declare_clippy_lint! { @@ -435,8 +426,7 @@ declare_lint_pass!(Loops => [ EXPLICIT_ITER_LOOP, EXPLICIT_INTO_ITER_LOOP, ITER_NEXT_LOOP, - FOR_LOOP_OVER_RESULT, - FOR_LOOP_OVER_OPTION, + FOR_LOOP_OVER_FALLIBLE, WHILE_LET_LOOP, NEEDLESS_COLLECT, EXPLICIT_COUNTER_LOOP, @@ -1283,7 +1273,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, e ITER_NEXT_LOOP, expr.span, "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ - probably not what you want", + probably not what you want", ); next_loop_linted = true; } @@ -1300,11 +1290,11 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) { if is_type_diagnostic_item(cx, ty, sym!(option_type)) { span_lint_and_help( cx, - FOR_LOOP_OVER_OPTION, + FOR_LOOP_OVER_FALLIBLE, arg.span, &format!( "for loop over `{0}`, which is an `Option`. This is more readably written as an \ - `if let` statement.", + `if let` statement.", snippet(cx, arg.span, "_") ), None, @@ -1317,11 +1307,11 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) { } else if is_type_diagnostic_item(cx, ty, sym!(result_type)) { span_lint_and_help( cx, - FOR_LOOP_OVER_RESULT, + FOR_LOOP_OVER_FALLIBLE, arg.span, &format!( "for loop over `{0}`, which is a `Result`. This is more readably written as an \ - `if let` statement.", + `if let` statement.", snippet(cx, arg.span, "_") ), None, diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 4e79ce96bb5..0ea0f55a381 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -676,16 +676,9 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ module: "loops", }, Lint { - name: "for_loop_over_option", + name: "for_loop_over_fallible", group: "correctness", - desc: "for-looping over an `Option`, which is more clearly expressed as an `if let`", - deprecation: None, - module: "loops", - }, - Lint { - name: "for_loop_over_result", - group: "correctness", - desc: "for-looping over a `Result`, which is more clearly expressed as an `if let`", + desc: "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`", deprecation: None, module: "loops", }, diff --git a/tests/ui/for_loop_over_option_result.rs b/tests/ui/for_loop_over_fallible.rs similarity index 81% rename from tests/ui/for_loop_over_option_result.rs rename to tests/ui/for_loop_over_fallible.rs index 6b207b26b6b..e52468cdd4b 100644 --- a/tests/ui/for_loop_over_option_result.rs +++ b/tests/ui/for_loop_over_fallible.rs @@ -1,18 +1,16 @@ -#![warn(clippy::for_loop_over_option, clippy::for_loop_over_result)] +#![warn(clippy::for_loop_over_fallible)] -/// Tests for_loop_over_result and for_loop_over_option - -fn for_loop_over_option_and_result() { +fn for_loop_over_fallible() { let option = Some(1); let result = option.ok_or("x not found"); let v = vec![0, 1, 2]; - // check FOR_LOOP_OVER_OPTION lint + // check over an `Option` for x in option { println!("{}", x); } - // check FOR_LOOP_OVER_RESULT lint + // check over a `Result` for x in result { println!("{}", x); } diff --git a/tests/ui/for_loop_over_option_result.stderr b/tests/ui/for_loop_over_fallible.stderr similarity index 81% rename from tests/ui/for_loop_over_option_result.stderr rename to tests/ui/for_loop_over_fallible.stderr index 194a0bfec5b..4ce9a144ad8 100644 --- a/tests/ui/for_loop_over_option_result.stderr +++ b/tests/ui/for_loop_over_fallible.stderr @@ -1,23 +1,22 @@ error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_option_result.rs:11:14 + --> $DIR/for_loop_over_fallible.rs:9:14 | LL | for x in option { | ^^^^^^ | - = note: `-D clippy::for-loop-over-option` implied by `-D warnings` + = note: `-D clippy::for-loop-over-fallible` implied by `-D warnings` = help: consider replacing `for x in option` with `if let Some(x) = option` error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_option_result.rs:16:14 + --> $DIR/for_loop_over_fallible.rs:14:14 | LL | for x in result { | ^^^^^^ | - = note: `-D clippy::for-loop-over-result` implied by `-D warnings` = help: consider replacing `for x in result` with `if let Ok(x) = result` error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_option_result.rs:20:14 + --> $DIR/for_loop_over_fallible.rs:18:14 | LL | for x in option.ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +24,7 @@ LL | for x in option.ok_or("x not found") { = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop_over_option_result.rs:26:14 + --> $DIR/for_loop_over_fallible.rs:24:14 | LL | for x in v.iter().next() { | ^^^^^^^^^^^^^^^ @@ -33,7 +32,7 @@ LL | for x in v.iter().next() { = note: `#[deny(clippy::iter_next_loop)]` on by default error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_option_result.rs:31:14 + --> $DIR/for_loop_over_fallible.rs:29:14 | LL | for x in v.iter().next().and(Some(0)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +40,7 @@ LL | for x in v.iter().next().and(Some(0)) { = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_option_result.rs:35:14 + --> $DIR/for_loop_over_fallible.rs:33:14 | LL | for x in v.iter().next().ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +48,7 @@ LL | for x in v.iter().next().ok_or("x not found") { = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` error: this loop never actually loops - --> $DIR/for_loop_over_option_result.rs:47:5 + --> $DIR/for_loop_over_fallible.rs:45:5 | LL | / while let Some(x) = option { LL | | println!("{}", x); @@ -60,7 +59,7 @@ LL | | } = note: `#[deny(clippy::never_loop)]` on by default error: this loop never actually loops - --> $DIR/for_loop_over_option_result.rs:53:5 + --> $DIR/for_loop_over_fallible.rs:51:5 | LL | / while let Ok(x) = result { LL | | println!("{}", x); From 95399f8f941b89785c6e9d94e0bc32ff5d43ba06 Mon Sep 17 00:00:00 2001 From: David Tolnay <dtolnay@gmail.com> Date: Thu, 14 May 2020 09:57:36 -0700 Subject: [PATCH 061/526] Downgrade useless_let_if_seq to nursery --- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/lib.rs | 3 +-- src/lintlist/mod.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 398a3103a03..d7bf8a14768 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -50,7 +50,7 @@ declare_clippy_lint! { /// }; /// ``` pub USELESS_LET_IF_SEQ, - style, + nursery, "unidiomatic `let mut` declaration followed by initialization in `if`" } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0c4daeb731f..b241ac5559c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1266,7 +1266,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), - LintId::of(&let_if_seq::USELESS_LET_IF_SEQ), LintId::of(&let_underscore::LET_UNDERSCORE_LOCK), LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES), LintId::of(&lifetimes::NEEDLESS_LIFETIMES), @@ -1476,7 +1475,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&inherent_to_string::INHERENT_TO_STRING), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), - LintId::of(&let_if_seq::USELESS_LET_IF_SEQ), LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING), LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::FOR_KV_MAP), @@ -1728,6 +1726,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS), LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS), LintId::of(&future_not_send::FUTURE_NOT_SEND), + LintId::of(&let_if_seq::USELESS_LET_IF_SEQ), LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN), LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL), LintId::of(&mutex_atomic::MUTEX_INTEGER), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index e1a6d4bdd31..e1c68b58b86 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2469,7 +2469,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ }, Lint { name: "useless_let_if_seq", - group: "style", + group: "nursery", desc: "unidiomatic `let mut` declaration followed by initialization in `if`", deprecation: None, module: "let_if_seq", From 94e4b5ec316993200d75276b4e7c16a059bf3a57 Mon Sep 17 00:00:00 2001 From: Vardan Margaryan <v.t.margaryan@gmail.com> Date: Sun, 10 May 2020 00:08:41 +0300 Subject: [PATCH 062/526] Add the redundant_wildcard_enum_match lint --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/matches.rs | 48 +++++++++++++++++++ src/lintlist/mod.rs | 7 +++ .../match_wildcard_for_single_variants.fixed | 18 +++++++ .../ui/match_wildcard_for_single_variants.rs | 18 +++++++ .../match_wildcard_for_single_variants.stderr | 10 ++++ 7 files changed, 104 insertions(+) create mode 100644 tests/ui/match_wildcard_for_single_variants.fixed create mode 100644 tests/ui/match_wildcard_for_single_variants.rs create mode 100644 tests/ui/match_wildcard_for_single_variants.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index b25ef049356..d6298fec65a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1439,6 +1439,7 @@ Released 2018-09-13 [`match_same_arms`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_same_arms [`match_single_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_single_binding [`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm +[`match_wildcard_for_single_variants`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants [`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter [`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum [`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0c4daeb731f..41046c18ed2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -641,6 +641,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &matches::MATCH_OVERLAPPING_ARM, &matches::MATCH_REF_PATS, &matches::MATCH_SINGLE_BINDING, + &matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS, &matches::MATCH_WILD_ERR_ARM, &matches::REST_PAT_IN_FULLY_BOUND_STRUCTS, &matches::SINGLE_MATCH, @@ -1147,6 +1148,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(¯o_use::MACRO_USE_IMPORTS), LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), LintId::of(&matches::MATCH_BOOL), + LintId::of(&matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS), LintId::of(&matches::SINGLE_MATCH_ELSE), LintId::of(&methods::FILTER_MAP), LintId::of(&methods::FILTER_MAP_NEXT), diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 8f86535ef1e..42a6c416619 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -229,6 +229,40 @@ declare_clippy_lint! { "a wildcard enum match arm using `_`" } +declare_clippy_lint! { + /// **What it does:** Checks for wildcard enum matches for a single variant. + /// + /// **Why is this bad?** New enum variants added by library updates can be missed. + /// + /// **Known problems:** Suggested replacements may not use correct path to enum + /// if it's not present in the current scope. + /// + /// **Example:** + /// + /// ```rust + /// # enum Foo { A, B, C } + /// # let x = Foo::B; + /// match x { + /// Foo::A => {}, + /// Foo::B => {}, + /// _ => {}, + /// } + /// ``` + /// Use instead: + /// ```rust + /// # enum Foo { A, B, C } + /// # let x = Foo::B; + /// match x { + /// Foo::A => {}, + /// Foo::B => {}, + /// Foo::C => {}, + /// } + /// ``` + pub MATCH_WILDCARD_FOR_SINGLE_VARIANTS, + pedantic, + "a wildcard enum match for a single variant" +} + declare_clippy_lint! { /// **What it does:** Checks for wildcard pattern used with others patterns in same match arm. /// @@ -356,6 +390,7 @@ impl_lint_pass!(Matches => [ MATCH_WILD_ERR_ARM, MATCH_AS_REF, WILDCARD_ENUM_MATCH_ARM, + MATCH_WILDCARD_FOR_SINGLE_VARIANTS, WILDCARD_IN_OR_PATTERNS, MATCH_SINGLE_BINDING, INFALLIBLE_DESTRUCTURING_MATCH, @@ -766,6 +801,19 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_ } } + if suggestion.len() == 1 { + // No need to check for non-exhaustive enum as in that case len would be greater than 1 + span_lint_and_sugg( + cx, + MATCH_WILDCARD_FOR_SINGLE_VARIANTS, + wildcard_span, + message, + "try this", + suggestion[0].clone(), + Applicability::MachineApplicable, + ) + }; + span_lint_and_sugg( cx, WILDCARD_ENUM_MATCH_ARM, diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index e1a6d4bdd31..250a7c09f78 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1200,6 +1200,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "matches", }, + Lint { + name: "match_wildcard_for_single_variants", + group: "pedantic", + desc: "a wildcard enum match for a single variant", + deprecation: None, + module: "matches", + }, Lint { name: "maybe_infinite_iter", group: "pedantic", diff --git a/tests/ui/match_wildcard_for_single_variants.fixed b/tests/ui/match_wildcard_for_single_variants.fixed new file mode 100644 index 00000000000..5f1a559f591 --- /dev/null +++ b/tests/ui/match_wildcard_for_single_variants.fixed @@ -0,0 +1,18 @@ +// run-rustfix + +#![warn(clippy::match_wildcard_for_single_variants)] +#![allow(dead_code)] + +enum Foo { + A, + B, + C, +} + +fn main() { + match Foo::A { + Foo::A => {}, + Foo::B => {}, + Foo::C => {}, + } +} diff --git a/tests/ui/match_wildcard_for_single_variants.rs b/tests/ui/match_wildcard_for_single_variants.rs new file mode 100644 index 00000000000..1159f9e722d --- /dev/null +++ b/tests/ui/match_wildcard_for_single_variants.rs @@ -0,0 +1,18 @@ +// run-rustfix + +#![warn(clippy::match_wildcard_for_single_variants)] +#![allow(dead_code)] + +enum Foo { + A, + B, + C, +} + +fn main() { + match Foo::A { + Foo::A => {}, + Foo::B => {}, + _ => {}, + } +} diff --git a/tests/ui/match_wildcard_for_single_variants.stderr b/tests/ui/match_wildcard_for_single_variants.stderr new file mode 100644 index 00000000000..128dd4808bf --- /dev/null +++ b/tests/ui/match_wildcard_for_single_variants.stderr @@ -0,0 +1,10 @@ +error: wildcard match will miss any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:16:9 + | +LL | _ => {}, + | ^ help: try this: `Foo::C` + | + = note: `-D clippy::match-wildcard-for-single-variants` implied by `-D warnings` + +error: aborting due to previous error + From 0ad9f7d651b52de4be6384c9b6dc893b389fd557 Mon Sep 17 00:00:00 2001 From: Vardan Margaryan <v.t.margaryan@gmail.com> Date: Sun, 10 May 2020 18:33:12 +0300 Subject: [PATCH 063/526] Fix trivial cases of new match_wildcard_for_single_variants lint --- clippy_lints/src/float_literal.rs | 2 +- clippy_lints/src/misc_early.rs | 2 +- clippy_lints/src/missing_const_for_fn.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/trivially_copy_pass_by_ref.rs | 2 +- tests/compile-test.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 3a52b1d3fc2..4c604cd0107 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -77,7 +77,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatLiteral { let type_suffix = match lit_float_ty { LitFloatType::Suffixed(FloatTy::F32) => Some("f32"), LitFloatType::Suffixed(FloatTy::F64) => Some("f64"), - _ => None + LitFloatType::Unsuffixed => None }; let (is_whole, mut float_str) = match fty { FloatTy::F32 => { diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 62ee051624b..552222eba2e 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -379,7 +379,7 @@ impl EarlyLintPass for MiscEarlyLints { let left_binding = match left { BindingMode::ByRef(Mutability::Mut) => "ref mut ", BindingMode::ByRef(Mutability::Not) => "ref ", - _ => "", + BindingMode::ByValue(..) => "", }; if let PatKind::Wild = right.kind { diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 4301157e164..9cfc8d19134 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { return; } }, - _ => return, + FnKind::Closure(..) => return, } let mir = cx.tcx.optimized_mir(def_id); diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index a21818701da..c099c553333 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } }, FnKind::Method(..) => (), - _ => return, + FnKind::Closure(..) => return, } // Exclude non-inherent impls diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 2c101220c5d..8e0cb94317a 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -161,7 +161,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { } }, FnKind::Method(..) => (), - _ => return, + FnKind::Closure(..) => return, } // Exclude non-inherent impls diff --git a/tests/compile-test.rs b/tests/compile-test.rs index de2cf6d7873..a3df9d5ccbd 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -44,7 +44,7 @@ fn third_party_crates() -> String { for entry in fs::read_dir(dep_dir).unwrap() { let path = match entry { Ok(entry) => entry.path(), - _ => continue, + Err(_) => continue, }; if let Some(name) = path.file_name().and_then(OsStr::to_str) { for dep in CRATES { From 494830797744c09d6de3b2b2452ab185d2204005 Mon Sep 17 00:00:00 2001 From: Vardan Margaryan <v.t.margaryan@gmail.com> Date: Sun, 10 May 2020 18:34:29 +0300 Subject: [PATCH 064/526] Fix cases of match_wildcard_for_single_variants lint when it is spanned on Option --- clippy_lints/src/consts.rs | 9 +++++---- clippy_lints/src/escape.rs | 4 ++-- clippy_lints/src/floating_point_arithmetic.rs | 2 +- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/modulo_arithmetic.rs | 1 + clippy_lints/src/utils/mod.rs | 2 ++ 7 files changed, 13 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 81ddc8c0067..efb424bcb7b 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -139,6 +139,7 @@ impl Constant { .find(|r| r.map_or(true, |o| o != Ordering::Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))), (&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => { + #[allow(clippy::match_wildcard_for_single_variants)] match Self::partial_cmp(tcx, cmp_type, lv, rv) { Some(Equal) => Some(ls.cmp(rs)), x => x, @@ -354,14 +355,14 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { (Some(Constant::Vec(vec)), Some(Constant::Int(index))) => match vec.get(index as usize) { Some(Constant::F32(x)) => Some(Constant::F32(*x)), Some(Constant::F64(x)) => Some(Constant::F64(*x)), - _ => None, + Some(_) | None => None, }, (Some(Constant::Vec(vec)), _) => { if !vec.is_empty() && vec.iter().all(|x| *x == vec[0]) { match vec.get(0) { Some(Constant::F32(x)) => Some(Constant::F32(*x)), Some(Constant::F64(x)) => Some(Constant::F64(*x)), - _ => None, + Some(_) | None => None, } } else { None @@ -532,7 +533,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> { }) .collect::<Option<Vec<Constant>>>() .map(Constant::Vec), - _ => None, + Some(_) | None => None, }, ty::Float(FloatTy::F64) => match miri_to_const(len) { Some(Constant::Int(len)) => alloc @@ -546,7 +547,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> { }) .collect::<Option<Vec<Constant>>>() .map(Constant::Vec), - _ => None, + Some(_) | None => None, }, // FIXME: implement other array type conversions. _ => None, diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 1ec60a0e6e6..615afee33ef 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -95,12 +95,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal { fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool { match map.find(id) { Some(Node::Binding(_)) => (), - _ => return false, + Some(_) | None => return false, } match map.find(map.get_parent_node(id)) { Some(Node::Param(_)) => true, - _ => false, + Some(_) | None => false, } } diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 86317fb8bd5..8c61b2f8664 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -410,7 +410,7 @@ fn is_zero(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { Some(Constant::Int(i)) => i == 0, Some(Constant::F32(f)) => f == 0.0, Some(Constant::F64(f)) => f == 0.0, - _ => false, + Some(_) | None => false, } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0bc6b70855b..39908bff5ed 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2154,7 +2154,7 @@ fn is_loop_nested(cx: &LateContext<'_, '_>, loop_expr: &Expr<'_>, iter_expr: &Ex } }, Some(Node::Stmt(_)) => (), - _ => { + Some(_) | None => { return false; }, } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index e1d524c2231..38c2645d36e 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -509,7 +509,7 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> boo Constant::F64(f) => *f == 0.0 || (*f).is_infinite(), _ => false, }), - _ => false, + Some(_) | None => false, } } diff --git a/clippy_lints/src/modulo_arithmetic.rs b/clippy_lints/src/modulo_arithmetic.rs index 4ca90455bc4..3bb3eb15d9c 100644 --- a/clippy_lints/src/modulo_arithmetic.rs +++ b/clippy_lints/src/modulo_arithmetic.rs @@ -37,6 +37,7 @@ struct OperandInfo { } fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<OperandInfo> { + #[allow(clippy::match_wildcard_for_single_variants)] match constant(cx, cx.tables, operand) { Some((Constant::Int(v), _)) => match cx.tables.expr_ty(expr).kind { ty::Int(ity) => { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 3b8ef18bfab..7bc8be492e8 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -370,6 +370,7 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'_, 'tcx>, hir_id: HirId) -> O /// Checks whether this type implements `Drop`. pub fn has_drop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { + #[allow(clippy::match_wildcard_for_single_variants)] match ty.ty_adt_def() { Some(def) => def.has_dtor(cx.tcx), _ => false, @@ -444,6 +445,7 @@ pub fn is_entrypoint_fn(cx: &LateContext<'_, '_>, def_id: DefId) -> bool { /// Gets the name of the item the expression is in, if available. pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<Name> { let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id); + #[allow(clippy::match_wildcard_for_single_variants)] match cx.tcx.hir().find(parent_id) { Some( Node::Item(Item { ident, .. }) From 749619cfe34be1ee591f3af748fbdd4d2f54d3f0 Mon Sep 17 00:00:00 2001 From: Vardan Margaryan <v.t.margaryan@gmail.com> Date: Thu, 14 May 2020 22:40:33 +0300 Subject: [PATCH 065/526] Apply suggestions from PR review --- clippy_lints/src/matches.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 42a6c416619..444f5bb0db6 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -810,7 +810,7 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_ message, "try this", suggestion[0].clone(), - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ) }; @@ -821,7 +821,7 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_ message, "try this", suggestion.join(" | "), - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ) } } From 1c59cd5f2110ff90a256f0948f05716403e84b85 Mon Sep 17 00:00:00 2001 From: Vardan Margaryan <v.t.margaryan@gmail.com> Date: Thu, 14 May 2020 22:41:05 +0300 Subject: [PATCH 066/526] Fix example code of wildcard_enum_match_arm lint --- clippy_lints/src/matches.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 444f5bb0db6..6fdb4cf9cd7 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -220,7 +220,7 @@ declare_clippy_lint! { /// # enum Foo { A(usize), B(usize) } /// # let x = Foo::B(1); /// match x { - /// A => {}, + /// Foo::A(_) => {}, /// _ => {}, /// } /// ``` From 93386563f66823ac7d10641c007b0bbc23ab09e6 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sun, 3 May 2020 19:58:27 +0200 Subject: [PATCH 067/526] Rename lint `map_unwrap` to `map_unwrap_or` and register lints as renamed --- CHANGELOG.md | 3 +- clippy_lints/src/lib.rs | 15 ++++++++-- clippy_lints/src/methods/mod.rs | 8 +++--- .../src/methods/option_map_unwrap_or.rs | 4 +-- src/lintlist/mod.rs | 9 +----- tests/ui/{map_unwrap.rs => map_unwrap_or.rs} | 2 +- ...map_unwrap.stderr => map_unwrap_or.stderr} | 28 +++++++++---------- 7 files changed, 36 insertions(+), 33 deletions(-) rename tests/ui/{map_unwrap.rs => map_unwrap_or.rs} (98%) rename tests/ui/{map_unwrap.stderr => map_unwrap_or.stderr} (90%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f9486e0972..77272f4f78b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1430,7 +1430,7 @@ Released 2018-09-13 [`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone [`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry [`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten -[`map_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap +[`map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or [`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref [`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool [`match_on_vec_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_on_vec_items @@ -1538,7 +1538,6 @@ Released 2018-09-13 [`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs [`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_or_into_option [`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn -[`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used [`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges [`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8de94d19d31..ff67ccae794 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -673,7 +673,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::ITER_SKIP_NEXT, &methods::MANUAL_SATURATING_ARITHMETIC, &methods::MAP_FLATTEN, - &methods::MAP_UNWRAP, + &methods::MAP_UNWRAP_OR, &methods::NEW_RET_NO_SELF, &methods::OK_EXPECT, &methods::OPTION_AND_THEN_SOME, @@ -1145,7 +1145,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::FIND_MAP), LintId::of(&methods::INEFFICIENT_TO_STRING), LintId::of(&methods::MAP_FLATTEN), - LintId::of(&methods::MAP_UNWRAP), + LintId::of(&methods::MAP_UNWRAP_OR), LintId::of(&misc::USED_UNDERSCORE_BINDING), LintId::of(&misc_early::UNSEPARATED_LITERAL_SUFFIX), LintId::of(&mut_mut::MUT_MUT), @@ -1785,6 +1785,17 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) { ls.register_renamed("clippy::new_without_default_derive", "clippy::new_without_default"); ls.register_renamed("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"); ls.register_renamed("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"); + ls.register_renamed("clippy::block_in_if_condition_expr", "clippy::block_in_if_condition"); + ls.register_renamed("clippy::block_in_if_condition_stmt", "clippy::block_in_if_condition"); + ls.register_renamed("clippy::option_map_unwrap_or", "clippy::map_unwrap_or"); + ls.register_renamed("clippy::option_map_unwrap_or_else", "clippy::map_unwrap_or"); + ls.register_renamed("clippy::result_map_unwrap_or_else", "clippy::map_unwrap_or"); + ls.register_renamed("clippy::option_unwrap_used", "clippy::unwrap_used"); + ls.register_renamed("clippy::result_unwrap_used", "clippy::unwrap_used"); + ls.register_renamed("clippy::option_expect_used", "clippy::expect_used"); + ls.register_renamed("clippy::result_expect_used", "clippy::expect_used"); + ls.register_renamed("clippy::for_loop_over_option", "clippy::for_loop_over_fallible"); + ls.register_renamed("clippy::for_loop_over_result", "clippy::for_loop_over_fallible"); } // only exists to let the dogfood integration test works. diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2e75de019b6..e6094edc5d7 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -255,7 +255,7 @@ declare_clippy_lint! { /// // Good /// x.map_or_else(some_function, |a| a + 1); /// ``` - pub MAP_UNWRAP, + pub MAP_UNWRAP_OR, pedantic, "using `.map(f).unwrap_or(a)` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)` or `map_or_else(a, f)`" } @@ -1240,7 +1240,7 @@ declare_lint_pass!(Methods => [ WRONG_SELF_CONVENTION, WRONG_PUB_SELF_CONVENTION, OK_EXPECT, - MAP_UNWRAP, + MAP_UNWRAP_OR, RESULT_MAP_OR_INTO_OPTION, OPTION_MAP_OR_NONE, OPTION_AND_THEN_SOME, @@ -2512,7 +2512,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( if same_span && !multiline { span_lint_and_note( cx, - MAP_UNWRAP, + MAP_UNWRAP_OR, expr.span, msg, None, @@ -2522,7 +2522,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( ), ); } else if same_span && multiline { - span_lint(cx, MAP_UNWRAP, expr.span, msg); + span_lint(cx, MAP_UNWRAP_OR, expr.span, msg); }; } } diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index fcaa9b47e64..20c60ef3318 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -9,7 +9,7 @@ use rustc_middle::hir::map::Map; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; -use super::MAP_UNWRAP; +use super::MAP_UNWRAP_OR; /// lint use of `map().unwrap_or()` for `Option`s pub(super) fn lint<'a, 'tcx>( @@ -66,7 +66,7 @@ pub(super) fn lint<'a, 'tcx>( arg, suggest ); - span_lint_and_then(cx, MAP_UNWRAP, expr.span, msg, |diag| { + span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| { let map_arg_span = map_args[1].span; let mut suggestion = vec![ diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 0ea0f55a381..e90b9c15747 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1138,7 +1138,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ module: "methods", }, Lint { - name: "map_unwrap", + name: "map_unwrap_or", group: "pedantic", desc: "using `.map(f).unwrap_or(a)` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)` or `map_or_else(a, f)`", deprecation: None, @@ -1872,13 +1872,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "map_unit_fn", }, - Lint { - name: "result_unwrap_used", - group: "restriction", - desc: "using `Result.unwrap()`, which might be better handled", - deprecation: None, - module: "methods", - }, Lint { name: "reversed_empty_ranges", group: "correctness", diff --git a/tests/ui/map_unwrap.rs b/tests/ui/map_unwrap_or.rs similarity index 98% rename from tests/ui/map_unwrap.rs rename to tests/ui/map_unwrap_or.rs index 53e50368231..585944032e7 100644 --- a/tests/ui/map_unwrap.rs +++ b/tests/ui/map_unwrap_or.rs @@ -1,7 +1,7 @@ // FIXME: Add "run-rustfix" once it's supported for multipart suggestions // aux-build:option_helpers.rs -#![warn(clippy::map_unwrap)] +#![warn(clippy::map_unwrap_or)] #[macro_use] extern crate option_helpers; diff --git a/tests/ui/map_unwrap.stderr b/tests/ui/map_unwrap_or.stderr similarity index 90% rename from tests/ui/map_unwrap.stderr rename to tests/ui/map_unwrap_or.stderr index 2610923275d..b62080a073f 100644 --- a/tests/ui/map_unwrap.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -1,5 +1,5 @@ error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/map_unwrap.rs:17:13 + --> $DIR/map_unwrap_or.rs:17:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -7,14 +7,14 @@ LL | | // Should lint even though this call is on a separate line. LL | | .unwrap_or(0); | |_____________________^ | - = note: `-D clippy::map-unwrap` implied by `-D warnings` + = note: `-D clippy::map-unwrap-or` implied by `-D warnings` help: use `map_or(a, f)` instead | LL | let _ = opt.map_or(0, |x| x + 1); | ^^^^^^ ^^ -- error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/map_unwrap.rs:21:13 + --> $DIR/map_unwrap_or.rs:21:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -32,7 +32,7 @@ LL | ); | error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/map_unwrap.rs:25:13 + --> $DIR/map_unwrap_or.rs:25:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -49,7 +49,7 @@ LL | }, |x| x + 1); | error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/map_unwrap.rs:30:13 + --> $DIR/map_unwrap_or.rs:30:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | let _ = opt.and_then(|x| Some(x + 1)); | ^^^^^^^^ -- error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/map_unwrap.rs:32:13 + --> $DIR/map_unwrap_or.rs:32:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -78,7 +78,7 @@ LL | ); | error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/map_unwrap.rs:36:13 + --> $DIR/map_unwrap_or.rs:36:13 | LL | let _ = opt | _____________^ @@ -92,7 +92,7 @@ LL | .and_then(|x| Some(x + 1)); | ^^^^^^^^ -- error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/map_unwrap.rs:47:13 + --> $DIR/map_unwrap_or.rs:47:13 | LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | let _ = Some("prefix").map_or(id, |p| format!("{}.", p)); | ^^^^^^ ^^^ -- error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/map_unwrap.rs:51:13 + --> $DIR/map_unwrap_or.rs:51:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -114,7 +114,7 @@ LL | | .unwrap_or_else(|| 0); = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/map_unwrap.rs:55:13 + --> $DIR/map_unwrap_or.rs:55:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -124,7 +124,7 @@ LL | | ).unwrap_or_else(|| 0); | |__________________________^ error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/map_unwrap.rs:59:13 + --> $DIR/map_unwrap_or.rs:59:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -134,7 +134,7 @@ LL | | ); | |_________^ error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead - --> $DIR/map_unwrap.rs:88:13 + --> $DIR/map_unwrap_or.rs:88:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even t = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead - --> $DIR/map_unwrap.rs:90:13 + --> $DIR/map_unwrap_or.rs:90:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -150,7 +150,7 @@ LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead - --> $DIR/map_unwrap.rs:91:13 + --> $DIR/map_unwrap_or.rs:91:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From ab87f87ba03518da23ca510249aa3f5908a42368 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Fri, 15 May 2020 18:20:07 +0200 Subject: [PATCH 068/526] Fix CHANGELOG.md and lint names plural --- CHANGELOG.md | 22 ++++++++--------- ...ondition.rs => blocks_in_if_conditions.rs} | 12 +++++----- clippy_lints/src/lib.rs | 24 +++++++++---------- clippy_lints/src/loops.rs | 8 +++---- src/lintlist/mod.rs | 6 ++--- ...on.fixed => blocks_in_if_conditions.fixed} | 2 +- ...ondition.rs => blocks_in_if_conditions.rs} | 2 +- ....stderr => blocks_in_if_conditions.stderr} | 8 +++---- ....rs => blocks_in_if_conditions_closure.rs} | 2 +- ...=> blocks_in_if_conditions_closure.stderr} | 6 ++--- ...allible.rs => for_loops_over_fallibles.rs} | 4 ++-- ...stderr => for_loops_over_fallibles.stderr} | 18 +++++++------- 12 files changed, 57 insertions(+), 57 deletions(-) rename clippy_lints/src/{block_in_if_condition.rs => blocks_in_if_conditions.rs} (93%) rename tests/ui/{block_in_if_condition.fixed => blocks_in_if_conditions.fixed} (96%) rename tests/ui/{block_in_if_condition.rs => blocks_in_if_conditions.rs} (96%) rename tests/ui/{block_in_if_condition.stderr => blocks_in_if_conditions.stderr} (77%) rename tests/ui/{block_in_if_condition_closure.rs => blocks_in_if_conditions_closure.rs} (95%) rename tests/ui/{block_in_if_condition_closure.stderr => blocks_in_if_conditions_closure.stderr} (78%) rename tests/ui/{for_loop_over_fallible.rs => for_loops_over_fallibles.rs} (93%) rename tests/ui/{for_loop_over_fallible.stderr => for_loops_over_fallibles.stderr} (84%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77272f4f78b..d05819a973a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -198,7 +198,7 @@ Released 2020-03-12 ### Suggestion Improvements -* [`option_map_unwrap_or`] [#4634](https://github.com/rust-lang/rust-clippy/pull/4634) +* `option_map_unwrap_or` [#4634](https://github.com/rust-lang/rust-clippy/pull/4634) * [`wildcard_enum_match_arm`] [#4934](https://github.com/rust-lang/rust-clippy/pull/4934) * [`cognitive_complexity`] [#4935](https://github.com/rust-lang/rust-clippy/pull/4935) * [`decimal_literal_representation`] [#4956](https://github.com/rust-lang/rust-clippy/pull/4956) @@ -282,8 +282,8 @@ Released 2019-12-19 * [`panic`] [#4657](https://github.com/rust-lang/rust-clippy/pull/4657) * [`unreachable`] [#4657](https://github.com/rust-lang/rust-clippy/pull/4657) * [`todo`] [#4657](https://github.com/rust-lang/rust-clippy/pull/4657) - * [`option_expect_used`] [#4657](https://github.com/rust-lang/rust-clippy/pull/4657) - * [`result_expect_used`] [#4657](https://github.com/rust-lang/rust-clippy/pull/4657) + * `option_expect_used` [#4657](https://github.com/rust-lang/rust-clippy/pull/4657) + * `result_expect_used` [#4657](https://github.com/rust-lang/rust-clippy/pull/4657) * Move `redundant_clone` to perf group [#4509](https://github.com/rust-lang/rust-clippy/pull/4509) * Move `manual_mul_add` to nursery group [#4736](https://github.com/rust-lang/rust-clippy/pull/4736) * Expand `unit_cmp` to also work with `assert_eq!`, `debug_assert_eq!`, `assert_ne!` and `debug_assert_ne!` [#4613](https://github.com/rust-lang/rust-clippy/pull/4613) @@ -395,7 +395,7 @@ Released 2019-08-15 * Fix false positive in [`useless_attribute`] [#4107](https://github.com/rust-lang/rust-clippy/pull/4107) * Fix incorrect suggestion for [`float_cmp`] [#4214](https://github.com/rust-lang/rust-clippy/pull/4214) * Add suggestions for [`print_with_newline`] and [`write_with_newline`] [#4136](https://github.com/rust-lang/rust-clippy/pull/4136) -* Improve suggestions for [`option_map_unwrap_or_else`] and [`result_map_unwrap_or_else`] [#4164](https://github.com/rust-lang/rust-clippy/pull/4164) +* Improve suggestions for `option_map_unwrap_or_else` and `result_map_unwrap_or_else` [#4164](https://github.com/rust-lang/rust-clippy/pull/4164) * Improve suggestions for [`non_ascii_literal`] [#4119](https://github.com/rust-lang/rust-clippy/pull/4119) * Improve diagnostics for [`let_and_return`] [#4137](https://github.com/rust-lang/rust-clippy/pull/4137) * Improve diagnostics for [`trivially_copy_pass_by_ref`] [#4071](https://github.com/rust-lang/rust-clippy/pull/4071) @@ -448,7 +448,7 @@ Released 2019-05-20 * Fix false positive in [`needless_range_loop`] pertaining to structs without a `.iter()` * Fix false positive in [`bool_comparison`] pertaining to non-bool types * Fix false positive in [`redundant_closure`] pertaining to differences in borrows -* Fix false positive in [`option_map_unwrap_or`] on non-copy types +* Fix false positive in `option_map_unwrap_or` on non-copy types * Fix false positives in [`missing_const_for_fn`] pertaining to macros and trait method impls * Fix false positive in [`needless_pass_by_value`] pertaining to procedural macros * Fix false positive in [`needless_continue`] pertaining to loop labels @@ -794,7 +794,7 @@ Released 2018-09-13 ## 0.0.169 * Rustup to *rustc 1.23.0-nightly (3b82e4c74 2017-11-05)* -* New lints: [`just_underscores_and_digits`], [`result_map_unwrap_or_else`], [`transmute_bytes_to_str`] +* New lints: [`just_underscores_and_digits`], `result_map_unwrap_or_else`, [`transmute_bytes_to_str`] ## 0.0.168 * Rustup to *rustc 1.23.0-nightly (f0fe716db 2017-10-30)* @@ -1068,7 +1068,7 @@ Released 2018-09-13 ## 0.0.93 — 2016-10-03 * Rustup to *rustc 1.14.0-nightly (144af3e97 2016-10-02)* -* [`option_map_unwrap_or`] and [`option_map_unwrap_or_else`] are now +* `option_map_unwrap_or` and `option_map_unwrap_or_else` are now allowed by default. * New lint: [`explicit_into_iter_loop`] @@ -1087,8 +1087,8 @@ Released 2018-09-13 ## 0.0.88 — 2016-09-04 * Rustup to *rustc 1.13.0-nightly (70598e04f 2016-09-03)* * The following lints are not new but were only usable through the `clippy` - lint groups: [`filter_next`], [`for_loop_over_option`], - [`for_loop_over_result`] and [`match_overlapping_arm`]. You should now be + lint groups: [`filter_next`], `for_loop_over_option`, + `for_loop_over_result` and [`match_overlapping_arm`]. You should now be able to `#[allow/deny]` them individually and they are available directly through `cargo clippy`. @@ -1274,7 +1274,7 @@ Released 2018-09-13 [`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock [`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask [`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name -[`block_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition +[`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_if_conditions [`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison [`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const [`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box @@ -1361,7 +1361,7 @@ Released 2018-09-13 [`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast [`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation [`for_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_kv_map -[`for_loop_over_fallible`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_fallible +[`for_loops_over_fallibles`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loops_over_fallibles [`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy [`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref [`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/blocks_in_if_conditions.rs similarity index 93% rename from clippy_lints/src/block_in_if_condition.rs rename to clippy_lints/src/blocks_in_if_conditions.rs index 8a5e595749f..8fa9b05ca32 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/blocks_in_if_conditions.rs @@ -36,12 +36,12 @@ declare_clippy_lint! { /// let res = { let x = somefunc(); x }; /// if res { /* ... */ } /// ``` - pub BLOCK_IN_IF_CONDITION, + pub BLOCKS_IN_IF_CONDITIONS, style, "useless or complex blocks that can be eliminated in conditions" } -declare_lint_pass!(BlockInIfCondition => [BLOCK_IN_IF_CONDITION]); +declare_lint_pass!(BlocksInIfConditions => [BLOCKS_IN_IF_CONDITIONS]); struct ExVisitor<'a, 'tcx> { found_block: Option<&'tcx Expr<'tcx>>, @@ -71,7 +71,7 @@ const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression conditio const COMPLEX_BLOCK_MESSAGE: &str = "in an `if` condition, avoid complex blocks or closures with blocks; \ instead, move the block or closure higher and bind it with a `let`"; -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlocksInIfConditions { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { if in_external_macro(cx.sess(), expr.span) { return; @@ -89,7 +89,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, - BLOCK_IN_IF_CONDITION, + BLOCKS_IN_IF_CONDITIONS, cond.span, BRACED_EXPR_MESSAGE, "try", @@ -115,7 +115,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, - BLOCK_IN_IF_CONDITION, + BLOCKS_IN_IF_CONDITIONS, expr.span.with_hi(cond.span.hi()), COMPLEX_BLOCK_MESSAGE, "try", @@ -137,7 +137,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { let mut visitor = ExVisitor { found_block: None, cx }; walk_expr(&mut visitor, cond); if let Some(block) = visitor.found_block { - span_lint(cx, BLOCK_IN_IF_CONDITION, block.span, COMPLEX_BLOCK_MESSAGE); + span_lint(cx, BLOCKS_IN_IF_CONDITIONS, block.span, COMPLEX_BLOCK_MESSAGE); } } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ff67ccae794..eba4ab5056b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -180,7 +180,7 @@ mod attrs; mod await_holding_lock; mod bit_mask; mod blacklisted_name; -mod block_in_if_condition; +mod blocks_in_if_conditions; mod booleans; mod bytecount; mod cargo_common_metadata; @@ -507,7 +507,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &bit_mask::INEFFECTIVE_BIT_MASK, &bit_mask::VERBOSE_BIT_MASK, &blacklisted_name::BLACKLISTED_NAME, - &block_in_if_condition::BLOCK_IN_IF_CONDITION, + &blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS, &booleans::LOGIC_BUG, &booleans::NONMINIMAL_BOOL, &bytecount::NAIVE_BYTECOUNT, @@ -615,7 +615,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::EXPLICIT_INTO_ITER_LOOP, &loops::EXPLICIT_ITER_LOOP, &loops::FOR_KV_MAP, - &loops::FOR_LOOP_OVER_FALLIBLE, + &loops::FOR_LOOPS_OVER_FALLIBLES, &loops::ITER_NEXT_LOOP, &loops::MANUAL_MEMCPY, &loops::MUT_RANGE_BOUND, @@ -894,7 +894,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box mut_reference::UnnecessaryMutPassed); store.register_late_pass(|| box len_zero::LenZero); store.register_late_pass(|| box attrs::Attributes); - store.register_late_pass(|| box block_in_if_condition::BlockInIfCondition); + store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions); store.register_late_pass(|| box unicode::Unicode); store.register_late_pass(|| box strings::StringAdd); store.register_late_pass(|| box implicit_return::ImplicitReturn); @@ -1199,7 +1199,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK), LintId::of(&bit_mask::VERBOSE_BIT_MASK), LintId::of(&blacklisted_name::BLACKLISTED_NAME), - LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION), + LintId::of(&blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), LintId::of(&booleans::LOGIC_BUG), LintId::of(&booleans::NONMINIMAL_BOOL), LintId::of(&bytecount::NAIVE_BYTECOUNT), @@ -1264,7 +1264,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::EXPLICIT_COUNTER_LOOP), LintId::of(&loops::FOR_KV_MAP), - LintId::of(&loops::FOR_LOOP_OVER_FALLIBLE), + LintId::of(&loops::FOR_LOOPS_OVER_FALLIBLES), LintId::of(&loops::ITER_NEXT_LOOP), LintId::of(&loops::MANUAL_MEMCPY), LintId::of(&loops::MUT_RANGE_BOUND), @@ -1444,7 +1444,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS), LintId::of(&bit_mask::VERBOSE_BIT_MASK), LintId::of(&blacklisted_name::BLACKLISTED_NAME), - LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION), + LintId::of(&blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), LintId::of(&collapsible_if::COLLAPSIBLE_IF), LintId::of(&comparison_chain::COMPARISON_CHAIN), LintId::of(&doc::MISSING_SAFETY_DOC), @@ -1639,7 +1639,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY), LintId::of(&let_underscore::LET_UNDERSCORE_LOCK), LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES), - LintId::of(&loops::FOR_LOOP_OVER_FALLIBLE), + LintId::of(&loops::FOR_LOOPS_OVER_FALLIBLES), LintId::of(&loops::ITER_NEXT_LOOP), LintId::of(&loops::NEVER_LOOP), LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), @@ -1785,8 +1785,8 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) { ls.register_renamed("clippy::new_without_default_derive", "clippy::new_without_default"); ls.register_renamed("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"); ls.register_renamed("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"); - ls.register_renamed("clippy::block_in_if_condition_expr", "clippy::block_in_if_condition"); - ls.register_renamed("clippy::block_in_if_condition_stmt", "clippy::block_in_if_condition"); + ls.register_renamed("clippy::block_in_if_condition_expr", "clippy::blocks_in_if_conditions"); + ls.register_renamed("clippy::block_in_if_condition_stmt", "clippy::blocks_in_if_conditions"); ls.register_renamed("clippy::option_map_unwrap_or", "clippy::map_unwrap_or"); ls.register_renamed("clippy::option_map_unwrap_or_else", "clippy::map_unwrap_or"); ls.register_renamed("clippy::result_map_unwrap_or_else", "clippy::map_unwrap_or"); @@ -1794,8 +1794,8 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) { ls.register_renamed("clippy::result_unwrap_used", "clippy::unwrap_used"); ls.register_renamed("clippy::option_expect_used", "clippy::expect_used"); ls.register_renamed("clippy::result_expect_used", "clippy::expect_used"); - ls.register_renamed("clippy::for_loop_over_option", "clippy::for_loop_over_fallible"); - ls.register_renamed("clippy::for_loop_over_result", "clippy::for_loop_over_fallible"); + ls.register_renamed("clippy::for_loop_over_option", "clippy::for_loops_over_fallibles"); + ls.register_renamed("clippy::for_loop_over_result", "clippy::for_loops_over_fallibles"); } // only exists to let the dogfood integration test works. diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index da6793a69d6..9c9d1a84003 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -205,7 +205,7 @@ declare_clippy_lint! { /// // .. /// } /// ``` - pub FOR_LOOP_OVER_FALLIBLE, + pub FOR_LOOPS_OVER_FALLIBLES, correctness, "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`" } @@ -426,7 +426,7 @@ declare_lint_pass!(Loops => [ EXPLICIT_ITER_LOOP, EXPLICIT_INTO_ITER_LOOP, ITER_NEXT_LOOP, - FOR_LOOP_OVER_FALLIBLE, + FOR_LOOPS_OVER_FALLIBLES, WHILE_LET_LOOP, NEEDLESS_COLLECT, EXPLICIT_COUNTER_LOOP, @@ -1290,7 +1290,7 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) { if is_type_diagnostic_item(cx, ty, sym!(option_type)) { span_lint_and_help( cx, - FOR_LOOP_OVER_FALLIBLE, + FOR_LOOPS_OVER_FALLIBLES, arg.span, &format!( "for loop over `{0}`, which is an `Option`. This is more readably written as an \ @@ -1307,7 +1307,7 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) { } else if is_type_diagnostic_item(cx, ty, sym!(result_type)) { span_lint_and_help( cx, - FOR_LOOP_OVER_FALLIBLE, + FOR_LOOPS_OVER_FALLIBLES, arg.span, &format!( "for loop over `{0}`, which is a `Result`. This is more readably written as an \ diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index e90b9c15747..feada261a4c 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -74,11 +74,11 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ module: "blacklisted_name", }, Lint { - name: "block_in_if_condition", + name: "blocks_in_if_conditions", group: "style", desc: "useless or complex blocks that can be eliminated in conditions", deprecation: None, - module: "block_in_if_condition", + module: "blocks_in_if_conditions", }, Lint { name: "bool_comparison", @@ -676,7 +676,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ module: "loops", }, Lint { - name: "for_loop_over_fallible", + name: "for_loops_over_fallibles", group: "correctness", desc: "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`", deprecation: None, diff --git a/tests/ui/block_in_if_condition.fixed b/tests/ui/blocks_in_if_conditions.fixed similarity index 96% rename from tests/ui/block_in_if_condition.fixed rename to tests/ui/blocks_in_if_conditions.fixed index ae01c6d3042..9040552cefc 100644 --- a/tests/ui/block_in_if_condition.fixed +++ b/tests/ui/blocks_in_if_conditions.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::block_in_if_condition)] +#![warn(clippy::blocks_in_if_conditions)] #![allow(unused, clippy::let_and_return)] #![warn(clippy::nonminimal_bool)] diff --git a/tests/ui/block_in_if_condition.rs b/tests/ui/blocks_in_if_conditions.rs similarity index 96% rename from tests/ui/block_in_if_condition.rs rename to tests/ui/blocks_in_if_conditions.rs index 88555dc47c2..2fe409b22d3 100644 --- a/tests/ui/block_in_if_condition.rs +++ b/tests/ui/blocks_in_if_conditions.rs @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::block_in_if_condition)] +#![warn(clippy::blocks_in_if_conditions)] #![allow(unused, clippy::let_and_return)] #![warn(clippy::nonminimal_bool)] diff --git a/tests/ui/block_in_if_condition.stderr b/tests/ui/blocks_in_if_conditions.stderr similarity index 77% rename from tests/ui/block_in_if_condition.stderr rename to tests/ui/blocks_in_if_conditions.stderr index 89e9ad26f49..9bdddc8e152 100644 --- a/tests/ui/block_in_if_condition.stderr +++ b/tests/ui/blocks_in_if_conditions.stderr @@ -1,5 +1,5 @@ error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/block_in_if_condition.rs:26:5 + --> $DIR/blocks_in_if_conditions.rs:26:5 | LL | / if { LL | | let x = 3; @@ -7,7 +7,7 @@ LL | | x == 3 LL | | } { | |_____^ | - = note: `-D clippy::block-in-if-condition` implied by `-D warnings` + = note: `-D clippy::blocks-in-if-conditions` implied by `-D warnings` help: try | LL | let res = { @@ -17,13 +17,13 @@ LL | }; if res { | error: omit braces around single expression condition - --> $DIR/block_in_if_condition.rs:37:8 + --> $DIR/blocks_in_if_conditions.rs:37:8 | LL | if { true } { | ^^^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/block_in_if_condition.rs:46:8 + --> $DIR/blocks_in_if_conditions.rs:46:8 | LL | if true && x == 3 { | ^^^^^^^^^^^^^^ help: try: `x == 3` diff --git a/tests/ui/block_in_if_condition_closure.rs b/tests/ui/blocks_in_if_conditions_closure.rs similarity index 95% rename from tests/ui/block_in_if_condition_closure.rs rename to tests/ui/blocks_in_if_conditions_closure.rs index 87b3fb94daf..acbabfa20d7 100644 --- a/tests/ui/block_in_if_condition_closure.rs +++ b/tests/ui/blocks_in_if_conditions_closure.rs @@ -1,4 +1,4 @@ -#![warn(clippy::block_in_if_condition)] +#![warn(clippy::blocks_in_if_conditions)] #![allow(unused, clippy::let_and_return)] fn predicate<F: FnOnce(T) -> bool, T>(pfn: F, val: T) -> bool { diff --git a/tests/ui/block_in_if_condition_closure.stderr b/tests/ui/blocks_in_if_conditions_closure.stderr similarity index 78% rename from tests/ui/block_in_if_condition_closure.stderr rename to tests/ui/blocks_in_if_conditions_closure.stderr index 3df25691c3c..941d604dd5f 100644 --- a/tests/ui/block_in_if_condition_closure.stderr +++ b/tests/ui/blocks_in_if_conditions_closure.stderr @@ -1,5 +1,5 @@ error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/block_in_if_condition_closure.rs:18:17 + --> $DIR/blocks_in_if_conditions_closure.rs:18:17 | LL | |x| { | _________________^ @@ -8,10 +8,10 @@ LL | | x == target LL | | }, | |_____________^ | - = note: `-D clippy::block-in-if-condition` implied by `-D warnings` + = note: `-D clippy::blocks-in-if-conditions` implied by `-D warnings` error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/block_in_if_condition_closure.rs:27:13 + --> $DIR/blocks_in_if_conditions_closure.rs:27:13 | LL | |x| { | _____________^ diff --git a/tests/ui/for_loop_over_fallible.rs b/tests/ui/for_loops_over_fallibles.rs similarity index 93% rename from tests/ui/for_loop_over_fallible.rs rename to tests/ui/for_loops_over_fallibles.rs index e52468cdd4b..1b9dde87cd5 100644 --- a/tests/ui/for_loop_over_fallible.rs +++ b/tests/ui/for_loops_over_fallibles.rs @@ -1,6 +1,6 @@ -#![warn(clippy::for_loop_over_fallible)] +#![warn(clippy::for_loops_over_fallibles)] -fn for_loop_over_fallible() { +fn for_loops_over_fallibles() { let option = Some(1); let result = option.ok_or("x not found"); let v = vec![0, 1, 2]; diff --git a/tests/ui/for_loop_over_fallible.stderr b/tests/ui/for_loops_over_fallibles.stderr similarity index 84% rename from tests/ui/for_loop_over_fallible.stderr rename to tests/ui/for_loops_over_fallibles.stderr index 4ce9a144ad8..bef228d4b93 100644 --- a/tests/ui/for_loop_over_fallible.stderr +++ b/tests/ui/for_loops_over_fallibles.stderr @@ -1,14 +1,14 @@ error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_fallible.rs:9:14 + --> $DIR/for_loops_over_fallibles.rs:9:14 | LL | for x in option { | ^^^^^^ | - = note: `-D clippy::for-loop-over-fallible` implied by `-D warnings` + = note: `-D clippy::for-loops-over-fallibles` implied by `-D warnings` = help: consider replacing `for x in option` with `if let Some(x) = option` error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_fallible.rs:14:14 + --> $DIR/for_loops_over_fallibles.rs:14:14 | LL | for x in result { | ^^^^^^ @@ -16,7 +16,7 @@ LL | for x in result { = help: consider replacing `for x in result` with `if let Ok(x) = result` error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_fallible.rs:18:14 + --> $DIR/for_loops_over_fallibles.rs:18:14 | LL | for x in option.ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | for x in option.ok_or("x not found") { = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop_over_fallible.rs:24:14 + --> $DIR/for_loops_over_fallibles.rs:24:14 | LL | for x in v.iter().next() { | ^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | for x in v.iter().next() { = note: `#[deny(clippy::iter_next_loop)]` on by default error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_fallible.rs:29:14 + --> $DIR/for_loops_over_fallibles.rs:29:14 | LL | for x in v.iter().next().and(Some(0)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | for x in v.iter().next().and(Some(0)) { = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop_over_fallible.rs:33:14 + --> $DIR/for_loops_over_fallibles.rs:33:14 | LL | for x in v.iter().next().ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | for x in v.iter().next().ok_or("x not found") { = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` error: this loop never actually loops - --> $DIR/for_loop_over_fallible.rs:45:5 + --> $DIR/for_loops_over_fallibles.rs:45:5 | LL | / while let Some(x) = option { LL | | println!("{}", x); @@ -59,7 +59,7 @@ LL | | } = note: `#[deny(clippy::never_loop)]` on by default error: this loop never actually loops - --> $DIR/for_loop_over_fallible.rs:51:5 + --> $DIR/for_loops_over_fallibles.rs:51:5 | LL | / while let Ok(x) = result { LL | | println!("{}", x); From fc8ab099c38952b91e38608c386314bde6dd2629 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Fri, 15 May 2020 21:17:37 +0200 Subject: [PATCH 069/526] identity_op: allow `1 << 0` --- clippy_lints/src/identity_op.rs | 22 ++++++++++++++++++++-- tests/ui/identity_op.rs | 5 +++++ tests/ui/identity_op.stderr | 20 +++++++++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 088e4ab1921..78e07d25f67 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,4 +1,5 @@ -use rustc_hir::{BinOpKind, Expr, ExprKind}; +use if_chain::if_chain; +use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -32,7 +33,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { if e.span.from_expansion() { return; } - if let ExprKind::Binary(ref cmp, ref left, ref right) = e.kind { + if let ExprKind::Binary(cmp, ref left, ref right) = e.kind { + if is_allowed(cx, cmp, left, right) { + return; + } match cmp.node { BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => { check(cx, left, 0, e.span, right.span); @@ -54,6 +58,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { } } +fn is_allowed(cx: &LateContext<'_, '_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> bool { + // `1 << 0` is a common pattern in bit manipulation code + if_chain! { + if let BinOpKind::Shl = cmp.node; + if let Some(Constant::Int(0)) = constant_simple(cx, cx.tables, right); + if let Some(Constant::Int(1)) = constant_simple(cx, cx.tables, left); + then { + return true; + } + } + + false +} + #[allow(clippy::cast_possible_wrap)] fn check(cx: &LateContext<'_, '_>, e: &Expr<'_>, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) { diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index ae2815d345a..ceaacaaf6bd 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -33,4 +33,9 @@ fn main() { let u: u8 = 0; u & 255; + + 1 << 0; // no error, this case is allowed, see issue 3430 + 42 << 0; + 1 >> 0; + 42 >> 0; } diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 4742877706a..d8d44a74f9a 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -48,5 +48,23 @@ error: the operation is ineffective. Consider reducing it to `u` LL | u & 255; | ^^^^^^^ -error: aborting due to 8 previous errors +error: the operation is ineffective. Consider reducing it to `42` + --> $DIR/identity_op.rs:38:5 + | +LL | 42 << 0; + | ^^^^^^^ + +error: the operation is ineffective. Consider reducing it to `1` + --> $DIR/identity_op.rs:39:5 + | +LL | 1 >> 0; + | ^^^^^^ + +error: the operation is ineffective. Consider reducing it to `42` + --> $DIR/identity_op.rs:40:5 + | +LL | 42 >> 0; + | ^^^^^^^ + +error: aborting due to 11 previous errors From 10313a2631efa6a01dc86199d554ce5a7c1bb51a Mon Sep 17 00:00:00 2001 From: Vardan Margaryan <v.t.margaryan@gmail.com> Date: Fri, 15 May 2020 22:33:37 +0300 Subject: [PATCH 070/526] Revert "Fix cases of match_wildcard_for_single_variants lint when it is spanned on Option" This reverts commit 494830797744c09d6de3b2b2452ab185d2204005. --- clippy_lints/src/consts.rs | 9 ++++----- clippy_lints/src/escape.rs | 4 ++-- clippy_lints/src/floating_point_arithmetic.rs | 2 +- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/modulo_arithmetic.rs | 1 - clippy_lints/src/utils/mod.rs | 2 -- 7 files changed, 9 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index efb424bcb7b..81ddc8c0067 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -139,7 +139,6 @@ impl Constant { .find(|r| r.map_or(true, |o| o != Ordering::Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))), (&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => { - #[allow(clippy::match_wildcard_for_single_variants)] match Self::partial_cmp(tcx, cmp_type, lv, rv) { Some(Equal) => Some(ls.cmp(rs)), x => x, @@ -355,14 +354,14 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { (Some(Constant::Vec(vec)), Some(Constant::Int(index))) => match vec.get(index as usize) { Some(Constant::F32(x)) => Some(Constant::F32(*x)), Some(Constant::F64(x)) => Some(Constant::F64(*x)), - Some(_) | None => None, + _ => None, }, (Some(Constant::Vec(vec)), _) => { if !vec.is_empty() && vec.iter().all(|x| *x == vec[0]) { match vec.get(0) { Some(Constant::F32(x)) => Some(Constant::F32(*x)), Some(Constant::F64(x)) => Some(Constant::F64(*x)), - Some(_) | None => None, + _ => None, } } else { None @@ -533,7 +532,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> { }) .collect::<Option<Vec<Constant>>>() .map(Constant::Vec), - Some(_) | None => None, + _ => None, }, ty::Float(FloatTy::F64) => match miri_to_const(len) { Some(Constant::Int(len)) => alloc @@ -547,7 +546,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> { }) .collect::<Option<Vec<Constant>>>() .map(Constant::Vec), - Some(_) | None => None, + _ => None, }, // FIXME: implement other array type conversions. _ => None, diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 615afee33ef..1ec60a0e6e6 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -95,12 +95,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal { fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool { match map.find(id) { Some(Node::Binding(_)) => (), - Some(_) | None => return false, + _ => return false, } match map.find(map.get_parent_node(id)) { Some(Node::Param(_)) => true, - Some(_) | None => false, + _ => false, } } diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 8c61b2f8664..86317fb8bd5 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -410,7 +410,7 @@ fn is_zero(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { Some(Constant::Int(i)) => i == 0, Some(Constant::F32(f)) => f == 0.0, Some(Constant::F64(f)) => f == 0.0, - Some(_) | None => false, + _ => false, } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 39908bff5ed..0bc6b70855b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2154,7 +2154,7 @@ fn is_loop_nested(cx: &LateContext<'_, '_>, loop_expr: &Expr<'_>, iter_expr: &Ex } }, Some(Node::Stmt(_)) => (), - Some(_) | None => { + _ => { return false; }, } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 38c2645d36e..e1d524c2231 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -509,7 +509,7 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> boo Constant::F64(f) => *f == 0.0 || (*f).is_infinite(), _ => false, }), - Some(_) | None => false, + _ => false, } } diff --git a/clippy_lints/src/modulo_arithmetic.rs b/clippy_lints/src/modulo_arithmetic.rs index 3bb3eb15d9c..4ca90455bc4 100644 --- a/clippy_lints/src/modulo_arithmetic.rs +++ b/clippy_lints/src/modulo_arithmetic.rs @@ -37,7 +37,6 @@ struct OperandInfo { } fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<OperandInfo> { - #[allow(clippy::match_wildcard_for_single_variants)] match constant(cx, cx.tables, operand) { Some((Constant::Int(v), _)) => match cx.tables.expr_ty(expr).kind { ty::Int(ity) => { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 7bc8be492e8..3b8ef18bfab 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -370,7 +370,6 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'_, 'tcx>, hir_id: HirId) -> O /// Checks whether this type implements `Drop`. pub fn has_drop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { - #[allow(clippy::match_wildcard_for_single_variants)] match ty.ty_adt_def() { Some(def) => def.has_dtor(cx.tcx), _ => false, @@ -445,7 +444,6 @@ pub fn is_entrypoint_fn(cx: &LateContext<'_, '_>, def_id: DefId) -> bool { /// Gets the name of the item the expression is in, if available. pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<Name> { let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id); - #[allow(clippy::match_wildcard_for_single_variants)] match cx.tcx.hir().find(parent_id) { Some( Node::Item(Item { ident, .. }) From 2620d2449da851171773f7bec1396af11babe278 Mon Sep 17 00:00:00 2001 From: Vardan Margaryan <v.t.margaryan@gmail.com> Date: Sat, 16 May 2020 00:06:52 +0300 Subject: [PATCH 071/526] Fix check for missing enum variants from match expressions TupleStruct matches are checked for exhaustiveness --- clippy_lints/src/matches.rs | 16 ++++++++++++++-- clippy_lints/src/utils/mod.rs | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 6fdb4cf9cd7..7d722820800 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -764,9 +764,21 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_ if let QPath::Resolved(_, p) = path { missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id())); } - } else if let PatKind::TupleStruct(ref path, ..) = arm.pat.kind { + } else if let PatKind::TupleStruct(ref path, ref patterns, ..) = arm.pat.kind { if let QPath::Resolved(_, p) = path { - missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id())); + // Some simple checks for exhaustive patterns. + // There is a room for improvements to detect more cases, + // but it can be more expensive to do so. + let is_pattern_exhaustive = |pat: &&Pat<'_>| { + if let PatKind::Wild | PatKind::Binding(.., None) = pat.kind { + true + } else { + false + } + }; + if patterns.iter().all(is_pattern_exhaustive) { + missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id())); + } } } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 3b8ef18bfab..7545235e646 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -372,7 +372,7 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'_, 'tcx>, hir_id: HirId) -> O pub fn has_drop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { match ty.ty_adt_def() { Some(def) => def.has_dtor(cx.tcx), - _ => false, + None => false, } } From d90625385e8ed0a9030e3ab2ea0990fce39c28bf Mon Sep 17 00:00:00 2001 From: Vardan Margaryan <v.t.margaryan@gmail.com> Date: Sat, 16 May 2020 00:19:30 +0300 Subject: [PATCH 072/526] Add more test cases for match_wildcard_for_single_variants --- .../match_wildcard_for_single_variants.fixed | 43 ++++++++++++++++++- .../ui/match_wildcard_for_single_variants.rs | 43 ++++++++++++++++++- .../match_wildcard_for_single_variants.stderr | 22 +++++++++- 3 files changed, 104 insertions(+), 4 deletions(-) diff --git a/tests/ui/match_wildcard_for_single_variants.fixed b/tests/ui/match_wildcard_for_single_variants.fixed index 5f1a559f591..519200977a7 100644 --- a/tests/ui/match_wildcard_for_single_variants.fixed +++ b/tests/ui/match_wildcard_for_single_variants.fixed @@ -9,10 +9,51 @@ enum Foo { C, } +enum Color { + Red, + Green, + Blue, + Rgb(u8, u8, u8), +} + fn main() { - match Foo::A { + let f = Foo::A; + match f { Foo::A => {}, Foo::B => {}, Foo::C => {}, } + + let color = Color::Red; + + // check exhaustive bindings + match color { + Color::Red => {}, + Color::Green => {}, + Color::Rgb(_r, _g, _b) => {}, + Color::Blue => {}, + } + + // check exhaustive wild + match color { + Color::Red => {}, + Color::Green => {}, + Color::Rgb(..) => {}, + Color::Blue => {}, + } + match color { + Color::Red => {}, + Color::Green => {}, + Color::Rgb(_, _, _) => {}, + Color::Blue => {}, + } + + // shouldn't lint as there is one missing variant + // and one that isn't exhaustively covered + match color { + Color::Red => {}, + Color::Green => {}, + Color::Rgb(255, _, _) => {}, + _ => {}, + } } diff --git a/tests/ui/match_wildcard_for_single_variants.rs b/tests/ui/match_wildcard_for_single_variants.rs index 1159f9e722d..1df917e085c 100644 --- a/tests/ui/match_wildcard_for_single_variants.rs +++ b/tests/ui/match_wildcard_for_single_variants.rs @@ -9,10 +9,51 @@ enum Foo { C, } +enum Color { + Red, + Green, + Blue, + Rgb(u8, u8, u8), +} + fn main() { - match Foo::A { + let f = Foo::A; + match f { Foo::A => {}, Foo::B => {}, _ => {}, } + + let color = Color::Red; + + // check exhaustive bindings + match color { + Color::Red => {}, + Color::Green => {}, + Color::Rgb(_r, _g, _b) => {}, + _ => {}, + } + + // check exhaustive wild + match color { + Color::Red => {}, + Color::Green => {}, + Color::Rgb(..) => {}, + _ => {}, + } + match color { + Color::Red => {}, + Color::Green => {}, + Color::Rgb(_, _, _) => {}, + _ => {}, + } + + // shouldn't lint as there is one missing variant + // and one that isn't exhaustively covered + match color { + Color::Red => {}, + Color::Green => {}, + Color::Rgb(255, _, _) => {}, + _ => {}, + } } diff --git a/tests/ui/match_wildcard_for_single_variants.stderr b/tests/ui/match_wildcard_for_single_variants.stderr index 128dd4808bf..82790aa9e80 100644 --- a/tests/ui/match_wildcard_for_single_variants.stderr +++ b/tests/ui/match_wildcard_for_single_variants.stderr @@ -1,10 +1,28 @@ error: wildcard match will miss any future added variants - --> $DIR/match_wildcard_for_single_variants.rs:16:9 + --> $DIR/match_wildcard_for_single_variants.rs:24:9 | LL | _ => {}, | ^ help: try this: `Foo::C` | = note: `-D clippy::match-wildcard-for-single-variants` implied by `-D warnings` -error: aborting due to previous error +error: wildcard match will miss any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:34:9 + | +LL | _ => {}, + | ^ help: try this: `Color::Blue` + +error: wildcard match will miss any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:42:9 + | +LL | _ => {}, + | ^ help: try this: `Color::Blue` + +error: wildcard match will miss any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:48:9 + | +LL | _ => {}, + | ^ help: try this: `Color::Blue` + +error: aborting due to 4 previous errors From e55b920970fdc33f5ddaf7757738fbacdadf15ab Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Mon, 4 May 2020 17:09:02 +0200 Subject: [PATCH 073/526] Rename lint `identity_conversion` to `useless_conversion` --- CHANGELOG.md | 4 +- clippy_lints/src/lib.rs | 11 +++-- ...ty_conversion.rs => useless_conversion.rs} | 30 +++++++----- src/lintlist/mod.rs | 14 +++--- ...version.fixed => useless_conversion.fixed} | 4 +- ...ty_conversion.rs => useless_conversion.rs} | 4 +- ...rsion.stderr => useless_conversion.stderr} | 46 +++++++++---------- 7 files changed, 60 insertions(+), 53 deletions(-) rename clippy_lints/src/{identity_conversion.rs => useless_conversion.rs} (84%) rename tests/ui/{identity_conversion.fixed => useless_conversion.fixed} (93%) rename tests/ui/{identity_conversion.rs => useless_conversion.rs} (94%) rename tests/ui/{identity_conversion.stderr => useless_conversion.stderr} (67%) diff --git a/CHANGELOG.md b/CHANGELOG.md index d05819a973a..9e85e6da3b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -805,7 +805,7 @@ Released 2018-09-13 ## 0.0.166 * Rustup to *rustc 1.22.0-nightly (b7960878b 2017-10-18)* -* New lints: [`explicit_write`], [`identity_conversion`], [`implicit_hasher`], [`invalid_ref`], [`option_map_or_none`], +* New lints: [`explicit_write`], `identity_conversion`, [`implicit_hasher`], [`invalid_ref`], [`option_map_or_none`], [`range_minus_one`], [`range_plus_one`], [`transmute_int_to_bool`], [`transmute_int_to_char`], [`transmute_int_to_float`] @@ -1367,7 +1367,6 @@ Released 2018-09-13 [`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send [`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len [`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap -[`identity_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_conversion [`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op [`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_mutex [`if_let_redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching @@ -1624,6 +1623,7 @@ Released 2018-09-13 [`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding [`useless_asref`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_asref [`useless_attribute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_attribute +[`useless_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion [`useless_format`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_format [`useless_let_if_seq`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_let_if_seq [`useless_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bda0d5c0458..4dda373738b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -221,7 +221,6 @@ mod formatting; mod functions; mod future_not_send; mod get_last_with_len; -mod identity_conversion; mod identity_op; mod if_let_mutex; mod if_let_some_result; @@ -324,6 +323,7 @@ mod unused_io_amount; mod unused_self; mod unwrap; mod use_self; +mod useless_conversion; mod vec; mod verbose_file_reads; mod wildcard_dependencies; @@ -577,7 +577,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &functions::TOO_MANY_LINES, &future_not_send::FUTURE_NOT_SEND, &get_last_with_len::GET_LAST_WITH_LEN, - &identity_conversion::IDENTITY_CONVERSION, &identity_op::IDENTITY_OP, &if_let_mutex::IF_LET_MUTEX, &if_let_some_result::IF_LET_SOME_RESULT, @@ -843,6 +842,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &unwrap::PANICKING_UNWRAP, &unwrap::UNNECESSARY_UNWRAP, &use_self::USE_SELF, + &useless_conversion::USELESS_CONVERSION, &utils::internal_lints::CLIPPY_LINTS_INTERNAL, &utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS, &utils::internal_lints::COMPILER_LINT_FUNCTIONS, @@ -980,7 +980,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box bytecount::ByteCount); store.register_late_pass(|| box infinite_iter::InfiniteIter); store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody); - store.register_late_pass(|| box identity_conversion::IdentityConversion::default()); + store.register_late_pass(|| box useless_conversion::UselessConversion::default()); store.register_late_pass(|| box types::ImplicitHasher); store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom); store.register_late_pass(|| box types::UnitArg); @@ -1241,7 +1241,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF), LintId::of(&functions::TOO_MANY_ARGUMENTS), LintId::of(&get_last_with_len::GET_LAST_WITH_LEN), - LintId::of(&identity_conversion::IDENTITY_CONVERSION), LintId::of(&identity_op::IDENTITY_OP), LintId::of(&if_let_mutex::IF_LET_MUTEX), LintId::of(&if_let_some_result::IF_LET_SOME_RESULT), @@ -1427,6 +1426,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), LintId::of(&unwrap::PANICKING_UNWRAP), LintId::of(&unwrap::UNNECESSARY_UNWRAP), + LintId::of(&useless_conversion::USELESS_CONVERSION), LintId::of(&vec::USELESS_VEC), LintId::of(&write::PRINTLN_EMPTY_STRING), LintId::of(&write::PRINT_LITERAL), @@ -1546,7 +1546,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&format::USELESS_FORMAT), LintId::of(&functions::TOO_MANY_ARGUMENTS), LintId::of(&get_last_with_len::GET_LAST_WITH_LEN), - LintId::of(&identity_conversion::IDENTITY_CONVERSION), LintId::of(&identity_op::IDENTITY_OP), LintId::of(&int_plus_one::INT_PLUS_ONE), LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES), @@ -1605,6 +1604,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::UNNECESSARY_CAST), LintId::of(&types::VEC_BOX), LintId::of(&unwrap::UNNECESSARY_UNWRAP), + LintId::of(&useless_conversion::USELESS_CONVERSION), LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO), ]); @@ -1795,6 +1795,7 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) { ls.register_renamed("clippy::result_expect_used", "clippy::expect_used"); ls.register_renamed("clippy::for_loop_over_option", "clippy::for_loops_over_fallibles"); ls.register_renamed("clippy::for_loop_over_result", "clippy::for_loops_over_fallibles"); + ls.register_renamed("clippy::identity_conversion", "clippy::useless_conversion"); } // only exists to let the dogfood integration test works. diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/useless_conversion.rs similarity index 84% rename from clippy_lints/src/identity_conversion.rs rename to clippy_lints/src/useless_conversion.rs index 33a9478f058..95921518986 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -7,30 +7,36 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { - /// **What it does:** Checks for always-identical `Into`/`From`/`IntoIter` conversions. + /// **What it does:** Checks for `Into`/`From`/`IntoIter` calls that useless converts + /// to the same type as caller. /// /// **Why is this bad?** Redundant code. /// /// **Known problems:** None. /// /// **Example:** + /// /// ```rust + /// // Bad /// // format!() returns a `String` /// let s: String = format!("hello").into(); + /// + /// // Good + /// let s: String = format!("hello"); /// ``` - pub IDENTITY_CONVERSION, + pub USELESS_CONVERSION, complexity, - "using always-identical `Into`/`From`/`IntoIter` conversions" + "calls to `Into`/`From`/`IntoIter` that performs useless conversions to the same type" } #[derive(Default)] -pub struct IdentityConversion { +pub struct UselessConversion { try_desugar_arm: Vec<HirId>, } -impl_lint_pass!(IdentityConversion => [IDENTITY_CONVERSION]); +impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { if e.span.from_expansion() { return; @@ -60,9 +66,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { span_lint_and_sugg( cx, - IDENTITY_CONVERSION, + USELESS_CONVERSION, e.span, - "identical conversion", + "useless conversion", "consider removing `.into()`", sugg, Applicability::MachineApplicable, // snippet @@ -76,9 +82,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { let sugg = snippet(cx, args[0].span, "<expr>").into_owned(); span_lint_and_sugg( cx, - IDENTITY_CONVERSION, + USELESS_CONVERSION, e.span, - "identical conversion", + "useless conversion", "consider removing `.into_iter()`", sugg, Applicability::MachineApplicable, // snippet @@ -99,9 +105,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); span_lint_and_sugg( cx, - IDENTITY_CONVERSION, + USELESS_CONVERSION, e.span, - "identical conversion", + "useless conversion", &sugg_msg, sugg, Applicability::MachineApplicable, // snippet diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index e5e3bf453a0..e411e60782a 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -717,13 +717,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "methods", }, - Lint { - name: "identity_conversion", - group: "complexity", - desc: "using always-identical `Into`/`From`/`IntoIter` conversions", - deprecation: None, - module: "identity_conversion", - }, Lint { name: "identity_op", group: "complexity", @@ -2418,6 +2411,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "attrs", }, + Lint { + name: "useless_conversion", + group: "complexity", + desc: "calls to `Into`/`From`/`IntoIter` that performs useless conversions to the same type", + deprecation: None, + module: "useless_conversion", + }, Lint { name: "useless_format", group: "complexity", diff --git a/tests/ui/identity_conversion.fixed b/tests/ui/useless_conversion.fixed similarity index 93% rename from tests/ui/identity_conversion.fixed rename to tests/ui/useless_conversion.fixed index dd3fc56e98b..fdd4bc581f3 100644 --- a/tests/ui/identity_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -1,6 +1,6 @@ // run-rustfix -#![deny(clippy::identity_conversion)] +#![deny(clippy::useless_conversion)] fn test_generic<T: Copy>(val: T) -> T { let _ = val; @@ -41,7 +41,7 @@ fn main() { let _: String = "foo".into(); let _: String = From::from("foo"); let _ = String::from("foo"); - #[allow(clippy::identity_conversion)] + #[allow(clippy::useless_conversion)] { let _: String = "foo".into(); let _ = String::from("foo"); diff --git a/tests/ui/identity_conversion.rs b/tests/ui/useless_conversion.rs similarity index 94% rename from tests/ui/identity_conversion.rs rename to tests/ui/useless_conversion.rs index 875ed7db373..4cae745e7c0 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -1,6 +1,6 @@ // run-rustfix -#![deny(clippy::identity_conversion)] +#![deny(clippy::useless_conversion)] fn test_generic<T: Copy>(val: T) -> T { let _ = T::from(val); @@ -41,7 +41,7 @@ fn main() { let _: String = "foo".into(); let _: String = From::from("foo"); let _ = String::from("foo"); - #[allow(clippy::identity_conversion)] + #[allow(clippy::useless_conversion)] { let _: String = "foo".into(); let _ = String::from("foo"); diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/useless_conversion.stderr similarity index 67% rename from tests/ui/identity_conversion.stderr rename to tests/ui/useless_conversion.stderr index 57626b23795..7df3507edfd 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -1,65 +1,65 @@ -error: identical conversion - --> $DIR/identity_conversion.rs:6:13 +error: useless conversion + --> $DIR/useless_conversion.rs:6:13 | LL | let _ = T::from(val); | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` | note: the lint level is defined here - --> $DIR/identity_conversion.rs:3:9 + --> $DIR/useless_conversion.rs:3:9 | -LL | #![deny(clippy::identity_conversion)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(clippy::useless_conversion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: identical conversion - --> $DIR/identity_conversion.rs:7:5 +error: useless conversion + --> $DIR/useless_conversion.rs:7:5 | LL | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` -error: identical conversion - --> $DIR/identity_conversion.rs:19:22 +error: useless conversion + --> $DIR/useless_conversion.rs:19:22 | LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` -error: identical conversion - --> $DIR/identity_conversion.rs:51:21 +error: useless conversion + --> $DIR/useless_conversion.rs:51:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` -error: identical conversion - --> $DIR/identity_conversion.rs:52:21 +error: useless conversion + --> $DIR/useless_conversion.rs:52:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` -error: identical conversion - --> $DIR/identity_conversion.rs:53:13 +error: useless conversion + --> $DIR/useless_conversion.rs:53:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` -error: identical conversion - --> $DIR/identity_conversion.rs:54:13 +error: useless conversion + --> $DIR/useless_conversion.rs:54:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` -error: identical conversion - --> $DIR/identity_conversion.rs:55:13 +error: useless conversion + --> $DIR/useless_conversion.rs:55:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` -error: identical conversion - --> $DIR/identity_conversion.rs:56:13 +error: useless conversion + --> $DIR/useless_conversion.rs:56:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` -error: identical conversion - --> $DIR/identity_conversion.rs:57:21 +error: useless conversion + --> $DIR/useless_conversion.rs:57:21 | LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` From cb7f9679a63075b3fce2fdc69f7b02fe0f482464 Mon Sep 17 00:00:00 2001 From: Aleksei Latyshev <alex_700_95@mail.ru> Date: Sat, 25 Apr 2020 20:52:00 +0300 Subject: [PATCH 074/526] simplify multispan_sugg interface - add `multispan_sugg_with_applicability` - not it gets `&str` instead of `String`, like in `diag.multispan_suggestion` --- clippy_lints/src/eq_op.rs | 2 +- clippy_lints/src/loops.rs | 4 ++-- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/types.rs | 2 +- clippy_lints/src/utils/diagnostics.rs | 28 +++++++++++----------- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 098d47bdd40..4e1c1f13140 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -115,7 +115,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { let rsnip = snippet(cx, r.span, "...").to_string(); multispan_sugg( diag, - "use the values directly".to_string(), + "use the values directly", vec![(left.span, lsnip), (right.span, rsnip)], ); }, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 9c9d1a84003..4a9c411d7c8 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1134,7 +1134,7 @@ fn check_for_loop_range<'a, 'tcx>( |diag| { multispan_sugg( diag, - "consider using an iterator".to_string(), + "consider using an iterator", vec![ (pat.span, format!("({}, <item>)", ident.name)), ( @@ -1163,7 +1163,7 @@ fn check_for_loop_range<'a, 'tcx>( |diag| { multispan_sugg( diag, - "consider using an iterator".to_string(), + "consider using an iterator", vec![(pat.span, "<item>".to_string()), (arg.span, repl)], ); }, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 8f86535ef1e..bbf14374a1f 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -820,7 +820,7 @@ fn check_match_ref_pats(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_> span_lint_and_then(cx, MATCH_REF_PATS, expr.span, title, |diag| { if !expr.span.from_expansion() { - multispan_sugg(diag, msg.to_owned(), suggs); + multispan_sugg(diag, msg, suggs); } }); } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index a21818701da..ed48ab54897 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -293,7 +293,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { ); spans.sort_by_key(|&(span, _)| span); } - multispan_sugg(diag, "consider taking a reference instead".to_string(), spans); + multispan_sugg(diag, "consider taking a reference instead", spans); }; span_lint_and_then( diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 6d49f50d550..f50adbc48ab 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -2206,7 +2206,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { multispan_sugg( diag, - "consider adding a type parameter".to_string(), + "consider adding a type parameter", vec![ ( generics_suggestion_span, diff --git a/clippy_lints/src/utils/diagnostics.rs b/clippy_lints/src/utils/diagnostics.rs index 24a1bdf1883..f6d87c8532e 100644 --- a/clippy_lints/src/utils/diagnostics.rs +++ b/clippy_lints/src/utils/diagnostics.rs @@ -1,6 +1,6 @@ //! Clippy wrappers around rustc's diagnostic functions. -use rustc_errors::{Applicability, CodeSuggestion, DiagnosticBuilder, Substitution, SubstitutionPart, SuggestionStyle}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::HirId; use rustc_lint::{LateContext, Lint, LintContext}; use rustc_span::source_map::{MultiSpan, Span}; @@ -198,20 +198,20 @@ pub fn span_lint_and_sugg<'a, T: LintContext>( /// appear once per /// replacement. In human-readable format though, it only appears once before /// the whole suggestion. -pub fn multispan_sugg<I>(diag: &mut DiagnosticBuilder<'_>, help_msg: String, sugg: I) +pub fn multispan_sugg<I>(diag: &mut DiagnosticBuilder<'_>, help_msg: &str, sugg: I) where I: IntoIterator<Item = (Span, String)>, { - let sugg = CodeSuggestion { - substitutions: vec![Substitution { - parts: sugg - .into_iter() - .map(|(span, snippet)| SubstitutionPart { snippet, span }) - .collect(), - }], - msg: help_msg, - style: SuggestionStyle::ShowCode, - applicability: Applicability::Unspecified, - }; - diag.suggestions.push(sugg); + multispan_sugg_with_applicability(diag, help_msg, Applicability::Unspecified, sugg) +} + +pub fn multispan_sugg_with_applicability<I>( + diag: &mut DiagnosticBuilder<'_>, + help_msg: &str, + applicability: Applicability, + sugg: I, +) where + I: IntoIterator<Item = (Span, String)>, +{ + diag.multipart_suggestion(help_msg, sugg.into_iter().collect(), applicability); } From 404ae5b211c9fb3960b64ecbf91d903d484b0c20 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sun, 17 May 2020 01:14:28 +0200 Subject: [PATCH 075/526] Re-remove util/dev Maybe someday, git subtree will do it right --- util/dev | 7 ------- 1 file changed, 7 deletions(-) delete mode 100755 util/dev diff --git a/util/dev b/util/dev deleted file mode 100755 index 319de217e0d..00000000000 --- a/util/dev +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -CARGO_TARGET_DIR=$(pwd)/target/ -export CARGO_TARGET_DIR - -echo 'Deprecated! `util/dev` usage is deprecated, please use `cargo dev` instead.' - -cd clippy_dev && cargo run -- "$@" From 7f317b708fe0889c04b7590ba53f3a41afa44a1d Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sun, 17 May 2020 01:18:43 +0200 Subject: [PATCH 076/526] Run fmt --- src/driver.rs | 228 +++++++++++++++++++++++++------------------------- 1 file changed, 113 insertions(+), 115 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 1ce0300f239..d3a7e24937f 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -295,121 +295,119 @@ fn toolchain_path(home: Option<String>, toolchain: Option<String>) -> Option<Pat pub fn main() { rustc_driver::init_rustc_env_logger(); lazy_static::initialize(&ICE_HOOK); - exit( - rustc_driver::catch_with_exit_code(move || { - let mut orig_args: Vec<String> = env::args().collect(); + exit(rustc_driver::catch_with_exit_code(move || { + let mut orig_args: Vec<String> = env::args().collect(); - if orig_args.iter().any(|a| a == "--version" || a == "-V") { - let version_info = rustc_tools_util::get_version_info!(); - println!("{}", version_info); - exit(0); + if orig_args.iter().any(|a| a == "--version" || a == "-V") { + let version_info = rustc_tools_util::get_version_info!(); + println!("{}", version_info); + exit(0); + } + + // Get the sysroot, looking from most specific to this invocation to the least: + // - command line + // - runtime environment + // - SYSROOT + // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN + // - sysroot from rustc in the path + // - compile-time environment + // - SYSROOT + // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN + let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true); + let have_sys_root_arg = sys_root_arg.is_some(); + let sys_root = sys_root_arg + .map(PathBuf::from) + .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from)) + .or_else(|| { + let home = std::env::var("RUSTUP_HOME") + .or_else(|_| std::env::var("MULTIRUST_HOME")) + .ok(); + let toolchain = std::env::var("RUSTUP_TOOLCHAIN") + .or_else(|_| std::env::var("MULTIRUST_TOOLCHAIN")) + .ok(); + toolchain_path(home, toolchain) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| PathBuf::from(s.trim())) + }) + .or_else(|| option_env!("SYSROOT").map(PathBuf::from)) + .or_else(|| { + let home = option_env!("RUSTUP_HOME") + .or(option_env!("MULTIRUST_HOME")) + .map(ToString::to_string); + let toolchain = option_env!("RUSTUP_TOOLCHAIN") + .or(option_env!("MULTIRUST_TOOLCHAIN")) + .map(ToString::to_string); + toolchain_path(home, toolchain) + }) + .map(|pb| pb.to_string_lossy().to_string()) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); + + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programmatically, so we ignore this/ + let wrapper_mode = orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref()); + + if wrapper_mode { + // we still want to be able to invoke it normally though + orig_args.remove(1); + } + + if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) { + display_help(); + exit(0); + } + + let should_describe_lints = || { + let args: Vec<_> = env::args().collect(); + args.windows(2).any(|args| { + args[1] == "help" + && match args[0].as_str() { + "-W" | "-A" | "-D" | "-F" => true, + _ => false, + } + }) + }; + + if !wrapper_mode && should_describe_lints() { + describe_lints(); + exit(0); + } + + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let mut args: Vec<String> = orig_args.clone(); + if !have_sys_root_arg { + args.extend(vec!["--sysroot".into(), sys_root]); + }; + + // this check ensures that dependencies are built but not linted and the final + // crate is linted but not built + let clippy_enabled = env::var("CLIPPY_TESTS").map_or(false, |val| val == "true") + || arg_value(&orig_args, "--cap-lints", |val| val == "allow").is_none(); + + if clippy_enabled { + args.extend(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()]); + if let Ok(extra_args) = env::var("CLIPPY_ARGS") { + args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| { + if s.is_empty() { + None + } else { + Some(s.to_string()) + } + })); } - - // Get the sysroot, looking from most specific to this invocation to the least: - // - command line - // - runtime environment - // - SYSROOT - // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN - // - sysroot from rustc in the path - // - compile-time environment - // - SYSROOT - // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN - let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true); - let have_sys_root_arg = sys_root_arg.is_some(); - let sys_root = sys_root_arg - .map(PathBuf::from) - .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from)) - .or_else(|| { - let home = std::env::var("RUSTUP_HOME") - .or_else(|_| std::env::var("MULTIRUST_HOME")) - .ok(); - let toolchain = std::env::var("RUSTUP_TOOLCHAIN") - .or_else(|_| std::env::var("MULTIRUST_TOOLCHAIN")) - .ok(); - toolchain_path(home, toolchain) - }) - .or_else(|| { - Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| PathBuf::from(s.trim())) - }) - .or_else(|| option_env!("SYSROOT").map(PathBuf::from)) - .or_else(|| { - let home = option_env!("RUSTUP_HOME") - .or(option_env!("MULTIRUST_HOME")) - .map(ToString::to_string); - let toolchain = option_env!("RUSTUP_TOOLCHAIN") - .or(option_env!("MULTIRUST_TOOLCHAIN")) - .map(ToString::to_string); - toolchain_path(home, toolchain) - }) - .map(|pb| pb.to_string_lossy().to_string()) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); - - // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. - // We're invoking the compiler programmatically, so we ignore this/ - let wrapper_mode = orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref()); - - if wrapper_mode { - // we still want to be able to invoke it normally though - orig_args.remove(1); - } - - if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) { - display_help(); - exit(0); - } - - let should_describe_lints = || { - let args: Vec<_> = env::args().collect(); - args.windows(2).any(|args| { - args[1] == "help" - && match args[0].as_str() { - "-W" | "-A" | "-D" | "-F" => true, - _ => false, - } - }) - }; - - if !wrapper_mode && should_describe_lints() { - describe_lints(); - exit(0); - } - - // this conditional check for the --sysroot flag is there so users can call - // `clippy_driver` directly - // without having to pass --sysroot or anything - let mut args: Vec<String> = orig_args.clone(); - if !have_sys_root_arg { - args.extend(vec!["--sysroot".into(), sys_root]); - }; - - // this check ensures that dependencies are built but not linted and the final - // crate is linted but not built - let clippy_enabled = env::var("CLIPPY_TESTS").map_or(false, |val| val == "true") - || arg_value(&orig_args, "--cap-lints", |val| val == "allow").is_none(); - - if clippy_enabled { - args.extend(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()]); - if let Ok(extra_args) = env::var("CLIPPY_ARGS") { - args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| { - if s.is_empty() { - None - } else { - Some(s.to_string()) - } - })); - } - } - let mut clippy = ClippyCallbacks; - let mut default = DefaultCallbacks; - let callbacks: &mut (dyn rustc_driver::Callbacks + Send) = - if clippy_enabled { &mut clippy } else { &mut default }; - rustc_driver::run_compiler(&args, callbacks, None, None) - }) - ) + } + let mut clippy = ClippyCallbacks; + let mut default = DefaultCallbacks; + let callbacks: &mut (dyn rustc_driver::Callbacks + Send) = + if clippy_enabled { &mut clippy } else { &mut default }; + rustc_driver::run_compiler(&args, callbacks, None, None) + })) } From e5b5f6f8a99253560096a5718fc7fc81daa23e02 Mon Sep 17 00:00:00 2001 From: Philipp Krones <hello@philkrones.com> Date: Sun, 17 May 2020 01:38:01 +0200 Subject: [PATCH 077/526] Better explain remotes in the sync process. --- CONTRIBUTING.md | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f7a60938374..6697ff2f40d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -166,15 +166,18 @@ Clippy in the `rust-lang/rust` repository. For general information about `subtree`s in the Rust repository see [Rust's `CONTRIBUTING.md`][subtree]. -Here is a TL;DR version of the sync process: +Here is a TL;DR version of the sync process (all of the following commands have +to be run inside the `rust` directory): -1. Clone the [`rust-lang/rust`] repository (all of the following commands have - to be run inside the `rust` directory) +1. Clone the [`rust-lang/rust`] repository 2. Sync the changes to the rust-copy of Clippy to your Clippy fork: ```bash # Make sure to change `your-github-name` to your github name in the following command git subtree push -P src/tools/clippy git@github.com:your-github-name/rust-clippy sync-from-rust ``` + _Note:_ This will directly push to the remote repository. You can also push + to your local copy by replacing the remote address with `/path/to/rust-clippy` + directory. 3. Open a PR to `rust-lang/rust-clippy` and wait for it to get merged (to accelerate the process ping the `@rust-lang/clippy` team in your PR and/or ~~annoy~~ ask them in the [Discord] channel.) @@ -185,6 +188,27 @@ Here is a TL;DR version of the sync process: ``` 5. Open a PR to [`rust-lang/rust`] +Also, you may want to define remotes, so you don't have to type out the remote +addresses on every sync. You can do this with the following commands (these +commands still have to be run inside the `rust` directory): + +```bash +# Set clippy-upstream remote for pulls +$ git remote add clippy-upstream https://github.com/rust-lang/rust-clippy +# Make sure to not push to the upstream repo +$ git remote set-url --push clippy-upstream DISABLED +# Set clippy-origin remote to your fork for pushes +$ git remote add clippy-origin git@github.com:your-github-name/rust-clippy +# Set a local remote +$ git remote add clippy-local /path/to/rust-clippy +``` + +You can then sync with the remote names from above, e.g.: + +```bash +$ git subtree push -P src/tools/clippy clippy-local sync-from-rust +``` + [subtree]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#external-dependencies-subtree [`rust-lang/rust`]: https://github.com/rust-lang/rust From 07f1edf2d43efa0ef53e5b6c56c895bc9738ab94 Mon Sep 17 00:00:00 2001 From: Aleksei Latyshev <alex_700_95@mail.ru> Date: Sat, 25 Apr 2020 23:33:11 +0300 Subject: [PATCH 078/526] improve and generalize `option_and_then_some` lint - rename it to bind_instead_of_map --- CHANGELOG.md | 4 +- clippy_lints/src/lib.rs | 7 +- clippy_lints/src/loops.rs | 2 +- .../src/methods/bind_instead_of_map.rs | 309 ++++++++++++++++++ clippy_lints/src/methods/mod.rs | 100 ++---- clippy_lints/src/types.rs | 2 +- src/lintlist/mod.rs | 14 +- ...n_some.fixed => bind_instead_of_map.fixed} | 4 +- ...nd_then_some.rs => bind_instead_of_map.rs} | 2 +- ...some.stderr => bind_instead_of_map.stderr} | 18 +- tests/ui/bind_instead_of_map_multipart.rs | 61 ++++ tests/ui/bind_instead_of_map_multipart.stderr | 73 +++++ tests/ui/blocks_in_if_conditions.fixed | 4 +- tests/ui/blocks_in_if_conditions.rs | 4 +- tests/ui/option_map_or_none.fixed | 2 +- tests/ui/option_map_or_none.rs | 2 +- 16 files changed, 503 insertions(+), 105 deletions(-) create mode 100644 clippy_lints/src/methods/bind_instead_of_map.rs rename tests/ui/{option_and_then_some.fixed => bind_instead_of_map.fixed} (90%) rename tests/ui/{option_and_then_some.rs => bind_instead_of_map.rs} (94%) rename tests/ui/{option_and_then_some.stderr => bind_instead_of_map.stderr} (50%) create mode 100644 tests/ui/bind_instead_of_map_multipart.rs create mode 100644 tests/ui/bind_instead_of_map_multipart.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index d05819a973a..7abefe65424 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -315,7 +315,7 @@ Released 2019-11-07 * [`missing_safety_doc`] [#4535](https://github.com/rust-lang/rust-clippy/pull/4535) * [`mem_replace_with_uninit`] [#4511](https://github.com/rust-lang/rust-clippy/pull/4511) * [`suspicious_map`] [#4394](https://github.com/rust-lang/rust-clippy/pull/4394) - * [`option_and_then_some`] [#4386](https://github.com/rust-lang/rust-clippy/pull/4386) + * `option_and_then_some` [#4386](https://github.com/rust-lang/rust-clippy/pull/4386) * [`manual_saturating_arithmetic`] [#4498](https://github.com/rust-lang/rust-clippy/pull/4498) * Deprecate `unused_collect` lint. This is fully covered by rustc's `#[must_use]` on `collect` [#4348](https://github.com/rust-lang/rust-clippy/pull/4348) * Move `type_repetition_in_bounds` to pedantic group [#4403](https://github.com/rust-lang/rust-clippy/pull/4403) @@ -1273,6 +1273,7 @@ Released 2018-09-13 [`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops [`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock [`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask +[`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map [`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name [`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_if_conditions [`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison @@ -1494,7 +1495,6 @@ Released 2018-09-13 [`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref [`ok_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#ok_expect [`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref -[`option_and_then_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_and_then_some [`option_as_ref_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref [`option_env_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_env_unwrap [`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bda0d5c0458..ec198b684b6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -650,6 +650,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &mem_replace::MEM_REPLACE_OPTION_WITH_NONE, &mem_replace::MEM_REPLACE_WITH_DEFAULT, &mem_replace::MEM_REPLACE_WITH_UNINIT, + &methods::BIND_INSTEAD_OF_MAP, &methods::CHARS_LAST_CMP, &methods::CHARS_NEXT_CMP, &methods::CLONE_DOUBLE_REF, @@ -676,7 +677,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::MAP_UNWRAP_OR, &methods::NEW_RET_NO_SELF, &methods::OK_EXPECT, - &methods::OPTION_AND_THEN_SOME, &methods::OPTION_AS_REF_DEREF, &methods::OPTION_MAP_OR_NONE, &methods::OR_FUN_CALL, @@ -1291,6 +1291,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE), LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT), LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT), + LintId::of(&methods::BIND_INSTEAD_OF_MAP), LintId::of(&methods::CHARS_LAST_CMP), LintId::of(&methods::CHARS_NEXT_CMP), LintId::of(&methods::CLONE_DOUBLE_REF), @@ -1307,7 +1308,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC), LintId::of(&methods::NEW_RET_NO_SELF), LintId::of(&methods::OK_EXPECT), - LintId::of(&methods::OPTION_AND_THEN_SOME), LintId::of(&methods::OPTION_AS_REF_DEREF), LintId::of(&methods::OPTION_MAP_OR_NONE), LintId::of(&methods::OR_FUN_CALL), @@ -1559,10 +1559,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&matches::MATCH_AS_REF), LintId::of(&matches::MATCH_SINGLE_BINDING), LintId::of(&matches::WILDCARD_IN_OR_PATTERNS), + LintId::of(&methods::BIND_INSTEAD_OF_MAP), LintId::of(&methods::CLONE_ON_COPY), LintId::of(&methods::FILTER_NEXT), LintId::of(&methods::FLAT_MAP_IDENTITY), - LintId::of(&methods::OPTION_AND_THEN_SOME), LintId::of(&methods::OPTION_AS_REF_DEREF), LintId::of(&methods::SEARCH_IS_SOME), LintId::of(&methods::SKIP_WHILE_NEXT), @@ -1784,6 +1784,7 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) { ls.register_renamed("clippy::new_without_default_derive", "clippy::new_without_default"); ls.register_renamed("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"); ls.register_renamed("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"); + ls.register_renamed("clippy::option_and_then_some", "clippy::bind_instead_of_map"); ls.register_renamed("clippy::block_in_if_condition_expr", "clippy::blocks_in_if_conditions"); ls.register_renamed("clippy::block_in_if_condition_stmt", "clippy::blocks_in_if_conditions"); ls.register_renamed("clippy::option_map_unwrap_or", "clippy::map_unwrap_or"); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 4a9c411d7c8..84e8a010738 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1462,7 +1462,7 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( let map = sugg::Sugg::hir(cx, arg, "map"); multispan_sugg( diag, - "use the corresponding method".into(), + "use the corresponding method", vec![ (pat_span, snippet(cx, new_pat_span, kind).into_owned()), (arg_span, format!("{}.{}s{}()", map.maybe_par(), kind, mutbl)), diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs new file mode 100644 index 00000000000..32e86637569 --- /dev/null +++ b/clippy_lints/src/methods/bind_instead_of_map.rs @@ -0,0 +1,309 @@ +use super::{contains_return, BIND_INSTEAD_OF_MAP}; +use crate::utils::{ + in_macro, match_qpath, match_type, method_calls, multispan_sugg_with_applicability, paths, remove_blocks, snippet, + snippet_with_macro_callsite, span_lint_and_sugg, span_lint_and_then, +}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_hir::intravisit::{self, Visitor}; +use rustc_lint::LateContext; +use rustc_middle::hir::map::Map; +use rustc_span::Span; + +pub(crate) struct OptionAndThenSome; +impl BindInsteadOfMap for OptionAndThenSome { + const TYPE_NAME: &'static str = "Option"; + const TYPE_QPATH: &'static [&'static str] = &paths::OPTION; + + const BAD_METHOD_NAME: &'static str = "and_then"; + const BAD_VARIANT_NAME: &'static str = "Some"; + const BAD_VARIANT_QPATH: &'static [&'static str] = &paths::OPTION_SOME; + + const GOOD_METHOD_NAME: &'static str = "map"; +} + +pub(crate) struct ResultAndThenOk; +impl BindInsteadOfMap for ResultAndThenOk { + const TYPE_NAME: &'static str = "Result"; + const TYPE_QPATH: &'static [&'static str] = &paths::RESULT; + + const BAD_METHOD_NAME: &'static str = "and_then"; + const BAD_VARIANT_NAME: &'static str = "Ok"; + const BAD_VARIANT_QPATH: &'static [&'static str] = &paths::RESULT_OK; + + const GOOD_METHOD_NAME: &'static str = "map"; +} + +pub(crate) struct ResultOrElseErrInfo; +impl BindInsteadOfMap for ResultOrElseErrInfo { + const TYPE_NAME: &'static str = "Result"; + const TYPE_QPATH: &'static [&'static str] = &paths::RESULT; + + const BAD_METHOD_NAME: &'static str = "or_else"; + const BAD_VARIANT_NAME: &'static str = "Err"; + const BAD_VARIANT_QPATH: &'static [&'static str] = &paths::RESULT_ERR; + + const GOOD_METHOD_NAME: &'static str = "map_err"; +} + +pub(crate) trait BindInsteadOfMap { + const TYPE_NAME: &'static str; + const TYPE_QPATH: &'static [&'static str]; + + const BAD_METHOD_NAME: &'static str; + const BAD_VARIANT_NAME: &'static str; + const BAD_VARIANT_QPATH: &'static [&'static str]; + + const GOOD_METHOD_NAME: &'static str; + + fn no_op_msg() -> String { + format!( + "using `{}.{}({})`, which is a no-op", + Self::TYPE_NAME, + Self::BAD_METHOD_NAME, + Self::BAD_VARIANT_NAME + ) + } + + fn lint_msg() -> String { + format!( + "using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`", + Self::TYPE_NAME, + Self::BAD_METHOD_NAME, + Self::BAD_VARIANT_NAME, + Self::GOOD_METHOD_NAME + ) + } + + fn lint_closure_autofixable( + cx: &LateContext<'_, '_>, + expr: &hir::Expr<'_>, + args: &[hir::Expr<'_>], + closure_expr: &hir::Expr<'_>, + closure_args_span: Span, + ) -> bool { + if_chain! { + if let hir::ExprKind::Call(ref some_expr, ref some_args) = closure_expr.kind; + if let hir::ExprKind::Path(ref qpath) = some_expr.kind; + if match_qpath(qpath, Self::BAD_VARIANT_QPATH); + if some_args.len() == 1; + then { + let inner_expr = &some_args[0]; + + if contains_return(inner_expr) { + return false; + } + + let some_inner_snip = if inner_expr.span.from_expansion() { + snippet_with_macro_callsite(cx, inner_expr.span, "_") + } else { + snippet(cx, inner_expr.span, "_") + }; + + let closure_args_snip = snippet(cx, closure_args_span, ".."); + let option_snip = snippet(cx, args[0].span, ".."); + let note = format!("{}.{}({} {})", option_snip, Self::GOOD_METHOD_NAME, closure_args_snip, some_inner_snip); + span_lint_and_sugg( + cx, + BIND_INSTEAD_OF_MAP, + expr.span, + Self::lint_msg().as_ref(), + "try this", + note, + Applicability::MachineApplicable, + ); + true + } else { + false + } + } + } + + fn lint_closure(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, closure_expr: &hir::Expr<'_>) { + let mut suggs = Vec::new(); + let can_sugg = find_all_ret_expressions(cx, closure_expr, |ret_expr| { + if_chain! { + if !in_macro(ret_expr.span); + if let hir::ExprKind::Call(ref func_path, ref args) = ret_expr.kind; + if let hir::ExprKind::Path(ref qpath) = func_path.kind; + if match_qpath(qpath, Self::BAD_VARIANT_QPATH); + if args.len() == 1; + if !contains_return(&args[0]); + then { + suggs.push((ret_expr.span, args[0].span.source_callsite())); + true + } else { + false + } + } + }); + + if can_sugg { + span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, Self::lint_msg().as_ref(), |diag| { + multispan_sugg_with_applicability( + diag, + "try this", + Applicability::MachineApplicable, + std::iter::once((*method_calls(expr, 1).2.get(0).unwrap(), Self::GOOD_METHOD_NAME.into())).chain( + suggs + .into_iter() + .map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())), + ), + ) + }); + } + } + + /// Lint use of `_.and_then(|x| Some(y))` for `Option`s + fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { + if !match_type(cx, cx.tables.expr_ty(&args[0]), Self::TYPE_QPATH) { + return; + } + + match args[1].kind { + hir::ExprKind::Closure(_, _, body_id, closure_args_span, _) => { + let closure_body = cx.tcx.hir().body(body_id); + let closure_expr = remove_blocks(&closure_body.value); + + if !Self::lint_closure_autofixable(cx, expr, args, closure_expr, closure_args_span) { + Self::lint_closure(cx, expr, closure_expr); + } + }, + // `_.and_then(Some)` case, which is no-op. + hir::ExprKind::Path(ref qpath) if match_qpath(qpath, Self::BAD_VARIANT_QPATH) => { + span_lint_and_sugg( + cx, + BIND_INSTEAD_OF_MAP, + expr.span, + Self::no_op_msg().as_ref(), + "use the expression directly", + snippet(cx, args[0].span, "..").into(), + Applicability::MachineApplicable, + ); + }, + _ => {}, + } + } +} + +/// returns `true` if expr contains match expr desugared from try +fn contains_try(expr: &hir::Expr<'_>) -> bool { + struct TryFinder { + found: bool, + } + + impl<'hir> intravisit::Visitor<'hir> for TryFinder { + type Map = Map<'hir>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { + intravisit::NestedVisitorMap::None + } + + fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { + if self.found { + return; + } + match expr.kind { + hir::ExprKind::Match(_, _, hir::MatchSource::TryDesugar) => self.found = true, + _ => intravisit::walk_expr(self, expr), + } + } + } + + let mut visitor = TryFinder { found: false }; + visitor.visit_expr(expr); + visitor.found +} + +fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_, '_>, expr: &'hir hir::Expr<'hir>, callback: F) -> bool +where + F: FnMut(&'hir hir::Expr<'hir>) -> bool, +{ + struct RetFinder<F> { + in_stmt: bool, + failed: bool, + cb: F, + } + + struct WithStmtGuarg<'a, F> { + val: &'a mut RetFinder<F>, + prev_in_stmt: bool, + } + + impl<F> RetFinder<F> { + fn inside_stmt(&mut self, in_stmt: bool) -> WithStmtGuarg<'_, F> { + let prev_in_stmt = std::mem::replace(&mut self.in_stmt, in_stmt); + WithStmtGuarg { + val: self, + prev_in_stmt, + } + } + } + + impl<F> std::ops::Deref for WithStmtGuarg<'_, F> { + type Target = RetFinder<F>; + + fn deref(&self) -> &Self::Target { + self.val + } + } + + impl<F> std::ops::DerefMut for WithStmtGuarg<'_, F> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.val + } + } + + impl<F> Drop for WithStmtGuarg<'_, F> { + fn drop(&mut self) { + self.val.in_stmt = self.prev_in_stmt; + } + } + + impl<'hir, F: FnMut(&'hir hir::Expr<'hir>) -> bool> intravisit::Visitor<'hir> for RetFinder<F> { + type Map = Map<'hir>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { + intravisit::NestedVisitorMap::None + } + + fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'_>) { + intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt) + } + + fn visit_expr(&mut self, expr: &'hir hir::Expr<'_>) { + if self.failed { + return; + } + if self.in_stmt { + match expr.kind { + hir::ExprKind::Ret(Some(expr)) => self.inside_stmt(false).visit_expr(expr), + _ => intravisit::walk_expr(self, expr), + } + } else { + match expr.kind { + hir::ExprKind::Match(cond, arms, _) => { + self.inside_stmt(true).visit_expr(cond); + for arm in arms { + self.visit_expr(arm.body); + } + }, + hir::ExprKind::Block(..) => intravisit::walk_expr(self, expr), + hir::ExprKind::Ret(Some(expr)) => self.visit_expr(expr), + _ => self.failed |= !(self.cb)(expr), + } + } + } + } + + !contains_try(expr) && { + let mut ret_finder = RetFinder { + in_stmt: false, + failed: false, + cb: callback, + }; + ret_finder.visit_expr(expr); + !ret_finder.failed + } +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index e6094edc5d7..626427c15ec 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1,3 +1,4 @@ +mod bind_instead_of_map; mod inefficient_to_string; mod manual_saturating_arithmetic; mod option_map_unwrap_or; @@ -7,6 +8,7 @@ use std::borrow::Cow; use std::fmt; use std::iter; +use bind_instead_of_map::BindInsteadOfMap; use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; @@ -306,27 +308,34 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Checks for usage of `_.and_then(|x| Some(y))`. + /// **What it does:** Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))` or + /// `_.or_else(|x| Err(y))`. /// /// **Why is this bad?** Readability, this can be written more concisely as - /// `_.map(|x| y)`. + /// `_.map(|x| y)` or `_.map_err(|x| y)`. /// /// **Known problems:** None /// /// **Example:** /// /// ```rust - /// let x = Some("foo"); - /// let _ = x.and_then(|s| Some(s.len())); + /// # fn opt() -> Option<&'static str> { Some("42") } + /// # fn res() -> Result<&'static str, &'static str> { Ok("42") } + /// let _ = opt().and_then(|s| Some(s.len())); + /// let _ = res().and_then(|s| if s.len() == 42 { Ok(10) } else { Ok(20) }); + /// let _ = res().or_else(|s| if s.len() == 42 { Err(10) } else { Err(20) }); /// ``` /// /// The correct use would be: /// /// ```rust - /// let x = Some("foo"); - /// let _ = x.map(|s| s.len()); + /// # fn opt() -> Option<&'static str> { Some("42") } + /// # fn res() -> Result<&'static str, &'static str> { Ok("42") } + /// let _ = opt().map(|s| s.len()); + /// let _ = res().map(|s| if s.len() == 42 { 10 } else { 20 }); + /// let _ = res().map_err(|s| if s.len() == 42 { 10 } else { 20 }); /// ``` - pub OPTION_AND_THEN_SOME, + pub BIND_INSTEAD_OF_MAP, complexity, "using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`" } @@ -1243,7 +1252,7 @@ declare_lint_pass!(Methods => [ MAP_UNWRAP_OR, RESULT_MAP_OR_INTO_OPTION, OPTION_MAP_OR_NONE, - OPTION_AND_THEN_SOME, + BIND_INSTEAD_OF_MAP, OR_FUN_CALL, EXPECT_FUN_CALL, CHARS_NEXT_CMP, @@ -1302,7 +1311,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { ["unwrap_or", "map"] => option_map_unwrap_or::lint(cx, expr, arg_lists[1], arg_lists[0], method_spans[1]), ["unwrap_or_else", "map"] => lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0]), ["map_or", ..] => lint_map_or_none(cx, expr, arg_lists[0]), - ["and_then", ..] => lint_option_and_then_some(cx, expr, arg_lists[0]), + ["and_then", ..] => { + bind_instead_of_map::OptionAndThenSome::lint(cx, expr, arg_lists[0]); + bind_instead_of_map::ResultAndThenOk::lint(cx, expr, arg_lists[0]); + }, + ["or_else", ..] => { + bind_instead_of_map::ResultOrElseErrInfo::lint(cx, expr, arg_lists[0]); + }, ["next", "filter"] => lint_filter_next(cx, expr, arg_lists[1]), ["next", "skip_while"] => lint_skip_while_next(cx, expr, arg_lists[1]), ["map", "filter"] => lint_filter_map(cx, expr, arg_lists[1], arg_lists[0]), @@ -2601,73 +2616,6 @@ fn lint_map_or_none<'a, 'tcx>( ); } -/// Lint use of `_.and_then(|x| Some(y))` for `Option`s -fn lint_option_and_then_some(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { - const LINT_MSG: &str = "using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`"; - const NO_OP_MSG: &str = "using `Option.and_then(Some)`, which is a no-op"; - - let ty = cx.tables.expr_ty(&args[0]); - if !is_type_diagnostic_item(cx, ty, sym!(option_type)) { - return; - } - - match args[1].kind { - hir::ExprKind::Closure(_, _, body_id, closure_args_span, _) => { - let closure_body = cx.tcx.hir().body(body_id); - let closure_expr = remove_blocks(&closure_body.value); - if_chain! { - if let hir::ExprKind::Call(ref some_expr, ref some_args) = closure_expr.kind; - if let hir::ExprKind::Path(ref qpath) = some_expr.kind; - if match_qpath(qpath, &paths::OPTION_SOME); - if some_args.len() == 1; - then { - let inner_expr = &some_args[0]; - - if contains_return(inner_expr) { - return; - } - - let some_inner_snip = if inner_expr.span.from_expansion() { - snippet_with_macro_callsite(cx, inner_expr.span, "_") - } else { - snippet(cx, inner_expr.span, "_") - }; - - let closure_args_snip = snippet(cx, closure_args_span, ".."); - let option_snip = snippet(cx, args[0].span, ".."); - let note = format!("{}.map({} {})", option_snip, closure_args_snip, some_inner_snip); - span_lint_and_sugg( - cx, - OPTION_AND_THEN_SOME, - expr.span, - LINT_MSG, - "try this", - note, - Applicability::MachineApplicable, - ); - } - } - }, - // `_.and_then(Some)` case, which is no-op. - hir::ExprKind::Path(ref qpath) => { - if match_qpath(qpath, &paths::OPTION_SOME) { - let option_snip = snippet(cx, args[0].span, ".."); - let note = format!("{}", option_snip); - span_lint_and_sugg( - cx, - OPTION_AND_THEN_SOME, - expr.span, - NO_OP_MSG, - "use the expression directly", - note, - Applicability::MachineApplicable, - ); - } - }, - _ => {}, - } -} - /// lint use of `filter().next()` for `Iterators` fn lint_filter_next<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f50adbc48ab..6ed9ff22e46 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -2230,7 +2230,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { ); if !vis.suggestions.is_empty() { - multispan_sugg(diag, "...and use generic constructor".into(), vis.suggestions); + multispan_sugg(diag, "...and use generic constructor", vis.suggestions); } } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index e5e3bf453a0..5b4e2906b5f 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -66,6 +66,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "bit_mask", }, + Lint { + name: "bind_instead_of_map", + group: "complexity", + desc: "using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`", + deprecation: None, + module: "methods", + }, Lint { name: "blacklisted_name", group: "style", @@ -1578,13 +1585,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "eq_op", }, - Lint { - name: "option_and_then_some", - group: "complexity", - desc: "using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`", - deprecation: None, - module: "methods", - }, Lint { name: "option_as_ref_deref", group: "complexity", diff --git a/tests/ui/option_and_then_some.fixed b/tests/ui/bind_instead_of_map.fixed similarity index 90% rename from tests/ui/option_and_then_some.fixed rename to tests/ui/bind_instead_of_map.fixed index 035bc1e5465..5815550d7a6 100644 --- a/tests/ui/option_and_then_some.fixed +++ b/tests/ui/bind_instead_of_map.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![deny(clippy::option_and_then_some)] +#![deny(clippy::bind_instead_of_map)] // need a main anyway, use it get rid of unused warnings too pub fn main() { @@ -12,7 +12,7 @@ pub fn main() { // Different type let x: Result<u32, &str> = Ok(1); - let _ = x.and_then(Ok); + let _ = x; } pub fn foo() -> Option<String> { diff --git a/tests/ui/option_and_then_some.rs b/tests/ui/bind_instead_of_map.rs similarity index 94% rename from tests/ui/option_and_then_some.rs rename to tests/ui/bind_instead_of_map.rs index d49da7813c6..623b100a4ce 100644 --- a/tests/ui/option_and_then_some.rs +++ b/tests/ui/bind_instead_of_map.rs @@ -1,5 +1,5 @@ // run-rustfix -#![deny(clippy::option_and_then_some)] +#![deny(clippy::bind_instead_of_map)] // need a main anyway, use it get rid of unused warnings too pub fn main() { diff --git a/tests/ui/option_and_then_some.stderr b/tests/ui/bind_instead_of_map.stderr similarity index 50% rename from tests/ui/option_and_then_some.stderr rename to tests/ui/bind_instead_of_map.stderr index 47825491765..24c6b7f9ef3 100644 --- a/tests/ui/option_and_then_some.stderr +++ b/tests/ui/bind_instead_of_map.stderr @@ -1,20 +1,26 @@ error: using `Option.and_then(Some)`, which is a no-op - --> $DIR/option_and_then_some.rs:8:13 + --> $DIR/bind_instead_of_map.rs:8:13 | LL | let _ = x.and_then(Some); | ^^^^^^^^^^^^^^^^ help: use the expression directly: `x` | note: the lint level is defined here - --> $DIR/option_and_then_some.rs:2:9 + --> $DIR/bind_instead_of_map.rs:2:9 | -LL | #![deny(clippy::option_and_then_some)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(clippy::bind_instead_of_map)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)` - --> $DIR/option_and_then_some.rs:9:13 + --> $DIR/bind_instead_of_map.rs:9:13 | LL | let _ = x.and_then(|o| Some(o + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.map(|o| o + 1)` -error: aborting due to 2 previous errors +error: using `Result.and_then(Ok)`, which is a no-op + --> $DIR/bind_instead_of_map.rs:15:13 + | +LL | let _ = x.and_then(Ok); + | ^^^^^^^^^^^^^^ help: use the expression directly: `x` + +error: aborting due to 3 previous errors diff --git a/tests/ui/bind_instead_of_map_multipart.rs b/tests/ui/bind_instead_of_map_multipart.rs new file mode 100644 index 00000000000..91d9d11e3c1 --- /dev/null +++ b/tests/ui/bind_instead_of_map_multipart.rs @@ -0,0 +1,61 @@ +#![deny(clippy::bind_instead_of_map)] +#![allow(clippy::blocks_in_if_conditions)] + +pub fn main() { + let _ = Some("42").and_then(|s| if s.len() < 42 { Some(0) } else { Some(s.len()) }); + let _ = Some("42").and_then(|s| if s.len() < 42 { None } else { Some(s.len()) }); + + let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Ok(0) } else { Ok(s.len()) }); + let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Err(()) } else { Ok(s.len()) }); + + let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Err(s.len() + 20) } else { Err(s.len()) }); + let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Ok(()) } else { Err(s.len()) }); + + hard_example(); + macro_example(); +} + +fn hard_example() { + Some("42").and_then(|s| { + if { + if s == "43" { + return Some(43); + } + s == "42" + } { + return Some(45); + } + match s.len() { + 10 => Some(2), + 20 => { + if foo() { + return { + if foo() { + return Some(20); + } + println!("foo"); + Some(3) + }; + } + Some(20) + }, + 40 => Some(30), + _ => Some(1), + } + }); +} + +fn foo() -> bool { + true +} + +macro_rules! m { + () => { + Some(10) + }; +} + +fn macro_example() { + let _ = Some("").and_then(|s| if s.len() == 20 { m!() } else { Some(20) }); + let _ = Some("").and_then(|s| if s.len() == 20 { Some(m!()) } else { Some(Some(20)) }); +} diff --git a/tests/ui/bind_instead_of_map_multipart.stderr b/tests/ui/bind_instead_of_map_multipart.stderr new file mode 100644 index 00000000000..50ce2f4051e --- /dev/null +++ b/tests/ui/bind_instead_of_map_multipart.stderr @@ -0,0 +1,73 @@ +error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)` + --> $DIR/bind_instead_of_map_multipart.rs:5:13 + | +LL | let _ = Some("42").and_then(|s| if s.len() < 42 { Some(0) } else { Some(s.len()) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/bind_instead_of_map_multipart.rs:1:9 + | +LL | #![deny(clippy::bind_instead_of_map)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try this + | +LL | let _ = Some("42").map(|s| if s.len() < 42 { 0 } else { s.len() }); + | ^^^ ^ ^^^^^^^ + +error: using `Result.and_then(|x| Ok(y))`, which is more succinctly expressed as `map(|x| y)` + --> $DIR/bind_instead_of_map_multipart.rs:8:13 + | +LL | let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Ok(0) } else { Ok(s.len()) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | let _ = Ok::<_, ()>("42").map(|s| if s.len() < 42 { 0 } else { s.len() }); + | ^^^ ^ ^^^^^^^ + +error: using `Result.or_else(|x| Err(y))`, which is more succinctly expressed as `map_err(|x| y)` + --> $DIR/bind_instead_of_map_multipart.rs:11:13 + | +LL | let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Err(s.len() + 20) } else { Err(s.len()) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | let _ = Err::<(), _>("42").map_err(|s| if s.len() < 42 { s.len() + 20 } else { s.len() }); + | ^^^^^^^ ^^^^^^^^^^^^ ^^^^^^^ + +error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)` + --> $DIR/bind_instead_of_map_multipart.rs:19:5 + | +LL | / Some("42").and_then(|s| { +LL | | if { +LL | | if s == "43" { +LL | | return Some(43); +... | +LL | | } +LL | | }); + | |______^ + | +help: try this + | +LL | Some("42").map(|s| { +LL | if { +LL | if s == "43" { +LL | return 43; +LL | } +LL | s == "42" + ... + +error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)` + --> $DIR/bind_instead_of_map_multipart.rs:60:13 + | +LL | let _ = Some("").and_then(|s| if s.len() == 20 { Some(m!()) } else { Some(Some(20)) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | let _ = Some("").map(|s| if s.len() == 20 { m!() } else { Some(20) }); + | ^^^ ^^^^ ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/blocks_in_if_conditions.fixed b/tests/ui/blocks_in_if_conditions.fixed index 9040552cefc..14562c4d32c 100644 --- a/tests/ui/blocks_in_if_conditions.fixed +++ b/tests/ui/blocks_in_if_conditions.fixed @@ -63,10 +63,10 @@ fn block_in_assert() { let opt = Some(42); assert!(opt .as_ref() - .and_then(|val| { + .map(|val| { let mut v = val * 2; v -= 1; - Some(v * 3) + v * 3 }) .is_some()); } diff --git a/tests/ui/blocks_in_if_conditions.rs b/tests/ui/blocks_in_if_conditions.rs index 2fe409b22d3..bda87650f6d 100644 --- a/tests/ui/blocks_in_if_conditions.rs +++ b/tests/ui/blocks_in_if_conditions.rs @@ -63,10 +63,10 @@ fn block_in_assert() { let opt = Some(42); assert!(opt .as_ref() - .and_then(|val| { + .map(|val| { let mut v = val * 2; v -= 1; - Some(v * 3) + v * 3 }) .is_some()); } diff --git a/tests/ui/option_map_or_none.fixed b/tests/ui/option_map_or_none.fixed index decbae4e5af..d80c3c7c1b7 100644 --- a/tests/ui/option_map_or_none.fixed +++ b/tests/ui/option_map_or_none.fixed @@ -1,6 +1,6 @@ // run-rustfix -#![allow(clippy::option_and_then_some)] +#![allow(clippy::bind_instead_of_map)] fn main() { let opt = Some(1); diff --git a/tests/ui/option_map_or_none.rs b/tests/ui/option_map_or_none.rs index 0f1d2218d5d..629842419e5 100644 --- a/tests/ui/option_map_or_none.rs +++ b/tests/ui/option_map_or_none.rs @@ -1,6 +1,6 @@ // run-rustfix -#![allow(clippy::option_and_then_some)] +#![allow(clippy::bind_instead_of_map)] fn main() { let opt = Some(1); From 1b3dc5f79b98ba92c0b6fa98e62c8f331faa8ed6 Mon Sep 17 00:00:00 2001 From: Rahul Butani <rr.butani@gmail.com> Date: Sun, 17 May 2020 22:21:02 -0500 Subject: [PATCH 079/526] Add to the list of words clippy::doc_markdown ignores --- clippy_lints/src/utils/conf.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 57b9eafd14d..9e8e0ff30ec 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -120,10 +120,12 @@ define_Conf! { "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", - "JavaScript", + "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", - "OpenGL", "OpenSSH", "OpenSSL", "OpenStreetMap", + "OCaml", + "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", + "TensorFlow", "TrueType", "iOS", "macOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", From 842dd072612a5a53bef37f242f8f2be8896902cc Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 19 May 2020 15:18:16 +0200 Subject: [PATCH 080/526] Add note that a subtree fix and stack limit increase is required --- CONTRIBUTING.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6697ff2f40d..c6a3998ec4e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -209,6 +209,13 @@ You can then sync with the remote names from above, e.g.: $ git subtree push -P src/tools/clippy clippy-local sync-from-rust ``` +_Note:_ The first time running `git subtree push` a cache has to be built. This +involves going through the complete Clippy history once. For this you have to +increase the stack limit though, which you can do with `ulimit -s 60000`. For +this to work, you will need the fix of `git subtree` available +[here][gitgitgadget-pr]. + +[gitgitgadget-pr]: https://github.com/gitgitgadget/git/pull/493 [subtree]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#external-dependencies-subtree [`rust-lang/rust`]: https://github.com/rust-lang/rust From 1a9ba3b2c208f8131587ece3ad8fb159336dd694 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 19 May 2020 16:36:14 +0200 Subject: [PATCH 081/526] Add note, that a merge commit after push is necessary --- CONTRIBUTING.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c6a3998ec4e..c9180e58fc2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -178,6 +178,15 @@ to be run inside the `rust` directory): _Note:_ This will directly push to the remote repository. You can also push to your local copy by replacing the remote address with `/path/to/rust-clippy` directory. + + _Note:_ Most of the time you have to create a merge commit in the + `rust-clippy` repo (this has to be done in the Clippy repo, not in the + rust-copy of Clippy): + ```bash + git checkout sync-from-rust + git fetch upstream + git merge upstream/master + ``` 3. Open a PR to `rust-lang/rust-clippy` and wait for it to get merged (to accelerate the process ping the `@rust-lang/clippy` team in your PR and/or ~~annoy~~ ask them in the [Discord] channel.) From da9b138ec7645d483112c6b20e91ab595326c41d Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 19 May 2020 16:12:03 +0200 Subject: [PATCH 082/526] Update test after const_ptr functions are must_use now --- tests/ui/ptr_offset_with_cast.fixed | 12 ++++++------ tests/ui/ptr_offset_with_cast.rs | 12 ++++++------ tests/ui/ptr_offset_with_cast.stderr | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/ui/ptr_offset_with_cast.fixed b/tests/ui/ptr_offset_with_cast.fixed index ebdd6c4003d..718e391e8bf 100644 --- a/tests/ui/ptr_offset_with_cast.fixed +++ b/tests/ui/ptr_offset_with_cast.fixed @@ -9,12 +9,12 @@ fn main() { let offset_isize = 1_isize; unsafe { - ptr.add(offset_usize); - ptr.offset(offset_isize as isize); - ptr.offset(offset_u8 as isize); + let _ = ptr.add(offset_usize); + let _ = ptr.offset(offset_isize as isize); + let _ = ptr.offset(offset_u8 as isize); - ptr.wrapping_add(offset_usize); - ptr.wrapping_offset(offset_isize as isize); - ptr.wrapping_offset(offset_u8 as isize); + let _ = ptr.wrapping_add(offset_usize); + let _ = ptr.wrapping_offset(offset_isize as isize); + let _ = ptr.wrapping_offset(offset_u8 as isize); } } diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index 3416c4b727a..f613742c741 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -9,12 +9,12 @@ fn main() { let offset_isize = 1_isize; unsafe { - ptr.offset(offset_usize as isize); - ptr.offset(offset_isize as isize); - ptr.offset(offset_u8 as isize); + let _ = ptr.offset(offset_usize as isize); + let _ = ptr.offset(offset_isize as isize); + let _ = ptr.offset(offset_u8 as isize); - ptr.wrapping_offset(offset_usize as isize); - ptr.wrapping_offset(offset_isize as isize); - ptr.wrapping_offset(offset_u8 as isize); + let _ = ptr.wrapping_offset(offset_usize as isize); + let _ = ptr.wrapping_offset(offset_isize as isize); + let _ = ptr.wrapping_offset(offset_u8 as isize); } } diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr index b5c7a03e277..fd45224ca06 100644 --- a/tests/ui/ptr_offset_with_cast.stderr +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -1,16 +1,16 @@ error: use of `offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:12:9 + --> $DIR/ptr_offset_with_cast.rs:12:17 | -LL | ptr.offset(offset_usize as isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)` +LL | let _ = ptr.offset(offset_usize as isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)` | = note: `-D clippy::ptr-offset-with-cast` implied by `-D warnings` error: use of `wrapping_offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:16:9 + --> $DIR/ptr_offset_with_cast.rs:16:17 | -LL | ptr.wrapping_offset(offset_usize as isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)` +LL | let _ = ptr.wrapping_offset(offset_usize as isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)` error: aborting due to 2 previous errors From f28f1f15da825bcf5cf78413f464dfea0bc553e5 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Wed, 20 May 2020 13:32:53 +0200 Subject: [PATCH 083/526] Fix dogfood fallout --- clippy_lints/src/utils/inspector.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 748c11fac64..9b672b9ec22 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -289,21 +289,21 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, indent: usize) { println!("{}operands:", ind); for op in asm.operands { match op { - hir::InlineAsmOperand::In { expr, .. } => print_expr(cx, expr, indent + 1), + hir::InlineAsmOperand::In { expr, .. } + | hir::InlineAsmOperand::InOut { expr, .. } + | hir::InlineAsmOperand::Const { expr } + | hir::InlineAsmOperand::Sym { expr } => print_expr(cx, expr, indent + 1), hir::InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { print_expr(cx, expr, indent + 1); } }, - hir::InlineAsmOperand::InOut { expr, .. } => print_expr(cx, expr, indent + 1), hir::InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { print_expr(cx, in_expr, indent + 1); if let Some(out_expr) = out_expr { print_expr(cx, out_expr, indent + 1); } }, - hir::InlineAsmOperand::Const { expr } => print_expr(cx, expr, indent + 1), - hir::InlineAsmOperand::Sym { expr } => print_expr(cx, expr, indent + 1), } } }, From ecd0a67b01e13d7a80d2f64bbfa5da1e568367e5 Mon Sep 17 00:00:00 2001 From: Elichai Turkel <elichai.turkel@gmail.com> Date: Wed, 20 May 2020 13:23:51 +0300 Subject: [PATCH 084/526] Make match_wild_err_arm pedantic, and update help messages --- clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/matches.rs | 6 +++--- src/lintlist/mod.rs | 2 +- tests/ui/match_wild_err_arm.stderr | 8 ++++---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4d4fff883b3..057d39d4c82 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1141,6 +1141,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), LintId::of(&matches::MATCH_BOOL), LintId::of(&matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS), + LintId::of(&matches::MATCH_WILD_ERR_ARM), LintId::of(&matches::SINGLE_MATCH_ELSE), LintId::of(&methods::FILTER_MAP), LintId::of(&methods::FILTER_MAP_NEXT), @@ -1285,7 +1286,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&matches::MATCH_OVERLAPPING_ARM), LintId::of(&matches::MATCH_REF_PATS), LintId::of(&matches::MATCH_SINGLE_BINDING), - LintId::of(&matches::MATCH_WILD_ERR_ARM), LintId::of(&matches::SINGLE_MATCH), LintId::of(&matches::WILDCARD_IN_OR_PATTERNS), LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), @@ -1476,7 +1476,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), LintId::of(&matches::MATCH_OVERLAPPING_ARM), LintId::of(&matches::MATCH_REF_PATS), - LintId::of(&matches::MATCH_WILD_ERR_ARM), LintId::of(&matches::SINGLE_MATCH), LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE), LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT), diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 4106e5013b9..94380acfcfd 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -168,7 +168,7 @@ declare_clippy_lint! { /// **What it does:** Checks for arm which matches all errors with `Err(_)` /// and take drastic actions like `panic!`. /// - /// **Why is this bad?** It is generally a bad practice, just like + /// **Why is this bad?** It is generally a bad practice, similar to /// catching all exceptions in java with `catch(Exception)` /// /// **Known problems:** None. @@ -182,7 +182,7 @@ declare_clippy_lint! { /// } /// ``` pub MATCH_WILD_ERR_ARM, - style, + pedantic, "a `match` with `Err(_)` arm and take drastic actions" } @@ -711,7 +711,7 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) arm.pat.span, &format!("`Err({})` matches all errors", &ident_bind_name), None, - "match each error separately or use the error output", + "match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable", ); } } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 0bf46491d31..8211a57b564 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1195,7 +1195,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ }, Lint { name: "match_wild_err_arm", - group: "style", + group: "pedantic", desc: "a `match` with `Err(_)` arm and take drastic actions", deprecation: None, module: "matches", diff --git a/tests/ui/match_wild_err_arm.stderr b/tests/ui/match_wild_err_arm.stderr index 20d4c933418..6a2a02987de 100644 --- a/tests/ui/match_wild_err_arm.stderr +++ b/tests/ui/match_wild_err_arm.stderr @@ -5,7 +5,7 @@ LL | Err(_) => panic!("err"), | ^^^^^^ | = note: `-D clippy::match-wild-err-arm` implied by `-D warnings` - = note: match each error separately or use the error output + = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable error: `Err(_)` matches all errors --> $DIR/match_wild_err_arm.rs:17:9 @@ -13,7 +13,7 @@ error: `Err(_)` matches all errors LL | Err(_) => panic!(), | ^^^^^^ | - = note: match each error separately or use the error output + = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable error: `Err(_)` matches all errors --> $DIR/match_wild_err_arm.rs:23:9 @@ -21,7 +21,7 @@ error: `Err(_)` matches all errors LL | Err(_) => { | ^^^^^^ | - = note: match each error separately or use the error output + = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable error: `Err(_e)` matches all errors --> $DIR/match_wild_err_arm.rs:31:9 @@ -29,7 +29,7 @@ error: `Err(_e)` matches all errors LL | Err(_e) => panic!(), | ^^^^^^^ | - = note: match each error separately or use the error output + = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable error: aborting due to 4 previous errors From 2db7f1abf84699605a5863887484cbf587db3eb1 Mon Sep 17 00:00:00 2001 From: Elichai Turkel <elichai.turkel@gmail.com> Date: Wed, 20 May 2020 16:46:30 +0300 Subject: [PATCH 085/526] Update future-not-send stderr output --- tests/ui/future_not_send.stderr | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/tests/ui/future_not_send.stderr b/tests/ui/future_not_send.stderr index d1863701bfe..b59dbb3e76c 100644 --- a/tests/ui/future_not_send.stderr +++ b/tests/ui/future_not_send.stderr @@ -47,17 +47,32 @@ error: future cannot be sent between threads safely --> $DIR/future_not_send.rs:20:63 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { - | ^^^^ + | ^^^^ future returned by `private_future2` is not `Send` | +note: captured value is not `Send` + --> $DIR/future_not_send.rs:20:26 + | +LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { + | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` +note: captured value is not `Send` + --> $DIR/future_not_send.rs:20:40 + | +LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { + | ^^^^ has type `&std::cell::Cell<usize>` which is not `Send` = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely --> $DIR/future_not_send.rs:24:43 | LL | pub async fn public_future2(rc: Rc<[u8]>) {} - | ^ + | ^ future returned by `public_future2` is not `Send` | +note: captured value is not `Send` + --> $DIR/future_not_send.rs:24:29 + | +LL | pub async fn public_future2(rc: Rc<[u8]>) {} + | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely @@ -117,8 +132,13 @@ error: future cannot be sent between threads safely --> $DIR/future_not_send.rs:66:34 | LL | async fn unclear_future<T>(t: T) {} - | ^ + | ^ future returned by `unclear_future` is not `Send` | +note: captured value is not `Send` + --> $DIR/future_not_send.rs:66:28 + | +LL | async fn unclear_future<T>(t: T) {} + | ^ has type `T` which is not `Send` = note: `T` doesn't implement `std::marker::Send` error: aborting due to 8 previous errors From bd9b09e29396697874f63d82926b36fa154caa1f Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 18 May 2020 20:54:09 +0200 Subject: [PATCH 086/526] Adapt compile-test to run tests for cargo lints --- tests/compile-test.rs | 150 ++++++++++++++++++------ tests/ui-cargo/update-all-references.sh | 18 +++ tests/ui-cargo/update-references.sh | 38 ++++++ 3 files changed, 169 insertions(+), 37 deletions(-) create mode 100755 tests/ui-cargo/update-all-references.sh create mode 100755 tests/ui-cargo/update-references.sh diff --git a/tests/compile-test.rs b/tests/compile-test.rs index a3df9d5ccbd..91b9c73c9d4 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -101,49 +101,124 @@ fn run_mode(cfg: &mut compiletest::Config) { compiletest::run_tests(&cfg); } -#[allow(clippy::identity_conversion)] -fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<tester::TestDescAndFn>) -> Result<bool, io::Error> { - let mut result = true; - let opts = compiletest::test_opts(config); - for dir in fs::read_dir(&config.src_base)? { - let dir = dir?; - if !dir.file_type()?.is_dir() { - continue; - } - let dir_path = dir.path(); - set_var("CARGO_MANIFEST_DIR", &dir_path); - for file in fs::read_dir(&dir_path)? { - let file = file?; - let file_path = file.path(); - if file.file_type()?.is_dir() { - continue; - } - if file_path.extension() != Some(OsStr::new("rs")) { - continue; - } - let paths = compiletest::common::TestPaths { - file: file_path, - base: config.src_base.clone(), - relative_dir: dir_path.file_name().unwrap().into(), - }; - let test_name = compiletest::make_test_name(&config, &paths); - let index = tests - .iter() - .position(|test| test.desc.name == test_name) - .expect("The test should be in there"); - result &= tester::run_tests_console(&opts, vec![tests.swap_remove(index)])?; - } - } - Ok(result) -} - fn run_ui_toml(config: &mut compiletest::Config) { + fn run_tests(config: &compiletest::Config, mut tests: Vec<tester::TestDescAndFn>) -> Result<bool, io::Error> { + let mut result = true; + let opts = compiletest::test_opts(config); + for dir in fs::read_dir(&config.src_base)? { + let dir = dir?; + if !dir.file_type()?.is_dir() { + continue; + } + let dir_path = dir.path(); + set_var("CARGO_MANIFEST_DIR", &dir_path); + for file in fs::read_dir(&dir_path)? { + let file = file?; + let file_path = file.path(); + if file.file_type()?.is_dir() { + continue; + } + if file_path.extension() != Some(OsStr::new("rs")) { + continue; + } + let paths = compiletest::common::TestPaths { + file: file_path, + base: config.src_base.clone(), + relative_dir: dir_path.file_name().unwrap().into(), + }; + let test_name = compiletest::make_test_name(&config, &paths); + let index = tests + .iter() + .position(|test| test.desc.name == test_name) + .expect("The test should be in there"); + result &= tester::run_tests_console(&opts, vec![tests.swap_remove(index)])?; + } + } + Ok(result) + } + config.mode = TestMode::Ui; config.src_base = Path::new("tests").join("ui-toml").canonicalize().unwrap(); let tests = compiletest::make_tests(&config); - let res = run_ui_toml_tests(&config, tests); + let res = run_tests(&config, tests); + match res { + Ok(true) => {}, + Ok(false) => panic!("Some tests failed"), + Err(e) => { + println!("I/O failure during tests: {:?}", e); + }, + } +} + +fn run_ui_cargo(config: &mut compiletest::Config) { + fn run_tests( + config: &compiletest::Config, + filter: &Option<String>, + mut tests: Vec<tester::TestDescAndFn>, + ) -> Result<bool, io::Error> { + let mut result = true; + let opts = compiletest::test_opts(config); + + for dir in fs::read_dir(&config.src_base)? { + let dir = dir?; + if !dir.file_type()?.is_dir() { + continue; + } + + // Use the filter if provided + let dir_path = dir.path(); + match &filter { + Some(name) if !dir_path.ends_with(name) => continue, + _ => {}, + } + + for case in &["pass", "fail"] { + let tail: PathBuf = [case, "src"].iter().collect(); + let src_path = dir_path.join(tail); + env::set_current_dir(&src_path)?; + + for file in fs::read_dir(&src_path)? { + let file = file?; + if file.file_type()?.is_dir() { + continue; + } + + // Search for the main file to avoid running a test for each file in the project + let file_path = file.path(); + match file_path.file_name().and_then(OsStr::to_str) { + Some("main.rs") => {}, + _ => continue, + } + + let paths = compiletest::common::TestPaths { + file: file_path, + base: config.src_base.clone(), + relative_dir: src_path.strip_prefix(&config.src_base).unwrap().into(), + }; + let test_name = compiletest::make_test_name(&config, &paths); + let index = tests + .iter() + .position(|test| test.desc.name == test_name) + .expect("The test should be in there"); + result &= tester::run_tests_console(&opts, vec![tests.swap_remove(index)])?; + } + } + } + Ok(result) + } + + config.mode = TestMode::Ui; + config.src_base = Path::new("tests").join("ui-cargo").canonicalize().unwrap(); + + let tests = compiletest::make_tests(&config); + + let current_dir = env::current_dir().unwrap(); + let filter = env::var("TESTNAME").ok(); + let res = run_tests(&config, &filter, tests); + env::set_current_dir(current_dir).unwrap(); + match res { Ok(true) => {}, Ok(false) => panic!("Some tests failed"), @@ -165,4 +240,5 @@ fn compile_test() { let mut config = default_config(); run_mode(&mut config); run_ui_toml(&mut config); + run_ui_cargo(&mut config); } diff --git a/tests/ui-cargo/update-all-references.sh b/tests/ui-cargo/update-all-references.sh new file mode 100755 index 00000000000..7028b251ea0 --- /dev/null +++ b/tests/ui-cargo/update-all-references.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# A script to update the references for all tests. The idea is that +# you do a run, which will generate files in the build directory +# containing the (normalized) actual output of the compiler. You then +# run this script, which will copy those files over. If you find +# yourself manually editing a foo.stderr file, you're doing it wrong. +# +# See all `update-references.sh`, if you just want to update a single test. + +if [[ "$1" == "--help" || "$1" == "-h" ]]; then + echo "usage: $0" +fi + +BUILD_DIR=$PWD/target/debug/test_build_base +MY_DIR=$(dirname "$0") +cd "$MY_DIR" || exit +find . -name '*.rs' -exec ./update-references.sh "$BUILD_DIR" {} + diff --git a/tests/ui-cargo/update-references.sh b/tests/ui-cargo/update-references.sh new file mode 100755 index 00000000000..50d42678734 --- /dev/null +++ b/tests/ui-cargo/update-references.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# A script to update the references for particular tests. The idea is +# that you do a run, which will generate files in the build directory +# containing the (normalized) actual output of the compiler. This +# script will then copy that output and replace the "expected output" +# files. You can then commit the changes. +# +# If you find yourself manually editing a foo.stderr file, you're +# doing it wrong. + +if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then + echo "usage: $0 <build-directory> <relative-path-to-rs-files>" + echo "" + echo "For example:" + echo " $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs" +fi + +MYDIR=$(dirname "$0") + +BUILD_DIR="$1" +shift + +while [[ "$1" != "" ]]; do + STDERR_NAME="${1/%.rs/.stderr}" + STDOUT_NAME="${1/%.rs/.stdout}" + shift + if [[ -f "$BUILD_DIR"/"$STDOUT_NAME" ]] && \ + ! (cmp -s -- "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"); then + echo updating "$MYDIR"/"$STDOUT_NAME" + cp "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME" + fi + if [[ -f "$BUILD_DIR"/"$STDERR_NAME" ]] && \ + ! (cmp -s -- "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"); then + echo updating "$MYDIR"/"$STDERR_NAME" + cp "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME" + fi +done From 96af3e83601a6cd37544e70a7a816c36cc9871f5 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 18 May 2020 20:55:12 +0200 Subject: [PATCH 087/526] Add test for wildcard_dependencies --- tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml | 6 ++++++ tests/ui-cargo/wildcard_dependencies/fail/src/main.rs | 3 +++ tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr | 6 ++++++ tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml | 6 ++++++ tests/ui-cargo/wildcard_dependencies/pass/src/main.rs | 3 +++ 5 files changed, 24 insertions(+) create mode 100644 tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml create mode 100644 tests/ui-cargo/wildcard_dependencies/fail/src/main.rs create mode 100644 tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr create mode 100644 tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml create mode 100644 tests/ui-cargo/wildcard_dependencies/pass/src/main.rs diff --git a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml new file mode 100644 index 00000000000..9558dd68091 --- /dev/null +++ b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "wildcard_dependencies" +version = "0.1.0" + +[dependencies] +regex = "*" diff --git a/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs b/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs new file mode 100644 index 00000000000..3491ccb0d47 --- /dev/null +++ b/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs @@ -0,0 +1,3 @@ +#![warn(clippy::wildcard_dependencies)] + +fn main() {} diff --git a/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr b/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr new file mode 100644 index 00000000000..9e65d2f9942 --- /dev/null +++ b/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr @@ -0,0 +1,6 @@ +error: wildcard dependency for `regex` + | + = note: `-D clippy::wildcard-dependencies` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml b/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml new file mode 100644 index 00000000000..062e441622a --- /dev/null +++ b/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "wildcard_dependencies" +version = "0.1.0" + +[dependencies] +regex = "1" diff --git a/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs b/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs new file mode 100644 index 00000000000..3491ccb0d47 --- /dev/null +++ b/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs @@ -0,0 +1,3 @@ +#![warn(clippy::wildcard_dependencies)] + +fn main() {} From bc93f7052e4a76d62e2aa5f11649e662cb46c7ce Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 18 May 2020 20:56:33 +0200 Subject: [PATCH 088/526] Add test for cargo_common_metadata Fix missing `authors` entry in the provided example --- clippy_lints/src/cargo_common_metadata.rs | 1 + .../cargo_common_metadata/fail/Cargo.toml | 3 +++ .../cargo_common_metadata/fail/src/main.rs | 3 +++ .../cargo_common_metadata/fail/src/main.stderr | 18 ++++++++++++++++++ .../cargo_common_metadata/pass/Cargo.toml | 10 ++++++++++ .../cargo_common_metadata/pass/src/main.rs | 3 +++ 6 files changed, 38 insertions(+) create mode 100644 tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml create mode 100644 tests/ui-cargo/cargo_common_metadata/fail/src/main.rs create mode 100644 tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr create mode 100644 tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml create mode 100644 tests/ui-cargo/cargo_common_metadata/pass/src/main.rs diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index 782da249808..16b46423c8f 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -23,6 +23,7 @@ declare_clippy_lint! { /// [package] /// name = "clippy" /// version = "0.0.212" + /// authors = ["Someone <someone@rust-lang.org>"] /// description = "A bunch of helpful lints to avoid common pitfalls in Rust" /// repository = "https://github.com/rust-lang/rust-clippy" /// readme = "README.md" diff --git a/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml new file mode 100644 index 00000000000..8346bf05778 --- /dev/null +++ b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "cargo_common_metadata" +version = "0.1.0" diff --git a/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs b/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs new file mode 100644 index 00000000000..c67166fc4b0 --- /dev/null +++ b/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs @@ -0,0 +1,3 @@ +#![warn(clippy::cargo_common_metadata)] + +fn main() {} diff --git a/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr new file mode 100644 index 00000000000..c8ae6c820df --- /dev/null +++ b/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr @@ -0,0 +1,18 @@ +error: package `cargo_common_metadata` is missing `package.authors` metadata + | + = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` + +error: package `cargo_common_metadata` is missing `package.description` metadata + +error: package `cargo_common_metadata` is missing `either package.license or package.license_file` metadata + +error: package `cargo_common_metadata` is missing `package.repository` metadata + +error: package `cargo_common_metadata` is missing `package.readme` metadata + +error: package `cargo_common_metadata` is missing `package.keywords` metadata + +error: package `cargo_common_metadata` is missing `package.categories` metadata + +error: aborting due to 7 previous errors + diff --git a/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml new file mode 100644 index 00000000000..f99c126fabf --- /dev/null +++ b/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "cargo_common_metadata" +version = "0.1.0" +authors = ["Random person from the Internet <someone@someplace.org>"] +description = "A test package for the cargo_common_metadata lint" +repository = "https://github.com/someone/cargo_common_metadata" +readme = "README.md" +license = "MIT OR Apache-2.0" +keywords = ["metadata", "lint", "clippy"] +categories = ["development-tools::testing"] diff --git a/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs b/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs new file mode 100644 index 00000000000..c67166fc4b0 --- /dev/null +++ b/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs @@ -0,0 +1,3 @@ +#![warn(clippy::cargo_common_metadata)] + +fn main() {} From 7a0eccbd8a719af00b027b0ea85c576d9cbed750 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 18 May 2020 20:58:02 +0200 Subject: [PATCH 089/526] Add test for multiple_crate_versions Make the output of the lint deterministic by sorting the versions --- clippy_lints/src/multiple_crate_versions.rs | 4 +++- tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml | 7 +++++++ tests/ui-cargo/multiple_crate_versions/fail/src/main.rs | 3 +++ .../ui-cargo/multiple_crate_versions/fail/src/main.stderr | 6 ++++++ tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml | 7 +++++++ tests/ui-cargo/multiple_crate_versions/pass/src/main.rs | 3 +++ 6 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml create mode 100644 tests/ui-cargo/multiple_crate_versions/fail/src/main.rs create mode 100644 tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr create mode 100644 tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml create mode 100644 tests/ui-cargo/multiple_crate_versions/pass/src/main.rs diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index ed85d0315bd..c4decfc9401 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -54,7 +54,9 @@ impl LateLintPass<'_, '_> for MultipleCrateVersions { let group: Vec<cargo_metadata::Package> = group.collect(); if group.len() > 1 { - let versions = group.into_iter().map(|p| p.version).join(", "); + let mut versions: Vec<_> = group.into_iter().map(|p| p.version).collect(); + versions.sort(); + let versions = versions.iter().join(", "); span_lint( cx, diff --git a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml new file mode 100644 index 00000000000..05ffde839dc --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "multiple_crate_versions" +version = "0.1.0" + +[dependencies] +ctrlc = "=3.1.0" +ansi_term = "=0.11.0" diff --git a/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs b/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs new file mode 100644 index 00000000000..4bc61dd6299 --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs @@ -0,0 +1,3 @@ +#![warn(clippy::multiple_crate_versions)] + +fn main() {} diff --git a/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr b/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr new file mode 100644 index 00000000000..4f668599be9 --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr @@ -0,0 +1,6 @@ +error: multiple versions for dependency `winapi`: 0.2.8, 0.3.8 + | + = note: `-D clippy::multiple-crate-versions` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml new file mode 100644 index 00000000000..cad32b9233f --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cargo_common_metadata" +version = "0.1.0" + +[dependencies] +regex = "1.3.7" +serde = "1.0.110" diff --git a/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs b/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs new file mode 100644 index 00000000000..4bc61dd6299 --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs @@ -0,0 +1,3 @@ +#![warn(clippy::multiple_crate_versions)] + +fn main() {} From 1eb6adf47579e3c56b38ba6cce7676e8d2d5beb0 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 18 May 2020 21:03:37 +0200 Subject: [PATCH 090/526] Adapt `cargo dev new_lint` to create tests for cargo lints --- clippy_dev/src/new_lint.rs | 182 ++++++++++++++++++++++--------------- 1 file changed, 107 insertions(+), 75 deletions(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 44b2a5383d2..843beaf3238 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -1,91 +1,110 @@ use crate::clippy_project_root; -use std::fs::{File, OpenOptions}; -use std::io; +use std::fs::{self, OpenOptions}; use std::io::prelude::*; -use std::io::ErrorKind; -use std::path::Path; +use std::io::{self, ErrorKind}; +use std::path::{Path, PathBuf}; -/// Creates files required to implement and test a new lint and runs `update_lints`. -/// -/// # Errors -/// -/// This function errors, if the files couldn't be created -pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str>) -> Result<(), io::Error> { - let pass = pass.expect("`pass` argument is validated by clap"); - let lint_name = lint_name.expect("`name` argument is validated by clap"); - let category = category.expect("`category` argument is validated by clap"); +struct LintData<'a> { + pass: &'a str, + name: &'a str, + category: &'a str, + project_root: PathBuf, +} - match open_files(lint_name) { - Ok((mut test_file, mut lint_file)) => { - let (pass_type, pass_lifetimes, pass_import, context_import) = match pass { - "early" => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"), - "late" => ("LateLintPass", "<'_, '_>", "use rustc_hir::*;", "LateContext"), - _ => { - unreachable!("`pass_type` should only ever be `early` or `late`!"); - }, - }; +trait Context { + fn context<C: AsRef<str>>(self, text: C) -> Self; +} - let camel_case_name = to_camel_case(lint_name); - - if let Err(e) = test_file.write_all(get_test_file_contents(lint_name).as_bytes()) { - return Err(io::Error::new( - ErrorKind::Other, - format!("Could not write to test file: {}", e), - )); - }; - - if let Err(e) = lint_file.write_all( - get_lint_file_contents( - pass_type, - pass_lifetimes, - lint_name, - &camel_case_name, - category, - pass_import, - context_import, - ) - .as_bytes(), - ) { - return Err(io::Error::new( - ErrorKind::Other, - format!("Could not write to lint file: {}", e), - )); - } - Ok(()) - }, - Err(e) => Err(io::Error::new( - ErrorKind::Other, - format!("Unable to create lint: {}", e), - )), +impl<T> Context for io::Result<T> { + fn context<C: AsRef<str>>(self, text: C) -> Self { + match self { + Err(e) => { + let message = format!("{}: {}", text.as_ref(), e); + Err(io::Error::new(ErrorKind::Other, message)) + }, + ok => ok, + } } } -fn open_files(lint_name: &str) -> Result<(File, File), io::Error> { - let project_root = clippy_project_root(); +/// Creates the files required to implement and test a new lint and runs `update_lints`. +/// +/// # Errors +/// +/// This function errors out if the files couldn't be created or written to. +pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str>) -> io::Result<()> { + let lint = LintData { + pass: pass.expect("`pass` argument is validated by clap"), + name: lint_name.expect("`name` argument is validated by clap"), + category: category.expect("`category` argument is validated by clap"), + project_root: clippy_project_root(), + }; - let test_file_path = project_root.join("tests").join("ui").join(format!("{}.rs", lint_name)); - let lint_file_path = project_root - .join("clippy_lints") - .join("src") - .join(format!("{}.rs", lint_name)); + create_lint(&lint).context("Unable to create lint implementation")?; + create_test(&lint).context("Unable to create a test for the new lint") +} - if Path::new(&test_file_path).exists() { - return Err(io::Error::new( - ErrorKind::AlreadyExists, - format!("test file {:?} already exists", test_file_path), - )); - } - if Path::new(&lint_file_path).exists() { - return Err(io::Error::new( - ErrorKind::AlreadyExists, - format!("lint file {:?} already exists", lint_file_path), - )); +fn create_lint(lint: &LintData) -> io::Result<()> { + let (pass_type, pass_lifetimes, pass_import, context_import) = match lint.pass { + "early" => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"), + "late" => ("LateLintPass", "<'_, '_>", "use rustc_hir::*;", "LateContext"), + _ => { + unreachable!("`pass_type` should only ever be `early` or `late`!"); + }, + }; + + let camel_case_name = to_camel_case(lint.name); + let lint_contents = get_lint_file_contents( + pass_type, + pass_lifetimes, + lint.name, + &camel_case_name, + lint.category, + pass_import, + context_import, + ); + + let lint_path = format!("clippy_lints/src/{}.rs", lint.name); + write_file(lint.project_root.join(&lint_path), lint_contents.as_bytes()) +} + +fn create_test(lint: &LintData) -> io::Result<()> { + fn create_project_layout<P: Into<PathBuf>>(lint_name: &str, location: P, case: &str, hint: &str) -> io::Result<()> { + let mut path = location.into().join(case); + fs::create_dir(&path)?; + write_file(path.join("Cargo.toml"), get_manifest_contents(lint_name, hint))?; + + path.push("src"); + fs::create_dir(&path)?; + write_file(path.join("main.rs"), get_test_file_contents(lint_name))?; + + Ok(()) } - let test_file = OpenOptions::new().write(true).create_new(true).open(test_file_path)?; - let lint_file = OpenOptions::new().write(true).create_new(true).open(lint_file_path)?; + if lint.category == "cargo" { + let relative_test_dir = format!("tests/ui-cargo/{}", lint.name); + let test_dir = lint.project_root.join(relative_test_dir); + fs::create_dir(&test_dir)?; - Ok((test_file, lint_file)) + create_project_layout(lint.name, &test_dir, "fail", "Content that triggers the lint goes here")?; + create_project_layout(lint.name, &test_dir, "pass", "This file should not trigger the lint") + } else { + let test_path = format!("tests/ui/{}.rs", lint.name); + let test_contents = get_test_file_contents(lint.name); + write_file(lint.project_root.join(test_path), test_contents) + } +} + +fn write_file<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { + fn inner(path: &Path, contents: &[u8]) -> io::Result<()> { + OpenOptions::new() + .write(true) + .create_new(true) + .open(path)? + .write_all(contents) + } + + inner(path.as_ref(), contents.as_ref()).context(format!("writing to file: {}", path.as_ref().display())) } fn to_camel_case(name: &str) -> String { @@ -112,6 +131,19 @@ fn main() {{ ) } +fn get_manifest_contents(lint_name: &str, hint: &str) -> String { + format!( + r#" +# {} + +[package] +name = "{}" +version = "0.1.0" +"#, + hint, lint_name + ) +} + fn get_lint_file_contents( pass_type: &str, pass_lifetimes: &str, From 5d0135e222448e637ec1d66b3dd5c0805884dedd Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 18 May 2020 21:39:56 +0200 Subject: [PATCH 091/526] Add documentation for testing cargo lints --- doc/adding_lints.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 9ad1315c175..75768681db9 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -42,8 +42,10 @@ case), and we don't need type information so it will have an early pass type `cargo dev new_lint --name=foo_functions --pass=early --category=pedantic` (category will default to nursery if not provided). This command will create two files: `tests/ui/foo_functions.rs` and `clippy_lints/src/foo_functions.rs`, -as well as run `cargo dev update_lints` to register the new lint. Next, we'll -open up these files and add our lint! +as well as run `cargo dev update_lints` to register the new lint. For cargo lints, +two project hierarchies (fail/pass) will be created under `tests/ui-cargo`. + +Next, we'll open up these files and add our lint! ## Testing @@ -105,6 +107,19 @@ our lint, we need to commit the generated `.stderr` files, too. In general, you should only commit files changed by `tests/ui/update-all-references.sh` for the specific lint you are creating/editing. +### Cargo lints + +For cargo lints, the process of testing differs in that we are interested in +the contents of the `Cargo.toml` files. If our new lint is named e.g. `foo_categories`, +after running `cargo dev new_lint` we will find two new manifest files: + +* `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the new lint to raise an error. +* `tests/ui-cargo/foo_categories/pass/Cargo.toml`: this file should not trigger the lint. + +The process of generating the `.stderr` file is the same, and prepending the `TESTNAME` +variable to `cargo uitest` works too, but the script to update the references +is in another path: `tests/ui-cargo/update-all-references.sh`. + ## Rustfix tests If the lint you are working on is making use of structured suggestions, the From 7ff71199df911b462800cf6bda7ac32879ba7eb1 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 21 May 2020 14:46:04 +0200 Subject: [PATCH 092/526] Address comments from PR review --- clippy_dev/src/new_lint.rs | 1 + tests/compile-test.rs | 4 ++-- tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml | 1 + tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml | 1 + tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml | 1 + tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml | 1 + tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml | 1 + tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml | 1 + 8 files changed, 9 insertions(+), 2 deletions(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 843beaf3238..80713ab569f 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -139,6 +139,7 @@ fn get_manifest_contents(lint_name: &str, hint: &str) -> String { [package] name = "{}" version = "0.1.0" +publish = false "#, hint, lint_name ) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 91b9c73c9d4..232b966f69a 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -147,7 +147,7 @@ fn run_ui_toml(config: &mut compiletest::Config) { Ok(true) => {}, Ok(false) => panic!("Some tests failed"), Err(e) => { - println!("I/O failure during tests: {:?}", e); + panic!("I/O failure during tests: {:?}", e); }, } } @@ -223,7 +223,7 @@ fn run_ui_cargo(config: &mut compiletest::Config) { Ok(true) => {}, Ok(false) => panic!("Some tests failed"), Err(e) => { - println!("I/O failure during tests: {:?}", e); + panic!("I/O failure during tests: {:?}", e); }, } } diff --git a/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml index 8346bf05778..c64adcf7c01 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml +++ b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml @@ -1,3 +1,4 @@ [package] name = "cargo_common_metadata" version = "0.1.0" +publish = false diff --git a/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml index f99c126fabf..c8233f328bb 100644 --- a/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml +++ b/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "cargo_common_metadata" version = "0.1.0" +publish = false authors = ["Random person from the Internet <someone@someplace.org>"] description = "A test package for the cargo_common_metadata lint" repository = "https://github.com/someone/cargo_common_metadata" diff --git a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml index 05ffde839dc..3a94b723f3f 100644 --- a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "multiple_crate_versions" version = "0.1.0" +publish = false [dependencies] ctrlc = "=3.1.0" diff --git a/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml index cad32b9233f..a9b06420b33 100644 --- a/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "cargo_common_metadata" version = "0.1.0" +publish = false [dependencies] regex = "1.3.7" diff --git a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml index 9558dd68091..fd2a3414856 100644 --- a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml +++ b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "wildcard_dependencies" version = "0.1.0" +publish = false [dependencies] regex = "*" diff --git a/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml b/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml index 062e441622a..38cb139146e 100644 --- a/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml +++ b/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "wildcard_dependencies" version = "0.1.0" +publish = false [dependencies] regex = "1" From 1a04686fc0d2752de8731c833ab67bfae6136720 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 21 May 2020 14:47:13 +0200 Subject: [PATCH 093/526] Avoid triggering match_wildcard_for_single_variants --- clippy_dev/src/new_lint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 80713ab569f..08a2e0c0918 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -18,11 +18,11 @@ trait Context { impl<T> Context for io::Result<T> { fn context<C: AsRef<str>>(self, text: C) -> Self { match self { + Ok(t) => Ok(t), Err(e) => { let message = format!("{}: {}", text.as_ref(), e); Err(io::Error::new(ErrorKind::Other, message)) }, - ok => ok, } } } From f9013ff197a693798f0532f88bab0ae591d5ff82 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 21 May 2020 15:34:48 +0200 Subject: [PATCH 094/526] Relax fs layout so that multiple pass/fail manifests are possible --- doc/adding_lints.md | 11 ++++++++--- tests/compile-test.rs | 10 +++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 75768681db9..b3f5a62d553 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -43,7 +43,7 @@ case), and we don't need type information so it will have an early pass type (category will default to nursery if not provided). This command will create two files: `tests/ui/foo_functions.rs` and `clippy_lints/src/foo_functions.rs`, as well as run `cargo dev update_lints` to register the new lint. For cargo lints, -two project hierarchies (fail/pass) will be created under `tests/ui-cargo`. +two project hierarchies (fail/pass) will be created by default under `tests/ui-cargo`. Next, we'll open up these files and add our lint! @@ -110,12 +110,17 @@ specific lint you are creating/editing. ### Cargo lints For cargo lints, the process of testing differs in that we are interested in -the contents of the `Cargo.toml` files. If our new lint is named e.g. `foo_categories`, -after running `cargo dev new_lint` we will find two new manifest files: +the `Cargo.toml` manifest file. We also need a minimal crate associated +with that manifest. + +If our new lint is named e.g. `foo_categories`, after running `cargo dev new_lint` +we will find by default two new crates, each with its manifest file: * `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the new lint to raise an error. * `tests/ui-cargo/foo_categories/pass/Cargo.toml`: this file should not trigger the lint. +If you need more cases, you can copy one of those crates (under `foo_categories`) and rename it. + The process of generating the `.stderr` file is the same, and prepending the `TESTNAME` variable to `cargo uitest` works too, but the script to update the references is in another path: `tests/ui-cargo/update-all-references.sh`. diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 232b966f69a..a5de8429390 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -174,9 +174,13 @@ fn run_ui_cargo(config: &mut compiletest::Config) { _ => {}, } - for case in &["pass", "fail"] { - let tail: PathBuf = [case, "src"].iter().collect(); - let src_path = dir_path.join(tail); + for case in fs::read_dir(&dir_path)? { + let case = case?; + if !case.file_type()?.is_dir() { + continue; + } + + let src_path = case.path().join("src"); env::set_current_dir(&src_path)?; for file in fs::read_dir(&src_path)? { From c00268d984b80e408f56b5d8180e2f1a80100c91 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Fri, 22 May 2020 02:40:39 +0200 Subject: [PATCH 095/526] Also install llvm-tools on toolchain setup --- setup-toolchain.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup-toolchain.sh b/setup-toolchain.sh index 6038ed697f9..191ea4315a6 100755 --- a/setup-toolchain.sh +++ b/setup-toolchain.sh @@ -32,5 +32,5 @@ else TOOLCHAIN=() fi -rustup-toolchain-install-master -f -n master "${TOOLCHAIN[@]}" -c rustc-dev -- "$RUST_COMMIT" +rustup-toolchain-install-master -f -n master "${TOOLCHAIN[@]}" -c rustc-dev -c llvm-tools -- "$RUST_COMMIT" rustup override set master From 6b3cf63bf568cab4f8e05ea483ad97d5ea0e2eec Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Fri, 22 May 2020 14:45:51 +0200 Subject: [PATCH 096/526] Fix dogfood fallout --- clippy_lints/src/methods/mod.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 810a226b50d..32b3b7f7947 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1496,17 +1496,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { if let ty::Opaque(def_id, _) = ret_ty.kind { // one of the associated types must be Self for predicate in cx.tcx.predicates_of(def_id).predicates { - match predicate.0.kind() { - ty::PredicateKind::Projection(poly_projection_predicate) => { - let binder = poly_projection_predicate.ty(); - let associated_type = binder.skip_binder(); + if let ty::PredicateKind::Projection(poly_projection_predicate) = predicate.0.kind() { + let binder = poly_projection_predicate.ty(); + let associated_type = binder.skip_binder(); - // walk the associated type and check for Self - if contains_self_ty(associated_type) { - return; - } - }, - _ => {}, + // walk the associated type and check for Self + if contains_self_ty(associated_type) { + return; + } } } } From a578bed69ac2a9b33fcb871f9ad7dbf02355cb82 Mon Sep 17 00:00:00 2001 From: Andy Russell <arussell123@gmail.com> Date: Mon, 18 May 2020 18:35:49 -0400 Subject: [PATCH 097/526] new_without_default: do not suggest deriving --- clippy_lints/src/new_without_default.rs | 118 +++++------------------- tests/ui/new_without_default.rs | 11 +++ tests/ui/new_without_default.stderr | 35 ++++++- 3 files changed, 64 insertions(+), 100 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index a599667b8d8..3b88e4c4cb1 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -1,27 +1,20 @@ use crate::utils::paths; use crate::utils::sugg::DiagnosticBuilderExt; -use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_hir_and_then}; +use crate::utils::{get_trait_def_id, return_ty, same_tys, span_lint_hir_and_then}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_hir::HirIdSet; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::Ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::source_map::Span; declare_clippy_lint! { /// **What it does:** Checks for types with a `fn new() -> Self` method and no /// implementation of /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html). /// - /// It detects both the case when a manual - /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) - /// implementation is required and also when it can be created with - /// `#[derive(Default)]` - /// /// **Why is this bad?** The user might expect to be able to use /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the /// type can be constructed without arguments. @@ -40,46 +33,17 @@ declare_clippy_lint! { /// } /// ``` /// - /// Instead, use: + /// To fix the lint, and a `Default` implementation that delegates to `new`: /// /// ```ignore /// struct Foo(Bar); /// /// impl Default for Foo { /// fn default() -> Self { - /// Foo(Bar::new()) + /// Foo::new() /// } /// } /// ``` - /// - /// Or, if - /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) - /// can be derived by `#[derive(Default)]`: - /// - /// ```rust - /// struct Foo; - /// - /// impl Foo { - /// fn new() -> Self { - /// Foo - /// } - /// } - /// ``` - /// - /// Instead, use: - /// - /// ```rust - /// #[derive(Default)] - /// struct Foo; - /// - /// impl Foo { - /// fn new() -> Self { - /// Foo - /// } - /// } - /// ``` - /// - /// You can also have `new()` call `Default::default()`. pub NEW_WITHOUT_DEFAULT, style, "`fn new() -> Self` method without `Default` implementation" @@ -158,46 +122,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { } } - if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { - span_lint_hir_and_then( - cx, - NEW_WITHOUT_DEFAULT, - id, - impl_item.span, - &format!( - "you should consider deriving a `Default` implementation for `{}`", - self_ty - ), - |diag| { - diag.suggest_item_with_attr( - cx, - sp, - "try this", - "#[derive(Default)]", - Applicability::MaybeIncorrect, - ); - }); - } else { - span_lint_hir_and_then( - cx, - NEW_WITHOUT_DEFAULT, - id, - impl_item.span, - &format!( - "you should consider adding a `Default` implementation for `{}`", - self_ty - ), - |diag| { - diag.suggest_prepend_item( - cx, - item.span, - "try this", - &create_new_without_default_suggest_msg(self_ty), - Applicability::MaybeIncorrect, - ); - }, - ); - } + span_lint_hir_and_then( + cx, + NEW_WITHOUT_DEFAULT, + id, + impl_item.span, + &format!( + "you should consider adding a `Default` implementation for `{}`", + self_ty + ), + |diag| { + diag.suggest_prepend_item( + cx, + item.span, + "try this", + &create_new_without_default_suggest_msg(self_ty), + Applicability::MaybeIncorrect, + ); + }, + ); } } } @@ -217,18 +160,3 @@ fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String { }} }}", ty) } - -fn can_derive_default<'t, 'c>(ty: Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option<Span> { - match ty.kind { - ty::Adt(adt_def, substs) if adt_def.is_struct() => { - for field in adt_def.all_fields() { - let f_ty = field.ty(cx.tcx, substs); - if !implements_trait(cx, f_ty, default_trait_id, &[]) { - return None; - } - } - Some(cx.tcx.def_span(adt_def.did)) - }, - _ => None, - } -} diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index 781ea7bb152..3b6041823d8 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -148,4 +148,15 @@ impl AllowDerive { } } +pub struct NewNotEqualToDerive { + foo: i32, +} + +impl NewNotEqualToDerive { + // This `new` implementation is not equal to a derived `Default`, so do not suggest deriving. + pub fn new() -> Self { + NewNotEqualToDerive { foo: 1 } + } +} + fn main() {} diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 5e485d40663..e529e441eb7 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -1,4 +1,4 @@ -error: you should consider deriving a `Default` implementation for `Foo` +error: you should consider adding a `Default` implementation for `Foo` --> $DIR/new_without_default.rs:8:5 | LL | / pub fn new() -> Foo { @@ -9,10 +9,14 @@ LL | | } = note: `-D clippy::new-without-default` implied by `-D warnings` help: try this | -LL | #[derive(Default)] +LL | impl Default for Foo { +LL | fn default() -> Self { +LL | Self::new() +LL | } +LL | } | -error: you should consider deriving a `Default` implementation for `Bar` +error: you should consider adding a `Default` implementation for `Bar` --> $DIR/new_without_default.rs:16:5 | LL | / pub fn new() -> Self { @@ -22,7 +26,11 @@ LL | | } | help: try this | -LL | #[derive(Default)] +LL | impl Default for Bar { +LL | fn default() -> Self { +LL | Self::new() +LL | } +LL | } | error: you should consider adding a `Default` implementation for `LtKo<'c>` @@ -42,5 +50,22 @@ LL | } LL | } | -error: aborting due to 3 previous errors +error: you should consider adding a `Default` implementation for `NewNotEqualToDerive` + --> $DIR/new_without_default.rs:157:5 + | +LL | / pub fn new() -> Self { +LL | | NewNotEqualToDerive { foo: 1 } +LL | | } + | |_____^ + | +help: try this + | +LL | impl Default for NewNotEqualToDerive { +LL | fn default() -> Self { +LL | Self::new() +LL | } +LL | } + | + +error: aborting due to 4 previous errors From 29d043683e6f70b22ae34596b4cb9ae07274c28b Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Fri, 22 May 2020 19:09:24 +0200 Subject: [PATCH 098/526] option_option test case #4298 --- tests/ui/option_option.rs | 25 +++++++++++++++++++++++++ tests/ui/option_option.stderr | 8 +++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs index 904c50e1403..a2617a13eca 100644 --- a/tests/ui/option_option.rs +++ b/tests/ui/option_option.rs @@ -60,3 +60,28 @@ fn main() { // The lint allows this let expr = Some(Some(true)); } + +extern crate serde; +mod issue_4298 { + use serde::{Deserialize, Deserializer, Serialize}; + use std::borrow::Cow; + + #[derive(Serialize, Deserialize)] + struct Foo<'a> { + #[serde(deserialize_with = "func")] + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] + #[serde(borrow)] + // FIXME: should not lint here + #[allow(clippy::option_option)] + foo: Option<Option<Cow<'a, str>>>, + } + + #[allow(clippy::option_option)] + fn func<'a, D>(_: D) -> Result<Option<Option<Cow<'a, str>>>, D::Error> + where + D: Deserializer<'a>, + { + Ok(Some(Some(Cow::Borrowed("hi")))) + } +} diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index 79db186d7ea..0cd4c96eb4f 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -58,5 +58,11 @@ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enu LL | Struct { x: Option<Option<u8>> }, | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases + --> $DIR/option_option.rs:77:14 + | +LL | foo: Option<Option<Cow<'a, str>>>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors From a709559705db19785b29ce4a9044d7aebaefec31 Mon Sep 17 00:00:00 2001 From: Nick Torres <nickrtorres@icloud.com> Date: Sat, 23 May 2020 16:14:38 -0700 Subject: [PATCH 099/526] Clarify the documentation of the `unnecessary_mut_passed` lint --- clippy_lints/src/mut_reference.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index e5680482e5b..67a1ac78a67 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { - /// **What it does:** Detects giving a mutable reference to a function that only + /// **What it does:** Detects passing a mutable reference to a function that only /// requires an immutable reference. /// /// **Why is this bad?** The immutable reference rules out all other references From 7a83eafd44b57196a454d10628d1cce1bfd60bd2 Mon Sep 17 00:00:00 2001 From: Philipp Krones <hello@philkrones.com> Date: Mon, 25 May 2020 17:11:07 +0200 Subject: [PATCH 100/526] Also fetch origin before merging master into the rustup branch --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c9180e58fc2..0f47ac98fd2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -183,8 +183,8 @@ to be run inside the `rust` directory): `rust-clippy` repo (this has to be done in the Clippy repo, not in the rust-copy of Clippy): ```bash + git fetch origin && git fetch upstream git checkout sync-from-rust - git fetch upstream git merge upstream/master ``` 3. Open a PR to `rust-lang/rust-clippy` and wait for it to get merged (to From cff5cff2f3a6687dfaf12b92762e70545e0abefe Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Fri, 22 May 2020 22:30:28 +0200 Subject: [PATCH 101/526] Make the name of the crate available in cargo UI tests --- clippy_dev/src/new_lint.rs | 17 ++++++++++++----- .../cargo_common_metadata/fail/src/main.rs | 1 + .../cargo_common_metadata/pass/src/main.rs | 1 + .../multiple_crate_versions/fail/src/main.rs | 1 + .../multiple_crate_versions/pass/src/main.rs | 1 + .../wildcard_dependencies/fail/src/main.rs | 1 + .../wildcard_dependencies/pass/src/main.rs | 1 + 7 files changed, 18 insertions(+), 5 deletions(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 08a2e0c0918..c0b2dac2f60 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -76,7 +76,8 @@ fn create_test(lint: &LintData) -> io::Result<()> { path.push("src"); fs::create_dir(&path)?; - write_file(path.join("main.rs"), get_test_file_contents(lint_name))?; + let header = format!("// compile-flags: --crate-name={}", lint_name); + write_file(path.join("main.rs"), get_test_file_contents(lint_name, Some(&header)))?; Ok(()) } @@ -90,7 +91,7 @@ fn create_test(lint: &LintData) -> io::Result<()> { create_project_layout(lint.name, &test_dir, "pass", "This file should not trigger the lint") } else { let test_path = format!("tests/ui/{}.rs", lint.name); - let test_contents = get_test_file_contents(lint.name); + let test_contents = get_test_file_contents(lint.name, None); write_file(lint.project_root.join(test_path), test_contents) } } @@ -119,8 +120,8 @@ fn to_camel_case(name: &str) -> String { .collect() } -fn get_test_file_contents(lint_name: &str) -> String { - format!( +fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String { + let mut contents = format!( "#![warn(clippy::{})] fn main() {{ @@ -128,7 +129,13 @@ fn main() {{ }} ", lint_name - ) + ); + + if let Some(header) = header_commands { + contents = format!("{}\n{}", header, contents); + } + + contents } fn get_manifest_contents(lint_name: &str, hint: &str) -> String { diff --git a/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs b/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs index c67166fc4b0..27841e18aa9 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs +++ b/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs @@ -1,3 +1,4 @@ +// compile-flags: --crate-name=cargo_common_metadata #![warn(clippy::cargo_common_metadata)] fn main() {} diff --git a/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs b/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs index c67166fc4b0..27841e18aa9 100644 --- a/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs +++ b/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs @@ -1,3 +1,4 @@ +// compile-flags: --crate-name=cargo_common_metadata #![warn(clippy::cargo_common_metadata)] fn main() {} diff --git a/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs b/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs index 4bc61dd6299..1b2d3ec9459 100644 --- a/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs +++ b/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs @@ -1,3 +1,4 @@ +// compile-flags: --crate-name=multiple_crate_versions #![warn(clippy::multiple_crate_versions)] fn main() {} diff --git a/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs b/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs index 4bc61dd6299..1b2d3ec9459 100644 --- a/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs +++ b/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs @@ -1,3 +1,4 @@ +// compile-flags: --crate-name=multiple_crate_versions #![warn(clippy::multiple_crate_versions)] fn main() {} diff --git a/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs b/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs index 3491ccb0d47..581babfeacb 100644 --- a/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs +++ b/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs @@ -1,3 +1,4 @@ +// compile-flags: --crate-name=wildcard_dependencies #![warn(clippy::wildcard_dependencies)] fn main() {} diff --git a/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs b/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs index 3491ccb0d47..581babfeacb 100644 --- a/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs +++ b/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs @@ -1,3 +1,4 @@ +// compile-flags: --crate-name=wildcard_dependencies #![warn(clippy::wildcard_dependencies)] fn main() {} From 8642fc97dd1a9b4f0291726c47ec97d15599d74d Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Fri, 22 May 2020 22:39:19 +0200 Subject: [PATCH 102/526] multiple_crate_versions: skip dev and build deps --- clippy_lints/src/multiple_crate_versions.rs | 59 ++++++++++++++----- .../5041_allow_dev_build/Cargo.toml | 17 ++++++ .../5041_allow_dev_build/src/main.rs | 4 ++ 3 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml create mode 100644 tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index c4decfc9401..b24ec897ef5 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -1,11 +1,14 @@ //! lint on multiple versions of a crate being used use crate::utils::{run_lints, span_lint}; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::{Crate, CRATE_HIR_ID}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; +use cargo_metadata::{DependencyKind, MetadataCommand, Node, Package, PackageId}; +use if_chain::if_chain; use itertools::Itertools; declare_clippy_lint! { @@ -34,37 +37,65 @@ declare_clippy_lint! { declare_lint_pass!(MultipleCrateVersions => [MULTIPLE_CRATE_VERSIONS]); impl LateLintPass<'_, '_> for MultipleCrateVersions { + #[allow(clippy::find_map)] fn check_crate(&mut self, cx: &LateContext<'_, '_>, _: &Crate<'_>) { if !run_lints(cx, &[MULTIPLE_CRATE_VERSIONS], CRATE_HIR_ID) { return; } - let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().exec() { + let metadata = if let Ok(metadata) = MetadataCommand::new().exec() { metadata } else { span_lint(cx, MULTIPLE_CRATE_VERSIONS, DUMMY_SP, "could not read cargo metadata"); - return; }; + let local_name = cx.tcx.crate_name(LOCAL_CRATE).as_str(); let mut packages = metadata.packages; packages.sort_by(|a, b| a.name.cmp(&b.name)); - for (name, group) in &packages.into_iter().group_by(|p| p.name.clone()) { - let group: Vec<cargo_metadata::Package> = group.collect(); + if_chain! { + if let Some(resolve) = &metadata.resolve; + if let Some(local_id) = packages.iter().find(|p| p.name == *local_name).map(|p| &p.id); + then { + for (name, group) in &packages.iter().group_by(|p| p.name.clone()) { + let group: Vec<&Package> = group.collect(); - if group.len() > 1 { - let mut versions: Vec<_> = group.into_iter().map(|p| p.version).collect(); - versions.sort(); - let versions = versions.iter().join(", "); + if group.len() <= 1 { + continue; + } - span_lint( - cx, - MULTIPLE_CRATE_VERSIONS, - DUMMY_SP, - &format!("multiple versions for dependency `{}`: {}", name, versions), - ); + if group.iter().all(|p| is_normal_dep(&resolve.nodes, local_id, &p.id)) { + let mut versions: Vec<_> = group.into_iter().map(|p| &p.version).collect(); + versions.sort(); + let versions = versions.iter().join(", "); + + span_lint( + cx, + MULTIPLE_CRATE_VERSIONS, + DUMMY_SP, + &format!("multiple versions for dependency `{}`: {}", name, versions), + ); + } + } } } } } + +fn is_normal_dep(nodes: &[Node], local_id: &PackageId, dep_id: &PackageId) -> bool { + fn depends_on(node: &Node, dep_id: &PackageId) -> bool { + node.deps.iter().any(|dep| { + dep.pkg == *dep_id + && dep + .dep_kinds + .iter() + .any(|info| matches!(info.kind, DependencyKind::Normal)) + }) + } + + nodes + .iter() + .filter(|node| depends_on(node, dep_id)) + .any(|node| node.id == *local_id || is_normal_dep(nodes, local_id, &node.id)) +} diff --git a/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml new file mode 100644 index 00000000000..72731fbc75d --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml @@ -0,0 +1,17 @@ +# Should not lint for dev or build dependencies. See issue 5041. + +[package] +name = "multiple_crate_versions" +version = "0.1.0" +publish = false + +# One of the versions of winapi is only a dev dependency: allowed +[dependencies] +ctrlc = "=3.1.0" +[dev-dependencies] +ansi_term = "=0.11.0" + +# Both versions of winapi are a build dependency: allowed +[build-dependencies] +ctrlc = "=3.1.0" +ansi_term = "=0.11.0" diff --git a/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs new file mode 100644 index 00000000000..1b2d3ec9459 --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs @@ -0,0 +1,4 @@ +// compile-flags: --crate-name=multiple_crate_versions +#![warn(clippy::multiple_crate_versions)] + +fn main() {} From ec0a00e53980619a6313ff4f01099a1aebcfd9e6 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sun, 24 May 2020 21:17:54 +0200 Subject: [PATCH 103/526] Use find_map instead of find() + map() --- clippy_lints/src/multiple_crate_versions.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index b24ec897ef5..b6770804e18 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -37,7 +37,6 @@ declare_clippy_lint! { declare_lint_pass!(MultipleCrateVersions => [MULTIPLE_CRATE_VERSIONS]); impl LateLintPass<'_, '_> for MultipleCrateVersions { - #[allow(clippy::find_map)] fn check_crate(&mut self, cx: &LateContext<'_, '_>, _: &Crate<'_>) { if !run_lints(cx, &[MULTIPLE_CRATE_VERSIONS], CRATE_HIR_ID) { return; @@ -56,7 +55,9 @@ impl LateLintPass<'_, '_> for MultipleCrateVersions { if_chain! { if let Some(resolve) = &metadata.resolve; - if let Some(local_id) = packages.iter().find(|p| p.name == *local_name).map(|p| &p.id); + if let Some(local_id) = packages + .iter() + .find_map(|p| if p.name == *local_name { Some(&p.id) } else { None }); then { for (name, group) in &packages.iter().group_by(|p| p.name.clone()) { let group: Vec<&Package> = group.collect(); From 4f8909fad986dda68a9dcd172eaa362b6fce105b Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sat, 9 May 2020 21:28:31 +0200 Subject: [PATCH 104/526] Extend `useless_conversion` lint with TryFrom --- clippy_lints/src/useless_conversion.rs | 47 ++++++++++++++++++++------ clippy_lints/src/utils/paths.rs | 1 + tests/ui/useless_conversion.stderr | 20 +++++------ tests/ui/useless_conversion_try.rs | 25 ++++++++++++++ tests/ui/useless_conversion_try.stderr | 39 +++++++++++++++++++++ 5 files changed, 112 insertions(+), 20 deletions(-) create mode 100644 tests/ui/useless_conversion_try.rs create mode 100644 tests/ui/useless_conversion_try.stderr diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 95921518986..0b080d9be2c 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -1,13 +1,16 @@ use crate::utils::{ - match_def_path, match_trait_method, paths, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_sugg, + is_type_diagnostic_item, match_def_path, match_trait_method, paths, same_tys, snippet, snippet_with_macro_callsite, + span_lint_and_help, span_lint_and_sugg, }; +use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, HirId, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { - /// **What it does:** Checks for `Into`/`From`/`IntoIter` calls that useless converts + /// **What it does:** Checks for `Into`, `From`, `TryFrom`,`IntoIter` calls that useless converts /// to the same type as caller. /// /// **Why is this bad?** Redundant code. @@ -26,7 +29,7 @@ declare_clippy_lint! { /// ``` pub USELESS_CONVERSION, complexity, - "calls to `Into`/`From`/`IntoIter` that performs useless conversions to the same type" + "calls to `Into`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type" } #[derive(Default)] @@ -68,7 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - "useless conversion", + "Useless conversion to the same type", "consider removing `.into()`", sugg, Applicability::MachineApplicable, // snippet @@ -84,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - "useless conversion", + "Useless conversion to the same type", "consider removing `.into_iter()`", sugg, Applicability::MachineApplicable, // snippet @@ -94,11 +97,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { }, ExprKind::Call(ref path, ref args) => { - if let ExprKind::Path(ref qpath) = path.kind { - if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id() { + if_chain! { + if args.len() == 1; + if let ExprKind::Path(ref qpath) = path.kind; + if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id(); + let a = cx.tables.expr_ty(e); + let b = cx.tables.expr_ty(&args[0]); + + then { + if_chain! { + if match_def_path(cx, def_id, &paths::TRY_FROM); + if is_type_diagnostic_item(cx, a, sym!(result_type)); + if let ty::Adt(_, substs) = a.kind; + if let Some(a_type) = substs.types().nth(0); + if same_tys(cx, a_type, b); + + then { + let hint = format!("consider removing `{}()`", snippet(cx, path.span, "TryFrom::try_from")); + span_lint_and_help( + cx, + USELESS_CONVERSION, + e.span, + "Useless conversion to the same type", + None, + &hint, + ); + } + } + if match_def_path(cx, def_id, &paths::FROM_FROM) { - let a = cx.tables.expr_ty(e); - let b = cx.tables.expr_ty(&args[0]); if same_tys(cx, a, b) { let sugg = snippet(cx, args[0].span.source_callsite(), "<expr>").into_owned(); let sugg_msg = @@ -107,7 +134,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - "useless conversion", + "Useless conversion to the same type", &sugg_msg, sugg, Applicability::MachineApplicable, // snippet diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index b3ad2ad9d99..e00d726282a 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -128,6 +128,7 @@ pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned" pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"]; pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"]; pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; +pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"]; pub const TRY_FROM_ERROR: [&str; 4] = ["std", "ops", "Try", "from_error"]; pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"]; pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"]; diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index 7df3507edfd..0b2947f7d62 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -1,4 +1,4 @@ -error: useless conversion +error: Useless conversion to the same type --> $DIR/useless_conversion.rs:6:13 | LL | let _ = T::from(val); @@ -10,55 +10,55 @@ note: the lint level is defined here LL | #![deny(clippy::useless_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: useless conversion +error: Useless conversion to the same type --> $DIR/useless_conversion.rs:7:5 | LL | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` -error: useless conversion +error: Useless conversion to the same type --> $DIR/useless_conversion.rs:19:22 | LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` -error: useless conversion +error: Useless conversion to the same type --> $DIR/useless_conversion.rs:51:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` -error: useless conversion +error: Useless conversion to the same type --> $DIR/useless_conversion.rs:52:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` -error: useless conversion +error: Useless conversion to the same type --> $DIR/useless_conversion.rs:53:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` -error: useless conversion +error: Useless conversion to the same type --> $DIR/useless_conversion.rs:54:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` -error: useless conversion +error: Useless conversion to the same type --> $DIR/useless_conversion.rs:55:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` -error: useless conversion +error: Useless conversion to the same type --> $DIR/useless_conversion.rs:56:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` -error: useless conversion +error: Useless conversion to the same type --> $DIR/useless_conversion.rs:57:21 | LL | let _: String = format!("Hello {}", "world").into(); diff --git a/tests/ui/useless_conversion_try.rs b/tests/ui/useless_conversion_try.rs new file mode 100644 index 00000000000..abf0c891b52 --- /dev/null +++ b/tests/ui/useless_conversion_try.rs @@ -0,0 +1,25 @@ +#![deny(clippy::useless_conversion)] + +use std::convert::TryFrom; + +fn test_generic<T: Copy>(val: T) -> T { + T::try_from(val).unwrap() +} + +fn test_generic2<T: Copy + Into<i32> + Into<U>, U: From<T>>(val: T) { + let _ = U::try_from(val).unwrap(); +} + +fn main() { + test_generic(10i32); + test_generic2::<i32, i32>(10i32); + + let _: String = TryFrom::try_from("foo").unwrap(); + let _ = String::try_from("foo").unwrap(); + #[allow(clippy::useless_conversion)] + let _ = String::try_from("foo").unwrap(); + + let _: String = TryFrom::try_from("foo".to_string()).unwrap(); + let _ = String::try_from("foo".to_string()).unwrap(); + let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); +} diff --git a/tests/ui/useless_conversion_try.stderr b/tests/ui/useless_conversion_try.stderr new file mode 100644 index 00000000000..b3cb01fbe32 --- /dev/null +++ b/tests/ui/useless_conversion_try.stderr @@ -0,0 +1,39 @@ +error: Useless conversion to the same type + --> $DIR/useless_conversion_try.rs:6:5 + | +LL | T::try_from(val).unwrap() + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/useless_conversion_try.rs:1:9 + | +LL | #![deny(clippy::useless_conversion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: consider removing `T::try_from()` + +error: Useless conversion to the same type + --> $DIR/useless_conversion_try.rs:22:21 + | +LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider removing `TryFrom::try_from()` + +error: Useless conversion to the same type + --> $DIR/useless_conversion_try.rs:23:13 + | +LL | let _ = String::try_from("foo".to_string()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider removing `String::try_from()` + +error: Useless conversion to the same type + --> $DIR/useless_conversion_try.rs:24:13 + | +LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider removing `String::try_from()` + +error: aborting due to 4 previous errors + From 705bfdcc467c0ddd7eb61d3adb24809b27bae891 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Fri, 22 May 2020 11:46:17 +0200 Subject: [PATCH 105/526] Extend `useless_conversion` lint with TryInto --- clippy_lints/src/useless_conversion.rs | 38 +++++++++++++++++++++----- clippy_lints/src/utils/paths.rs | 1 + src/lintlist/mod.rs | 2 +- tests/ui/useless_conversion_try.rs | 17 +++++++++--- tests/ui/useless_conversion_try.stderr | 38 +++++++++++++++++++++----- 5 files changed, 77 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 0b080d9be2c..1645c5777b2 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -10,8 +10,8 @@ use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { - /// **What it does:** Checks for `Into`, `From`, `TryFrom`,`IntoIter` calls that useless converts - /// to the same type as caller. + /// **What it does:** Checks for `Into`, `TryInto`, `From`, `TryFrom`,`IntoIter` calls + /// that useless converts to the same type as caller. /// /// **Why is this bad?** Redundant code. /// @@ -29,7 +29,7 @@ declare_clippy_lint! { /// ``` pub USELESS_CONVERSION, complexity, - "calls to `Into`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type" + "calls to `Into`, `TryInto`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type" } #[derive(Default)] @@ -39,6 +39,7 @@ pub struct UselessConversion { impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]); +#[allow(clippy::too_many_lines)] impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { if e.span.from_expansion() { @@ -66,7 +67,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { let b = cx.tables.expr_ty(&args[0]); if same_tys(cx, a, b) { let sugg = snippet_with_macro_callsite(cx, args[0].span, "<expr>").to_string(); - span_lint_and_sugg( cx, USELESS_CONVERSION, @@ -94,6 +94,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { ); } } + if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && &*name.ident.as_str() == "try_into" { + if_chain! { + let a = cx.tables.expr_ty(e); + let b = cx.tables.expr_ty(&args[0]); + if is_type_diagnostic_item(cx, a, sym!(result_type)); + if let ty::Adt(_, substs) = a.kind; + if let Some(a_type) = substs.types().next(); + if same_tys(cx, a_type, b); + + then { + span_lint_and_help( + cx, + USELESS_CONVERSION, + e.span, + "Useless conversion to the same type", + None, + "consider removing `.try_into()`", + ); + } + } + } }, ExprKind::Call(ref path, ref args) => { @@ -109,7 +130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { if match_def_path(cx, def_id, &paths::TRY_FROM); if is_type_diagnostic_item(cx, a, sym!(result_type)); if let ty::Adt(_, substs) = a.kind; - if let Some(a_type) = substs.types().nth(0); + if let Some(a_type) = substs.types().next(); if same_tys(cx, a_type, b); then { @@ -125,8 +146,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { } } - if match_def_path(cx, def_id, &paths::FROM_FROM) { - if same_tys(cx, a, b) { + if_chain! { + if match_def_path(cx, def_id, &paths::FROM_FROM); + if same_tys(cx, a, b); + + then { let sugg = snippet(cx, args[0].span.source_callsite(), "<expr>").into_owned(); let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index e00d726282a..779da7e6bf2 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -131,6 +131,7 @@ pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"]; pub const TRY_FROM_ERROR: [&str; 4] = ["std", "ops", "Try", "from_error"]; pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"]; +pub const TRY_INTO_TRAIT: [&str; 3] = ["core", "convert", "TryInto"]; pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"]; pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"]; pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"]; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 8211a57b564..f63301c7db0 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2421,7 +2421,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ Lint { name: "useless_conversion", group: "complexity", - desc: "calls to `Into`/`From`/`IntoIter` that performs useless conversions to the same type", + desc: "calls to `Into`, `TryInto`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type", deprecation: None, module: "useless_conversion", }, diff --git a/tests/ui/useless_conversion_try.rs b/tests/ui/useless_conversion_try.rs index abf0c891b52..ab4f960edb7 100644 --- a/tests/ui/useless_conversion_try.rs +++ b/tests/ui/useless_conversion_try.rs @@ -1,12 +1,16 @@ #![deny(clippy::useless_conversion)] -use std::convert::TryFrom; +use std::convert::{TryFrom, TryInto}; fn test_generic<T: Copy>(val: T) -> T { - T::try_from(val).unwrap() + let _ = T::try_from(val).unwrap(); + val.try_into().unwrap() } fn test_generic2<T: Copy + Into<i32> + Into<U>, U: From<T>>(val: T) { + // ok + let _: i32 = val.try_into().unwrap(); + let _: U = val.try_into().unwrap(); let _ = U::try_from(val).unwrap(); } @@ -14,12 +18,17 @@ fn main() { test_generic(10i32); test_generic2::<i32, i32>(10i32); + let _: String = "foo".try_into().unwrap(); let _: String = TryFrom::try_from("foo").unwrap(); let _ = String::try_from("foo").unwrap(); #[allow(clippy::useless_conversion)] - let _ = String::try_from("foo").unwrap(); - + { + let _ = String::try_from("foo").unwrap(); + let _: String = "foo".try_into().unwrap(); + } + let _: String = "foo".to_string().try_into().unwrap(); let _: String = TryFrom::try_from("foo".to_string()).unwrap(); let _ = String::try_from("foo".to_string()).unwrap(); let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); + let _: String = format!("Hello {}", "world").try_into().unwrap(); } diff --git a/tests/ui/useless_conversion_try.stderr b/tests/ui/useless_conversion_try.stderr index b3cb01fbe32..5afb5dc45d3 100644 --- a/tests/ui/useless_conversion_try.stderr +++ b/tests/ui/useless_conversion_try.stderr @@ -1,8 +1,8 @@ error: Useless conversion to the same type - --> $DIR/useless_conversion_try.rs:6:5 + --> $DIR/useless_conversion_try.rs:6:13 | -LL | T::try_from(val).unwrap() - | ^^^^^^^^^^^^^^^^ +LL | let _ = T::try_from(val).unwrap(); + | ^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/useless_conversion_try.rs:1:9 @@ -12,7 +12,23 @@ LL | #![deny(clippy::useless_conversion)] = help: consider removing `T::try_from()` error: Useless conversion to the same type - --> $DIR/useless_conversion_try.rs:22:21 + --> $DIR/useless_conversion_try.rs:7:5 + | +LL | val.try_into().unwrap() + | ^^^^^^^^^^^^^^ + | + = help: consider removing `.try_into()` + +error: Useless conversion to the same type + --> $DIR/useless_conversion_try.rs:29:21 + | +LL | let _: String = "foo".to_string().try_into().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider removing `.try_into()` + +error: Useless conversion to the same type + --> $DIR/useless_conversion_try.rs:30:21 | LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +36,7 @@ LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); = help: consider removing `TryFrom::try_from()` error: Useless conversion to the same type - --> $DIR/useless_conversion_try.rs:23:13 + --> $DIR/useless_conversion_try.rs:31:13 | LL | let _ = String::try_from("foo".to_string()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,12 +44,20 @@ LL | let _ = String::try_from("foo".to_string()).unwrap(); = help: consider removing `String::try_from()` error: Useless conversion to the same type - --> $DIR/useless_conversion_try.rs:24:13 + --> $DIR/useless_conversion_try.rs:32:13 | LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider removing `String::try_from()` -error: aborting due to 4 previous errors +error: Useless conversion to the same type + --> $DIR/useless_conversion_try.rs:33:21 + | +LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider removing `.try_into()` + +error: aborting due to 7 previous errors From 827041252c709dee70756633a33a13a0bacbd3a9 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sat, 23 May 2020 09:35:56 +0200 Subject: [PATCH 106/526] Add common lint tools doc --- doc/adding_lints.md | 1 + doc/common_tools_writing_lints.md | 152 ++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 doc/common_tools_writing_lints.md diff --git a/doc/adding_lints.md b/doc/adding_lints.md index b3f5a62d553..8092be277cc 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -465,6 +465,7 @@ Here are some pointers to things you are likely going to need for every lint: * [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro] * [`Span`][span] * [`Applicability`][applicability] +* [Common tools for writing lints](common_tools_writing_lints.md) helps with common operations * [The rustc-dev-guide][rustc-dev-guide] explains a lot of internal compiler concepts * [The nightly rustc docs][nightly_docs] which has been linked to throughout this guide diff --git a/doc/common_tools_writing_lints.md b/doc/common_tools_writing_lints.md new file mode 100644 index 00000000000..ed33b37c6bd --- /dev/null +++ b/doc/common_tools_writing_lints.md @@ -0,0 +1,152 @@ +# Common tools for writing lints + +You may need following tooltips to catch up with common operations. + +- [Common tools for writing lints](#common-tools-for-writing-lints) + - [Retrieving the type of an expression](#retrieving-the-type-of-an-expression) + - [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait) + - [Dealing with macros](#dealing-with-macros) + +Useful Rustc dev guide links: +- [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation) +- [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html) +- [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html) + +# Retrieving the type of an expression + +Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for example to answer following questions: + +- which type does this expression correspond to (using its [`TyKind`][TyKind])? +- is it a sized type? +- is it a primitive type? +- does it implement a trait? + +This operation is performed using the [`expr_ty()`][expr_ty] method from the [`TypeckTables`][TypeckTables] struct, +that gives you access to the underlying structure [`TyS`][TyS]. + +Example of use: +```rust +impl LateLintPass<'_, '_> for MyStructLint { + fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + // Get type of `expr` + let ty = cx.tables.expr_ty(expr); + // Match its kind to enter its type + match ty.kind { + ty::Adt(adt_def, _) if adt_def.is_struct() => println!("Our `expr` is a struct!"), + _ => () + } + } +} +``` + +Similarly in [`TypeckTables`][TypeckTables] methods, you have the [`pat_ty()`][pat_ty] method +to retrieve a type from a pattern. + +Two noticeable items here: +- `cx` is the lint context [`LateContext`][LateContext]. + The two most useful data structures in this context are `tcx` and `tables`, + allowing us to jump to type definitions and other compilation stages such as HIR. +- `tables` is [`TypeckTables`][TypeckTables] and is created by type checking step, + it includes useful information such as types of expressions, ways to resolve methods and so on. + +# Checking if a type implements a specific trait + +There are two ways to do this, depending if the target trait is part of lang items. + +```rust +use crate::utils::{implements_trait, match_trait_method, paths}; + +impl LateLintPass<'_, '_> for MyStructLint { + fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + // 1. Using expression and Clippy's convenient method + // we use `match_trait_method` function from Clippy's toolbox + if match_trait_method(cx, expr, &paths::INTO) { + // `expr` implements `Into` trait + } + + // 2. Using type context `TyCtxt` + let ty = cx.tables.expr_ty(expr); + if cx.tcx.lang_items() + // we are looking for the `DefId` of `Drop` trait in lang items + .drop_trait() + // then we use it with our type `ty` by calling `implements_trait` from Clippy's utils + .map_or(false, |id| implements_trait(cx, ty, id, &[])) { + // `expr` implements `Drop` trait + } + } +} +``` + +> Prefer using lang items, if the target trait is available there. + +A list of defined paths for Clippy can be found in [paths.rs][paths] + +We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate. + +# Dealing with macros + +There are several helpers in Clippy's utils to deal with macros: + +- `in_macro()`: detect if the given span is expanded by a macro + +You may want to use this for example to not start linting in any macro. + +```rust +macro_rules! foo { + ($param:expr) => { + match $param { + "bar" => println!("whatever"), + _ => () + } + }; +} + +foo!("bar"); + +// if we lint the `match` of `foo` call and test its span +assert_eq!(in_macro(match_span), true); +``` + +- `in_external_macro()`: detect if the given span is from an external macro, defined in a foreign crate + +You may want to use it for example to not start linting in macros from other crates + +```rust +#[macro_use] +extern crate a_crate_with_macros; + +// `foo` is defined in `a_crate_with_macros` +foo!("bar"); + +// if we lint the `match` of `foo` call and test its span +assert_eq!(in_external_macro(cx.sess(), match_span), true); +``` + +- `differing_macro_contexts()`: returns true if the two given spans are not from the same context + +```rust +macro_rules! m { + ($a:expr, $b:expr) => { + if $a.is_some() { + $b; + } + } +} + +let x: Option<u32> = Some(42); +m!(x, x.unwrap()); + +// These spans are not from the same context +// x.is_some() is from inside the macro +// x.unwrap() is from outside the macro +assert_eq!(differing_macro_contexts(x_is_some_span, x_unwrap_span), true); +``` + +[TyS]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyS.html +[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html +[TypeckTables]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckTables.html +[expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckTables.html#method.expr_ty +[LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html +[TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html +[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckTables.html#method.pat_ty +[paths]: ../clippy_lints/src/utils/paths.rs From 60d38ee1dde4344daa5fdf716eef78b45f483c7e Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sat, 23 May 2020 22:07:03 +0200 Subject: [PATCH 107/526] reversed_empty_ranges: add suggestion for &slice[N..N] --- clippy_lints/src/ranges.rs | 30 ++++++++++++++----- tests/ui/reversed_empty_ranges_fixable.fixed | 7 ++++- tests/ui/reversed_empty_ranges_fixable.rs | 7 ++++- tests/ui/reversed_empty_ranges_fixable.stderr | 16 ++++++---- tests/ui/reversed_empty_ranges_unfixable.rs | 1 - .../ui/reversed_empty_ranges_unfixable.stderr | 10 ++----- 6 files changed, 47 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 83c6faac041..1eb26d97ed4 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -241,14 +241,14 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { - fn inside_indexing_expr(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { - matches!( - get_parent_expr(cx, expr), - Some(Expr { + fn inside_indexing_expr<'a>(cx: &'a LateContext<'_, '_>, expr: &Expr<'_>) -> Option<&'a Expr<'a>> { + match get_parent_expr(cx, expr) { + parent_expr @ Some(Expr { kind: ExprKind::Index(..), .. - }) - ) + }) => parent_expr, + _ => None, + } } fn is_empty_range(limits: RangeLimits, ordering: Ordering) -> bool { @@ -267,18 +267,32 @@ fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx); if is_empty_range(limits, ordering); then { - if inside_indexing_expr(cx, expr) { + if let Some(parent_expr) = inside_indexing_expr(cx, expr) { let (reason, outcome) = if ordering == Ordering::Equal { ("empty", "always yield an empty slice") } else { ("reversed", "panic at run-time") }; - span_lint( + span_lint_and_then( cx, REVERSED_EMPTY_RANGES, expr.span, &format!("this range is {} and using it to index a slice will {}", reason, outcome), + |diag| { + if_chain! { + if ordering == Ordering::Equal; + if let ty::Slice(slice_ty) = cx.tables.expr_ty(parent_expr).kind; + then { + diag.span_suggestion( + parent_expr.span, + "if you want an empty slice, use", + format!("[] as &[{}]", slice_ty), + Applicability::MaybeIncorrect + ); + } + } + } ); } else { span_lint_and_then( diff --git a/tests/ui/reversed_empty_ranges_fixable.fixed b/tests/ui/reversed_empty_ranges_fixable.fixed index ee2cbc3cf54..332c0427ef6 100644 --- a/tests/ui/reversed_empty_ranges_fixable.fixed +++ b/tests/ui/reversed_empty_ranges_fixable.fixed @@ -4,18 +4,23 @@ const ANSWER: i32 = 42; fn main() { + let arr = [1, 2, 3, 4, 5]; + + // These should be linted: + (21..=42).rev().for_each(|x| println!("{}", x)); let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>(); for _ in (-42..=-21).rev() {} for _ in (21u32..42u32).rev() {} + let _ = &[] as &[i32]; + // These should be ignored as they are not empty ranges: (21..=42).for_each(|x| println!("{}", x)); (21..42).for_each(|x| println!("{}", x)); - let arr = [1, 2, 3, 4, 5]; let _ = &arr[1..=3]; let _ = &arr[1..3]; diff --git a/tests/ui/reversed_empty_ranges_fixable.rs b/tests/ui/reversed_empty_ranges_fixable.rs index 6ed5ca6daa0..901ec8bcc09 100644 --- a/tests/ui/reversed_empty_ranges_fixable.rs +++ b/tests/ui/reversed_empty_ranges_fixable.rs @@ -4,18 +4,23 @@ const ANSWER: i32 = 42; fn main() { + let arr = [1, 2, 3, 4, 5]; + + // These should be linted: + (42..=21).for_each(|x| println!("{}", x)); let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>(); for _ in -21..=-42 {} for _ in 42u32..21u32 {} + let _ = &arr[3..3]; + // These should be ignored as they are not empty ranges: (21..=42).for_each(|x| println!("{}", x)); (21..42).for_each(|x| println!("{}", x)); - let arr = [1, 2, 3, 4, 5]; let _ = &arr[1..=3]; let _ = &arr[1..3]; diff --git a/tests/ui/reversed_empty_ranges_fixable.stderr b/tests/ui/reversed_empty_ranges_fixable.stderr index 97933b8ff85..9a646fd9939 100644 --- a/tests/ui/reversed_empty_ranges_fixable.stderr +++ b/tests/ui/reversed_empty_ranges_fixable.stderr @@ -1,5 +1,5 @@ error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_fixable.rs:7:5 + --> $DIR/reversed_empty_ranges_fixable.rs:11:5 | LL | (42..=21).for_each(|x| println!("{}", x)); | ^^^^^^^^^ @@ -11,7 +11,7 @@ LL | (21..=42).rev().for_each(|x| println!("{}", x)); | ^^^^^^^^^^^^^^^ error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_fixable.rs:8:13 + --> $DIR/reversed_empty_ranges_fixable.rs:12:13 | LL | let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>(); | ^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::<Ve | ^^^^^^^^^^^^^^^^^^ error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_fixable.rs:10:14 + --> $DIR/reversed_empty_ranges_fixable.rs:14:14 | LL | for _ in -21..=-42 {} | ^^^^^^^^^ @@ -33,7 +33,7 @@ LL | for _ in (-42..=-21).rev() {} | ^^^^^^^^^^^^^^^^^ error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_fixable.rs:11:14 + --> $DIR/reversed_empty_ranges_fixable.rs:15:14 | LL | for _ in 42u32..21u32 {} | ^^^^^^^^^^^^ @@ -43,5 +43,11 @@ help: consider using the following if you are attempting to iterate over this ra LL | for _ in (21u32..42u32).rev() {} | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: this range is empty and using it to index a slice will always yield an empty slice + --> $DIR/reversed_empty_ranges_fixable.rs:17:18 + | +LL | let _ = &arr[3..3]; + | ----^^^^- help: if you want an empty slice, use: `[] as &[i32]` + +error: aborting due to 5 previous errors diff --git a/tests/ui/reversed_empty_ranges_unfixable.rs b/tests/ui/reversed_empty_ranges_unfixable.rs index c9ca4c47668..561a35625f0 100644 --- a/tests/ui/reversed_empty_ranges_unfixable.rs +++ b/tests/ui/reversed_empty_ranges_unfixable.rs @@ -9,7 +9,6 @@ fn main() { let arr = [1, 2, 3, 4, 5]; let _ = &arr[3usize..=1usize]; let _ = &arr[SOME_NUM..1]; - let _ = &arr[3..3]; for _ in ANSWER..ANSWER {} } diff --git a/tests/ui/reversed_empty_ranges_unfixable.stderr b/tests/ui/reversed_empty_ranges_unfixable.stderr index 12e5483ecdf..240188cbb46 100644 --- a/tests/ui/reversed_empty_ranges_unfixable.stderr +++ b/tests/ui/reversed_empty_ranges_unfixable.stderr @@ -18,17 +18,11 @@ error: this range is reversed and using it to index a slice will panic at run-ti LL | let _ = &arr[SOME_NUM..1]; | ^^^^^^^^^^^ -error: this range is empty and using it to index a slice will always yield an empty slice - --> $DIR/reversed_empty_ranges_unfixable.rs:12:18 - | -LL | let _ = &arr[3..3]; - | ^^^^ - error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_unfixable.rs:14:14 + --> $DIR/reversed_empty_ranges_unfixable.rs:13:14 | LL | for _ in ANSWER..ANSWER {} | ^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors From 6bd9cd99a3da53bdda4530dde9f737a843de6c91 Mon Sep 17 00:00:00 2001 From: Jeremy Stucki <stucki.jeremy@gmail.com> Date: Wed, 21 Aug 2019 21:18:43 +0200 Subject: [PATCH 108/526] Add tests --- tests/ui/or_fun_call.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 7599b945a91..522f31b72d0 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -95,6 +95,15 @@ fn test_or_with_ctors() { let b = "b".to_string(); let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) .or(Some(Bar(b, Duration::from_secs(2)))); + + let vec = vec!["foo"]; + let _ = opt.ok_or(vec.len()); + + let array = ["foo"]; + let _ = opt.ok_or(array.len()); + + let slice = &["foo"][..]; + let _ = opt.ok_or(slice.len()); } // Issue 4514 - early return From 566377f6272b0a3b9fa65dabe1f39ee82be80d4e Mon Sep 17 00:00:00 2001 From: Jeremy Stucki <stucki.jeremy@gmail.com> Date: Wed, 21 Aug 2019 21:19:28 +0200 Subject: [PATCH 109/526] Ignore calls to 'len' --- clippy_lints/src/methods/mod.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 32b3b7f7947..c82cf57a4b1 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1614,6 +1614,21 @@ fn lint_or_fun_call<'a, 'tcx>( or_has_args: bool, span: Span, ) { + if let hir::ExprKind::MethodCall(ref path, _, ref args) = &arg.node { + if path.ident.as_str() == "len" { + let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); + + match ty.sty { + ty::Slice(_) | ty::Array(_, _) => return, + _ => (), + } + + if match_type(cx, ty, &paths::VEC) { + return; + } + } + } + // (path, fn_has_argument, methods, suffix) let know_types: &[(&[_], _, &[_], _)] = &[ (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), From bcfeb4de1589c19a7b21f04fec284e6045c0aa7a Mon Sep 17 00:00:00 2001 From: Jeremy Stucki <dev@jeremystucki.ch> Date: Mon, 25 May 2020 21:23:39 +0200 Subject: [PATCH 110/526] Fix build --- clippy_lints/src/methods/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index c82cf57a4b1..52ca962e7ef 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1614,11 +1614,11 @@ fn lint_or_fun_call<'a, 'tcx>( or_has_args: bool, span: Span, ) { - if let hir::ExprKind::MethodCall(ref path, _, ref args) = &arg.node { + if let hir::ExprKind::MethodCall(ref path, _, ref args) = &arg.kind { if path.ident.as_str() == "len" { let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); - match ty.sty { + match ty.kind { ty::Slice(_) | ty::Array(_, _) => return, _ => (), } From d9f55322cccf1e1ca1b996f8431f7ff8836d5d55 Mon Sep 17 00:00:00 2001 From: Jeremy Stucki <dev@jeremystucki.ch> Date: Mon, 25 May 2020 21:38:46 +0200 Subject: [PATCH 111/526] Update ui test --- tests/ui/or_fun_call.fixed | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index 8ea03fe4261..7bb08797ef3 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -95,6 +95,15 @@ fn test_or_with_ctors() { let b = "b".to_string(); let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) .or(Some(Bar(b, Duration::from_secs(2)))); + + let vec = vec!["foo"]; + let _ = opt.ok_or(vec.len()); + + let array = ["foo"]; + let _ = opt.ok_or(array.len()); + + let slice = &["foo"][..]; + let _ = opt.ok_or(slice.len()); } // Issue 4514 - early return From f2154e98379fcdd42ef226b6e19e9dc218422f83 Mon Sep 17 00:00:00 2001 From: returntrip <stefano@figura.im> Date: Mon, 25 May 2020 23:06:08 +0200 Subject: [PATCH 112/526] To make it easier for Linux distributions, ship the licenses text within each crate directory. --- rustc_tools_util/LICENSE-APACHE | 1 + rustc_tools_util/LICENSE-MIT | 1 + 2 files changed, 2 insertions(+) create mode 120000 rustc_tools_util/LICENSE-APACHE create mode 120000 rustc_tools_util/LICENSE-MIT diff --git a/rustc_tools_util/LICENSE-APACHE b/rustc_tools_util/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/rustc_tools_util/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/rustc_tools_util/LICENSE-MIT b/rustc_tools_util/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/rustc_tools_util/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file From a1824e187cb6d17e48e2ff039810551540a9b826 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 25 May 2020 23:09:06 +0200 Subject: [PATCH 113/526] ptr_arg: honor `allow` attr on arguments --- clippy_lints/src/ptr.rs | 10 +++++++++- clippy_lints/src/utils/sugg.rs | 2 +- tests/ui/ptr_arg.rs | 32 +++++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 2cdf9671419..4eac571f966 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -2,7 +2,7 @@ use crate::utils::ptr::get_spans; use crate::utils::{ - is_type_diagnostic_item, match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_sugg, + is_allowed, is_type_diagnostic_item, match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_sugg, span_lint_and_then, walk_ptrs_hir_ty, }; use if_chain::if_chain; @@ -150,8 +150,16 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_ let fn_def_id = cx.tcx.hir().local_def_id(fn_id); let sig = cx.tcx.fn_sig(fn_def_id); let fn_ty = sig.skip_binder(); + let body = opt_body_id.map(|id| cx.tcx.hir().body(id)); for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() { + // Honor the allow attribute on parameters. See issue 5644. + if let Some(body) = &body { + if is_allowed(cx, PTR_ARG, body.params[idx].hir_id) { + continue; + } + } + if let ty::Ref(_, ty, Mutability::Not) = ty.kind { if is_type_diagnostic_item(cx, ty, sym!(vec_type)) { let mut ty_snippet = None; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 4ebe2e2852f..73758b7eeb7 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -530,7 +530,7 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext> { /// Suggest to add an item before another. /// - /// The item should not be indented (expect for inner indentation). + /// The item should not be indented (except for inner indentation). /// /// # Example /// diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 30f39e9b063..541225e6351 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -71,7 +71,6 @@ fn false_positive_capacity_too(x: &String) -> String { #[allow(dead_code)] fn test_cow_with_ref(c: &Cow<[i32]>) {} -#[allow(dead_code)] fn test_cow(c: Cow<[i32]>) { let _c = c; } @@ -84,3 +83,34 @@ trait Foo2 { impl Foo2 for String { fn do_string(&self) {} } + +// Check that the allow attribute on parameters is honored +mod issue_5644 { + use std::borrow::Cow; + + fn allowed( + #[allow(clippy::ptr_arg)] _v: &Vec<u32>, + #[allow(clippy::ptr_arg)] _s: &String, + #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, + ) { + } + + struct S {} + impl S { + fn allowed( + #[allow(clippy::ptr_arg)] _v: &Vec<u32>, + #[allow(clippy::ptr_arg)] _s: &String, + #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, + ) { + } + } + + trait T { + fn allowed( + #[allow(clippy::ptr_arg)] _v: &Vec<u32>, + #[allow(clippy::ptr_arg)] _s: &String, + #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, + ) { + } + } +} From 67167be1679c60eefa2c314c5e4a2b673d5eef11 Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Sun, 17 May 2020 18:14:43 +0200 Subject: [PATCH 114/526] Make empty_line_after_outer_attr an early lint --- clippy_lints/Cargo.toml | 4 + clippy_lints/src/attrs.rs | 75 +++++++++++-------- tests/compile-test.rs | 2 +- tests/ui/auxiliary/proc_macro_attr.rs | 37 +++++++++ tests/ui/empty_line_after_outer_attribute.rs | 19 ++++- .../empty_line_after_outer_attribute.stderr | 12 +-- 6 files changed, 109 insertions(+), 40 deletions(-) create mode 100644 tests/ui/auxiliary/proc_macro_attr.rs diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 1c0be727834..043a79f2001 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -33,5 +33,9 @@ semver = "0.9.0" # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864> url = { version = "2.1.0", features = ["serde"] } +[dev-dependencies] +quote = "*" +syn = { version = "*", features = ["full"] } + [features] deny-warnings = [] diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 64abc9fdc71..41f125d4839 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -248,7 +248,6 @@ declare_lint_pass!(Attributes => [ INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE, - EMPTY_LINE_AFTER_OUTER_ATTR, UNKNOWN_CLIPPY_LINTS, ]); @@ -480,36 +479,6 @@ fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attrib } for attr in attrs { - let attr_item = if let AttrKind::Normal(ref attr) = attr.kind { - attr - } else { - continue; - }; - - if attr.style == AttrStyle::Outer { - if attr_item.args.inner_tokens().is_empty() || !is_present_in_source(cx, attr.span) { - return; - } - - let begin_of_attr_to_item = Span::new(attr.span.lo(), span.lo(), span.ctxt()); - let end_of_attr_to_item = Span::new(attr.span.hi(), span.lo(), span.ctxt()); - - if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) { - let lines = snippet.split('\n').collect::<Vec<_>>(); - let lines = without_block_comments(lines); - - if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 { - span_lint( - cx, - EMPTY_LINE_AFTER_OUTER_ATTR, - begin_of_attr_to_item, - "Found an empty line after an outer attribute. \ - Perhaps you forgot to add a `!` to make it an inner attribute?", - ); - } - } - } - if let Some(values) = attr.meta_item_list() { if values.len() != 1 || !attr.check_name(sym!(inline)) { continue; @@ -551,15 +520,57 @@ fn is_word(nmi: &NestedMetaItem, expected: Symbol) -> bool { } } -declare_lint_pass!(EarlyAttributes => [DEPRECATED_CFG_ATTR, MISMATCHED_TARGET_OS]); +declare_lint_pass!(EarlyAttributes => [ + DEPRECATED_CFG_ATTR, + MISMATCHED_TARGET_OS, + EMPTY_LINE_AFTER_OUTER_ATTR, +]); impl EarlyLintPass for EarlyAttributes { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::ast::Item) { + check_empty_line_after_outer_attr(cx, item); + } + fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { check_deprecated_cfg_attr(cx, attr); check_mismatched_target_os(cx, attr); } } +fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::ast::Item) { + for attr in &item.attrs { + let attr_item = if let AttrKind::Normal(ref attr) = attr.kind { + attr + } else { + return; + }; + + if attr.style == AttrStyle::Outer { + if attr_item.args.inner_tokens().is_empty() || !is_present_in_source(cx, attr.span) { + return; + } + + let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt()); + let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt()); + + if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) { + let lines = snippet.split('\n').collect::<Vec<_>>(); + let lines = without_block_comments(lines); + + if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 { + span_lint( + cx, + EMPTY_LINE_AFTER_OUTER_ATTR, + begin_of_attr_to_item, + "Found an empty line after an outer attribute. \ + Perhaps you forgot to add a `!` to make it an inner attribute?", + ); + } + } + } + } +} + fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute) { if_chain! { // check cfg_attr diff --git a/tests/compile-test.rs b/tests/compile-test.rs index a5de8429390..2758b9a7e76 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -38,7 +38,7 @@ fn clippy_driver_path() -> PathBuf { // as what we manually pass to `cargo` invocation fn third_party_crates() -> String { use std::collections::HashMap; - static CRATES: &[&str] = &["serde", "serde_derive", "regex", "clippy_lints"]; + static CRATES: &[&str] = &["serde", "serde_derive", "regex", "clippy_lints", "syn", "quote"]; let dep_dir = cargo::TARGET_LIB.join("deps"); let mut crates: HashMap<&str, PathBuf> = HashMap::with_capacity(CRATES.len()); for entry in fs::read_dir(dep_dir).unwrap() { diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs new file mode 100644 index 00000000000..e6626d57a77 --- /dev/null +++ b/tests/ui/auxiliary/proc_macro_attr.rs @@ -0,0 +1,37 @@ +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(repr128, proc_macro_hygiene, proc_macro_quote)] +#![allow(clippy::useless_conversion)] + +extern crate proc_macro; +extern crate quote; +extern crate syn; + +use proc_macro::TokenStream; +use quote::{quote, quote_spanned}; +use syn::parse_macro_input; +use syn::{parse_quote, ItemTrait, TraitItem}; + +#[proc_macro_attribute] +pub fn fake_async_trait(_args: TokenStream, input: TokenStream) -> TokenStream { + let mut item = parse_macro_input!(input as ItemTrait); + for inner in &mut item.items { + if let TraitItem::Method(method) = inner { + let sig = &method.sig; + let block = &mut method.default; + if let Some(block) = block { + let brace = block.brace_token; + + let my_block = quote_spanned!( brace.span => { + // Should not trigger `empty_line_after_outer_attr` + #[crate_type = "lib"] + #sig #block + Vec::new() + }); + *block = parse_quote!(#my_block); + } + } + } + TokenStream::from(quote!(#item)) +} diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 5343dff9da1..3e92bca986a 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,8 +1,12 @@ +// aux-build:proc_macro_attr.rs #![warn(clippy::empty_line_after_outer_attr)] #![allow(clippy::assertions_on_constants)] #![feature(custom_inner_attributes)] #![rustfmt::skip] +#[macro_use] +extern crate proc_macro_attr; + // This should produce a warning #[crate_type = "lib"] @@ -93,4 +97,17 @@ pub struct S; /* test */ pub struct T; -fn main() { } +// This should not produce a warning +// See https://github.com/rust-lang/rust-clippy/issues/5567 +#[fake_async_trait] +pub trait Bazz { + fn foo() -> Vec<u8> { + let _i = ""; + + + + vec![] + } +} + +fn main() {} diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr index d8c9786541f..bf753a732f0 100644 --- a/tests/ui/empty_line_after_outer_attribute.stderr +++ b/tests/ui/empty_line_after_outer_attribute.stderr @@ -1,5 +1,5 @@ error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:7:1 + --> $DIR/empty_line_after_outer_attribute.rs:11:1 | LL | / #[crate_type = "lib"] LL | | @@ -10,7 +10,7 @@ LL | | fn with_one_newline_and_comment() { assert!(true) } = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings` error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:19:1 + --> $DIR/empty_line_after_outer_attribute.rs:23:1 | LL | / #[crate_type = "lib"] LL | | @@ -18,7 +18,7 @@ LL | | fn with_one_newline() { assert!(true) } | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:24:1 + --> $DIR/empty_line_after_outer_attribute.rs:28:1 | LL | / #[crate_type = "lib"] LL | | @@ -27,7 +27,7 @@ LL | | fn with_two_newlines() { assert!(true) } | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:31:1 + --> $DIR/empty_line_after_outer_attribute.rs:35:1 | LL | / #[crate_type = "lib"] LL | | @@ -35,7 +35,7 @@ LL | | enum Baz { | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:39:1 + --> $DIR/empty_line_after_outer_attribute.rs:43:1 | LL | / #[crate_type = "lib"] LL | | @@ -43,7 +43,7 @@ LL | | struct Foo { | |_ error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? - --> $DIR/empty_line_after_outer_attribute.rs:47:1 + --> $DIR/empty_line_after_outer_attribute.rs:51:1 | LL | / #[crate_type = "lib"] LL | | From e3f6a8fc20ce778168e079257b7a33a47fe8541f Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Sun, 17 May 2020 19:09:07 +0200 Subject: [PATCH 115/526] Specify quote and syn versions --- clippy_lints/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 043a79f2001..11586083d8c 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -34,8 +34,8 @@ semver = "0.9.0" url = { version = "2.1.0", features = ["serde"] } [dev-dependencies] -quote = "*" -syn = { version = "*", features = ["full"] } +quote = "1.0.2" +syn = { version = "1.0.11", features = ["full"] } [features] deny-warnings = [] From cdff59e156a85d86f7abb9834e42a18fe1ee257e Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Sun, 17 May 2020 19:13:33 +0200 Subject: [PATCH 116/526] Using dev-dependencies doesn't seem to work w/ compiletest --- clippy_lints/Cargo.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 11586083d8c..7514608bc7e 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -32,8 +32,6 @@ semver = "0.9.0" # NOTE: cargo requires serde feat in its url dep # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864> url = { version = "2.1.0", features = ["serde"] } - -[dev-dependencies] quote = "1.0.2" syn = { version = "1.0.11", features = ["full"] } From fd86b3150e21df8eb6fee2f0c8b69f323146ffad Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Tue, 26 May 2020 16:51:04 +0200 Subject: [PATCH 117/526] Be less specific about quote and syn versions --- clippy_lints/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 7514608bc7e..76baf27fb2d 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -32,8 +32,8 @@ semver = "0.9.0" # NOTE: cargo requires serde feat in its url dep # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864> url = { version = "2.1.0", features = ["serde"] } -quote = "1.0.2" -syn = { version = "1.0.11", features = ["full"] } +quote = "1" +syn = { version = "1", features = ["full"] } [features] deny-warnings = [] From 1801841ae554a7778666c4c1085393b32eccf74d Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Tue, 26 May 2020 18:40:42 +0200 Subject: [PATCH 118/526] Add test cases for broader coverage --- clippy_lints/src/useless_conversion.rs | 10 ++++---- tests/ui/useless_conversion.stderr | 20 ++++++++-------- tests/ui/useless_conversion_try.rs | 8 +++++++ tests/ui/useless_conversion_try.stderr | 32 +++++++++++++++++++------- 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 1645c5777b2..7fa97b24699 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -71,7 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - "Useless conversion to the same type", + "useless conversion to the same type", "consider removing `.into()`", sugg, Applicability::MachineApplicable, // snippet @@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - "Useless conversion to the same type", + "useless conversion to the same type", "consider removing `.into_iter()`", sugg, Applicability::MachineApplicable, // snippet @@ -108,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - "Useless conversion to the same type", + "useless conversion to the same type", None, "consider removing `.try_into()`", ); @@ -139,7 +139,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - "Useless conversion to the same type", + "useless conversion to the same type", None, &hint, ); @@ -158,7 +158,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { cx, USELESS_CONVERSION, e.span, - "Useless conversion to the same type", + "useless conversion to the same type", &sugg_msg, sugg, Applicability::MachineApplicable, // snippet diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index 0b2947f7d62..84ec5370278 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -1,4 +1,4 @@ -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion.rs:6:13 | LL | let _ = T::from(val); @@ -10,55 +10,55 @@ note: the lint level is defined here LL | #![deny(clippy::useless_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion.rs:7:5 | LL | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion.rs:19:22 | LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion.rs:51:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion.rs:52:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion.rs:53:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion.rs:54:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion.rs:55:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion.rs:56:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion.rs:57:21 | LL | let _: String = format!("Hello {}", "world").into(); diff --git a/tests/ui/useless_conversion_try.rs b/tests/ui/useless_conversion_try.rs index ab4f960edb7..3787ea99144 100644 --- a/tests/ui/useless_conversion_try.rs +++ b/tests/ui/useless_conversion_try.rs @@ -31,4 +31,12 @@ fn main() { let _ = String::try_from("foo".to_string()).unwrap(); let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); let _: String = format!("Hello {}", "world").try_into().unwrap(); + let _: String = "".to_owned().try_into().unwrap(); + let _: String = match String::from("_").try_into() { + Ok(a) => a, + Err(_) => "".into(), + }; + // FIXME this is a false negative + #[allow(clippy::cmp_owned)] + if String::from("a") == TryInto::<String>::try_into(String::from("a")).unwrap() {} } diff --git a/tests/ui/useless_conversion_try.stderr b/tests/ui/useless_conversion_try.stderr index 5afb5dc45d3..b765727c168 100644 --- a/tests/ui/useless_conversion_try.stderr +++ b/tests/ui/useless_conversion_try.stderr @@ -1,4 +1,4 @@ -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion_try.rs:6:13 | LL | let _ = T::try_from(val).unwrap(); @@ -11,7 +11,7 @@ LL | #![deny(clippy::useless_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: consider removing `T::try_from()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion_try.rs:7:5 | LL | val.try_into().unwrap() @@ -19,7 +19,7 @@ LL | val.try_into().unwrap() | = help: consider removing `.try_into()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion_try.rs:29:21 | LL | let _: String = "foo".to_string().try_into().unwrap(); @@ -27,7 +27,7 @@ LL | let _: String = "foo".to_string().try_into().unwrap(); | = help: consider removing `.try_into()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion_try.rs:30:21 | LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); @@ -35,7 +35,7 @@ LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); | = help: consider removing `TryFrom::try_from()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion_try.rs:31:13 | LL | let _ = String::try_from("foo".to_string()).unwrap(); @@ -43,7 +43,7 @@ LL | let _ = String::try_from("foo".to_string()).unwrap(); | = help: consider removing `String::try_from()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion_try.rs:32:13 | LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); @@ -51,7 +51,7 @@ LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); | = help: consider removing `String::try_from()` -error: Useless conversion to the same type +error: useless conversion to the same type --> $DIR/useless_conversion_try.rs:33:21 | LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); @@ -59,5 +59,21 @@ LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); | = help: consider removing `.try_into()` -error: aborting due to 7 previous errors +error: useless conversion to the same type + --> $DIR/useless_conversion_try.rs:34:21 + | +LL | let _: String = "".to_owned().try_into().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider removing `.try_into()` + +error: useless conversion to the same type + --> $DIR/useless_conversion_try.rs:35:27 + | +LL | let _: String = match String::from("_").try_into() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider removing `.try_into()` + +error: aborting due to 9 previous errors From 7fd3bd0f57e11a65641501d6a898328ecb83ca77 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Fri, 24 Apr 2020 00:14:03 +0200 Subject: [PATCH 119/526] Register redundant_field_names and non_expressive_names as early passes --- clippy_lints/src/lib.rs | 12 ++++++------ src/driver.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 057d39d4c82..902f3d56c1e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -346,13 +346,8 @@ mod reexport { /// level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass. /// /// Used in `./src/driver.rs`. -pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &Conf) { +pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) { store.register_pre_expansion_pass(|| box write::Write::default()); - store.register_pre_expansion_pass(|| box redundant_field_names::RedundantFieldNames); - let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; - store.register_pre_expansion_pass(move || box non_expressive_names::NonExpressiveNames { - single_char_binding_names_threshold, - }); store.register_pre_expansion_pass(|| box attrs::EarlyAttributes); store.register_pre_expansion_pass(|| box dbg_macro::DbgMacro); } @@ -1066,6 +1061,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems); store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive); store.register_late_pass(|| box manual_async_fn::ManualAsyncFn); + store.register_early_pass(|| box redundant_field_names::RedundantFieldNames); + let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; + store.register_early_pass(move || box non_expressive_names::NonExpressiveNames { + single_char_binding_names_threshold, + }); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), diff --git a/src/driver.rs b/src/driver.rs index d3a7e24937f..70c47b42682 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -79,7 +79,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { let conf = clippy_lints::read_conf(&[], &sess); clippy_lints::register_plugins(&mut lint_store, &sess, &conf); - clippy_lints::register_pre_expansion_lints(&mut lint_store, &conf); + clippy_lints::register_pre_expansion_lints(&mut lint_store); clippy_lints::register_renamed(&mut lint_store); })); From 8e22d15055231fc0df4a07d57cd883fd89d8131b Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 12 May 2020 16:26:55 +0200 Subject: [PATCH 120/526] Fix fallout in redundant_field_names --- clippy_lints/src/redundant_field_names.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index b12c3c344ef..2a81170e49e 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -2,6 +2,7 @@ use crate::utils::span_lint_and_sugg; use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -36,6 +37,9 @@ declare_lint_pass!(RedundantFieldNames => [REDUNDANT_FIELD_NAMES]); impl EarlyLintPass for RedundantFieldNames { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if in_external_macro(cx.sess, expr.span) { + return; + } if let ExprKind::Struct(_, ref fields, _) = expr.kind { for field in fields { if field.is_shorthand { From 04db13eb564f6e3264a0d376ef95365b1de44797 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 12 May 2020 16:50:00 +0200 Subject: [PATCH 121/526] Fix fallout in similar_names --- clippy_lints/src/non_expressive_names.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 2b51b732075..5328773a738 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -5,6 +5,7 @@ use rustc_ast::ast::{ use rustc_ast::attr; use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor}; use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::{Ident, SymbolStr}; @@ -354,12 +355,20 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { impl EarlyLintPass for NonExpressiveNames { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if in_external_macro(cx.sess, item.span) { + return; + } + if let ItemKind::Fn(_, ref sig, _, Some(ref blk)) = item.kind { do_check(self, cx, &item.attrs, &sig.decl, blk); } } fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &AssocItem) { + if in_external_macro(cx.sess, item.span) { + return; + } + if let AssocItemKind::Fn(_, ref sig, _, Some(ref blk)) = item.kind { do_check(self, cx, &item.attrs, &sig.decl, blk); } From 0ad08109fd1c0b72d8bde3291271e4f2c8dbe66e Mon Sep 17 00:00:00 2001 From: Sora Morimoto <git@bsky.moe> Date: Wed, 27 May 2020 06:25:38 +0900 Subject: [PATCH 122/526] Bump actions/cache from v1 to v2 --- .github/workflows/clippy.yml | 2 +- .github/workflows/clippy_bors.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 8edf0c23860..5fa8009a8b4 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -49,7 +49,7 @@ jobs: run: cargo update - name: Cache cargo dir - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.cargo key: ${{ runner.os }}-x86_64-unknown-linux-gnu-${{ hashFiles('Cargo.lock') }} diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 6675a1029bb..a8a673343bf 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -94,7 +94,7 @@ jobs: run: cargo update - name: Cache cargo dir - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.cargo key: ${{ runner.os }}-${{ matrix.host }}-${{ hashFiles('Cargo.lock') }} @@ -190,7 +190,7 @@ jobs: run: cargo update - name: Cache cargo dir - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.cargo key: ${{ runner.os }}-x86_64-unknown-linux-gnu-${{ hashFiles('Cargo.lock') }} @@ -269,7 +269,7 @@ jobs: run: cargo update - name: Cache cargo dir - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ~/.cargo key: ${{ runner.os }}-x86_64-unknown-linux-gnu-${{ hashFiles('Cargo.lock') }} From 416182347589e9503408136747593ff95fb9dd13 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Wed, 27 May 2020 00:06:50 +0200 Subject: [PATCH 123/526] Avoid triggering similar names on code from expansion --- clippy_lints/src/new_without_default.rs | 10 +++++----- clippy_lints/src/non_expressive_names.rs | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 3b88e4c4cb1..e556e5d59c1 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -90,8 +90,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { return; } if sig.decl.inputs.is_empty() && name == sym!(new) && cx.access_levels.is_reachable(id) { - let self_did = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent_item(id)); - let self_ty = cx.tcx.type_of(self_did); + let self_def_id = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent_item(id)); + let self_ty = cx.tcx.type_of(self_def_id); if_chain! { if same_tys(cx, self_ty, return_ty(cx, id)); if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); @@ -112,10 +112,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { // generics if_chain! { if let Some(ref impling_types) = self.impling_types; - if let Some(self_def) = cx.tcx.type_of(self_did).ty_adt_def(); - if let Some(self_def_id) = self_def.did.as_local(); + if let Some(self_def) = cx.tcx.type_of(self_def_id).ty_adt_def(); + if let Some(self_local_did) = self_def.did.as_local(); then { - let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_def_id); + let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did); if impling_types.contains(&self_id) { return; } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 5328773a738..5f14fe97afe 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -132,7 +132,11 @@ struct SimilarNamesNameVisitor<'a, 'tcx, 'b>(&'b mut SimilarNamesLocalVisitor<'a impl<'a, 'tcx, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { fn visit_pat(&mut self, pat: &'tcx Pat) { match pat.kind { - PatKind::Ident(_, ident, _) => self.check_ident(ident), + PatKind::Ident(_, ident, _) => { + if !pat.span.from_expansion() { + self.check_ident(ident); + } + }, PatKind::Struct(_, ref fields, _) => { for field in fields { if !field.is_shorthand { From 58429c74a31fabde8555f940530039bdadde8400 Mon Sep 17 00:00:00 2001 From: Philipp Krones <hello@philkrones.com> Date: Wed, 27 May 2020 00:51:08 +0200 Subject: [PATCH 124/526] Fail bors on missing changelog --- .github/workflows/clippy_bors.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 6675a1029bb..eb8da9dcc88 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -312,7 +312,7 @@ jobs: name: bors test finished if: github.event.pusher.name == 'bors' && success() runs-on: ubuntu-latest - needs: [base, integration] + needs: [changelog, base, integration_build, integration] steps: - name: Mark the job as successful @@ -322,7 +322,7 @@ jobs: name: bors test finished if: github.event.pusher.name == 'bors' && (failure() || cancelled()) runs-on: ubuntu-latest - needs: [base, integration] + needs: [changelog, base, integration_build, integration] steps: - name: Mark the job as a failure From 3089c3b3077fa8ae0b6f68c5f56650bf726e3298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Wed, 27 May 2020 13:55:57 +0200 Subject: [PATCH 125/526] rustup https://github.com/rust-lang/rust/pull/72342, allow unused_crate_dependencies --- tests/ui/cognitive_complexity.rs | 2 +- tests/ui/cognitive_complexity_attr_used.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/cognitive_complexity.rs b/tests/ui/cognitive_complexity.rs index 1d3fe405521..912e6788afd 100644 --- a/tests/ui/cognitive_complexity.rs +++ b/tests/ui/cognitive_complexity.rs @@ -1,6 +1,6 @@ #![allow(clippy::all)] #![warn(clippy::cognitive_complexity)] -#![allow(unused)] +#![allow(unused, unused_crate_dependencies)] #[rustfmt::skip] fn main() { diff --git a/tests/ui/cognitive_complexity_attr_used.rs b/tests/ui/cognitive_complexity_attr_used.rs index 403eff566ed..771a26fc9a8 100644 --- a/tests/ui/cognitive_complexity_attr_used.rs +++ b/tests/ui/cognitive_complexity_attr_used.rs @@ -1,5 +1,5 @@ -#![warn(clippy::cognitive_complexity)] -#![warn(unused)] +#![warn(unused, clippy::cognitive_complexity)] +#![allow(unused_crate_dependencies)] fn main() { kaboom(); From 64a05f56c33d4754808ef85e634f72a9053c56fd Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 28 May 2020 00:36:15 +0200 Subject: [PATCH 126/526] len_zero: skip ranges if feature `range_is_empty` is not enabled --- clippy_lints/src/len_zero.rs | 17 ++++++++++++++++- tests/ui/len_zero.fixed | 8 ++++++++ tests/ui/len_zero.rs | 8 ++++++++ tests/ui/len_zero_ranges.fixed | 14 ++++++++++++++ tests/ui/len_zero_ranges.rs | 14 ++++++++++++++ tests/ui/len_zero_ranges.stderr | 10 ++++++++++ 6 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/ui/len_zero_ranges.fixed create mode 100644 tests/ui/len_zero_ranges.rs create mode 100644 tests/ui/len_zero_ranges.stderr diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 2ec0b5a8d6f..f5bfede75a7 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,4 +1,4 @@ -use crate::utils::{get_item_name, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::{get_item_name, higher, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; use rustc_ast::ast::LitKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -259,6 +259,17 @@ fn check_len( /// Checks if this type has an `is_empty` method. fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + /// Special case ranges until `range_is_empty` is stabilized. See issue 3807. + fn should_skip_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + higher::range(cx, expr).map_or(false, |_| { + !cx.tcx + .features() + .declared_lib_features + .iter() + .any(|(name, _)| name.as_str() == "range_is_empty") + }) + } + /// Gets an `AssocItem` and return true if it matches `is_empty(self)`. fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssocItem) -> bool { if let ty::AssocKind::Fn = item.kind { @@ -284,6 +295,10 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { }) } + if should_skip_range(cx, expr) { + return false; + } + let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); match ty.kind { ty::Dynamic(ref tt, ..) => { diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed index 624e5ef8fcf..a29b832eb60 100644 --- a/tests/ui/len_zero.fixed +++ b/tests/ui/len_zero.fixed @@ -141,3 +141,11 @@ fn main() { fn test_slice(b: &[u8]) { if !b.is_empty() {} } + +mod issue_3807 { + // Avoid suggesting changes to ranges if the user did not enable `range_is_empty`. + // See https://github.com/rust-lang/rust/issues/48111#issuecomment-445132965 + fn no_suggestion() { + let _ = (0..42).len() == 0; + } +} diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index 7fba971cfd8..8fd0093f4fd 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -141,3 +141,11 @@ fn main() { fn test_slice(b: &[u8]) { if b.len() != 0 {} } + +mod issue_3807 { + // Avoid suggesting changes to ranges if the user did not enable `range_is_empty`. + // See https://github.com/rust-lang/rust/issues/48111#issuecomment-445132965 + fn no_suggestion() { + let _ = (0..42).len() == 0; + } +} diff --git a/tests/ui/len_zero_ranges.fixed b/tests/ui/len_zero_ranges.fixed new file mode 100644 index 00000000000..7da26f8ff4d --- /dev/null +++ b/tests/ui/len_zero_ranges.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +#![feature(range_is_empty)] +#![warn(clippy::len_zero)] +#![allow(unused)] + +mod issue_3807 { + // With the feature enabled, `is_empty` should be suggested + fn suggestion_is_fine() { + let _ = (0..42).is_empty(); + } +} + +fn main() {} diff --git a/tests/ui/len_zero_ranges.rs b/tests/ui/len_zero_ranges.rs new file mode 100644 index 00000000000..be7b4244bc0 --- /dev/null +++ b/tests/ui/len_zero_ranges.rs @@ -0,0 +1,14 @@ +// run-rustfix + +#![feature(range_is_empty)] +#![warn(clippy::len_zero)] +#![allow(unused)] + +mod issue_3807 { + // With the feature enabled, `is_empty` should be suggested + fn suggestion_is_fine() { + let _ = (0..42).len() == 0; + } +} + +fn main() {} diff --git a/tests/ui/len_zero_ranges.stderr b/tests/ui/len_zero_ranges.stderr new file mode 100644 index 00000000000..6e5fa41fb08 --- /dev/null +++ b/tests/ui/len_zero_ranges.stderr @@ -0,0 +1,10 @@ +error: length comparison to zero + --> $DIR/len_zero_ranges.rs:10:17 + | +LL | let _ = (0..42).len() == 0; + | ^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(0..42).is_empty()` + | + = note: `-D clippy::len-zero` implied by `-D warnings` + +error: aborting due to previous error + From 7b490903809ce5c03c83869357a68e88f8cc0799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Wed, 27 May 2020 14:08:31 +0200 Subject: [PATCH 127/526] clippy_dev: add ra_setup This takes an absolute path to a rustc repo and adds path-dependencies that point towards the respective rustc subcrates into the Cargo.tomls of the clippy and clippy_lints crate. This allows rustc-analyzer to show proper type annotations etc on rustc-internals inside the clippy repo. Usage: cargo dev ra-setup /absolute/path/to/rust/ cc https://github.com/rust-analyzer/rust-analyzer/issues/3517 cc https://github.com/rust-lang/rust-clippy/issues/5514 --- clippy_dev/src/lib.rs | 3 +- clippy_dev/src/main.rs | 16 ++++++- clippy_dev/src/ra_setup.rs | 90 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 clippy_dev/src/ra_setup.rs diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 6fdd282c684..5baa31d5cde 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -11,6 +11,7 @@ use walkdir::WalkDir; pub mod fmt; pub mod new_lint; +pub mod ra_setup; pub mod stderr_length_check; pub mod update_lints; @@ -400,7 +401,7 @@ fn test_replace_region_no_changes() { changed: false, new_lines: "123\n456\n789".to_string(), }; - let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, || vec![]); + let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, Vec::new); assert_eq!(expected, result); } diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index d99235f7c07..281037ae37c 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -1,7 +1,7 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] use clap::{App, Arg, SubCommand}; -use clippy_dev::{fmt, new_lint, stderr_length_check, update_lints}; +use clippy_dev::{fmt, new_lint, ra_setup, stderr_length_check, update_lints}; fn main() { let matches = App::new("Clippy developer tooling") @@ -87,6 +87,19 @@ fn main() { SubCommand::with_name("limit_stderr_length") .about("Ensures that stderr files do not grow longer than a certain amount of lines."), ) + .subcommand( + SubCommand::with_name("ra-setup") + .about("Alter dependencies so rust-analyzer can find rustc internals") + .arg( + Arg::with_name("rustc-repo-path") + .long("repo-path") + .short("r") + .help("The path to a rustc repo that will be used for setting the dependencies") + .takes_value(true) + .value_name("path") + .required(true), + ), + ) .get_matches(); match matches.subcommand() { @@ -115,6 +128,7 @@ fn main() { ("limit_stderr_length", _) => { stderr_length_check::check(); }, + ("ra-setup", Some(matches)) => ra_setup::run(matches.value_of("rustc-repo-path")), _ => {}, } } diff --git a/clippy_dev/src/ra_setup.rs b/clippy_dev/src/ra_setup.rs new file mode 100644 index 00000000000..8617445c8a6 --- /dev/null +++ b/clippy_dev/src/ra_setup.rs @@ -0,0 +1,90 @@ +#![allow(clippy::filter_map)] + +use std::fs; +use std::fs::File; +use std::io::prelude::*; +use std::path::PathBuf; + +// This module takes an absolute path to a rustc repo and alters the dependencies to point towards +// the respective rustc subcrates instead of using extern crate xyz. +// This allows rust analyzer to analyze rustc internals and show proper information inside clippy +// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details + +pub fn run(rustc_path: Option<&str>) { + // we can unwrap here because the arg is required here + let rustc_path = PathBuf::from(rustc_path.unwrap()); + assert!(rustc_path.is_dir(), "path is not a directory"); + let rustc_source_basedir = rustc_path.join("src"); + assert!( + rustc_source_basedir.is_dir(), + "are you sure the path leads to a rustc repo?" + ); + + let clippy_root_manifest = fs::read_to_string("Cargo.toml").expect("failed to read ./Cargo.toml"); + let clippy_root_lib_rs = fs::read_to_string("src/driver.rs").expect("failed to read ./src/driver.rs"); + inject_deps_into_manifest( + &rustc_source_basedir, + "Cargo.toml", + &clippy_root_manifest, + &clippy_root_lib_rs, + ) + .expect("Failed to inject deps into ./Cargo.toml"); + + let clippy_lints_manifest = + fs::read_to_string("clippy_lints/Cargo.toml").expect("failed to read ./clippy_lints/Cargo.toml"); + let clippy_lints_lib_rs = + fs::read_to_string("clippy_lints/src/lib.rs").expect("failed to read ./clippy_lints/src/lib.rs"); + inject_deps_into_manifest( + &rustc_source_basedir, + "clippy_lints/Cargo.toml", + &clippy_lints_manifest, + &clippy_lints_lib_rs, + ) + .expect("Failed to inject deps into ./clippy_lints/Cargo.toml"); +} + +fn inject_deps_into_manifest( + rustc_source_dir: &PathBuf, + manifest_path: &str, + cargo_toml: &str, + lib_rs: &str, +) -> std::io::Result<()> { + let extern_crates = lib_rs + .lines() + // get the deps + .filter(|line| line.starts_with("extern crate")) + // we have something like "extern crate foo;", we only care about the "foo" + // ↓ ↓ + // extern crate rustc_middle; + .map(|s| &s[13..(s.len() - 1)]); + + let new_deps = extern_crates.map(|dep| { + // format the dependencies that are going to be put inside the Cargo.toml + format!( + "{dep} = {{ path = \"{source_path}/lib{dep}\" }}\n", + dep = dep, + source_path = rustc_source_dir.display() + ) + }); + + // format a new [dependencies]-block with the new deps we need to inject + let mut all_deps = String::from("[dependencies]\n"); + new_deps.for_each(|dep_line| { + all_deps.push_str(&dep_line); + }); + + // replace "[dependencies]" with + // [dependencies] + // dep1 = { path = ... } + // dep2 = { path = ... } + // etc + let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1); + + // println!("{}", new_manifest); + let mut file = File::create(manifest_path)?; + file.write_all(new_manifest.as_bytes())?; + + println!("Dependency paths injected: {}", manifest_path); + + Ok(()) +} From b92cc8a08d74fb412bc444a4361df51b0c95401c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Fri, 29 May 2020 22:46:05 +0200 Subject: [PATCH 128/526] add testcase that no longer ICEs Fixes #3969 --- tests/ui/crashes/ice-3969.rs | 51 ++++++++++++++++++++++++++++++++ tests/ui/crashes/ice-3969.stderr | 22 ++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tests/ui/crashes/ice-3969.rs create mode 100644 tests/ui/crashes/ice-3969.stderr diff --git a/tests/ui/crashes/ice-3969.rs b/tests/ui/crashes/ice-3969.rs new file mode 100644 index 00000000000..4feab7910b7 --- /dev/null +++ b/tests/ui/crashes/ice-3969.rs @@ -0,0 +1,51 @@ +// https://github.com/rust-lang/rust-clippy/issues/3969 +// used to crash: error: internal compiler error: +// src/librustc_traits/normalize_erasing_regions.rs:43: could not fully normalize `<i32 as +// std::iter::Iterator>::Item test from rustc ./ui/trivial-bounds/trivial-bounds-inconsistent.rs + +// Check that tautalogically false bounds are accepted, and are used +// in type inference. +#![feature(trivial_bounds)] +#![allow(unused)] + +trait A {} + +impl A for i32 {} + +struct Dst<X: ?Sized> { + x: X, +} + +struct TwoStrs(str, str) +where + str: Sized; + +fn unsized_local() +where + for<'a> Dst<A + 'a>: Sized, +{ + let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>); +} + +fn return_str() -> str +where + str: Sized, +{ + *"Sized".to_string().into_boxed_str() +} + +fn use_op(s: String) -> String +where + String: ::std::ops::Neg<Output = String>, +{ + -s +} + +fn use_for() +where + i32: Iterator, +{ + for _ in 2i32 {} +} + +fn main() {} diff --git a/tests/ui/crashes/ice-3969.stderr b/tests/ui/crashes/ice-3969.stderr new file mode 100644 index 00000000000..923db0664a7 --- /dev/null +++ b/tests/ui/crashes/ice-3969.stderr @@ -0,0 +1,22 @@ +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/ice-3969.rs:25:17 + | +LL | for<'a> Dst<A + 'a>: Sized, + | ^^^^^^ help: use `dyn`: `dyn A + 'a` + | + = note: `-D bare-trait-objects` implied by `-D warnings` + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/ice-3969.rs:27:16 + | +LL | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>); + | ^ help: use `dyn`: `dyn A` + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/ice-3969.rs:27:57 + | +LL | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>); + | ^ help: use `dyn`: `dyn A` + +error: aborting due to 3 previous errors + From 5faab874f9f8655c8f284944b5acdede5c088af4 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Sat, 23 May 2020 00:07:09 +0200 Subject: [PATCH 129/526] new lint: vec_resize_to_zero --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 +++ clippy_lints/src/utils/paths.rs | 1 + clippy_lints/src/vec_resize_to_zero.rs | 59 ++++++++++++++++++++++++++ src/lintlist/mod.rs | 7 +++ tests/ui/vec_resize_to_zero.rs | 15 +++++++ tests/ui/vec_resize_to_zero.stderr | 13 ++++++ 7 files changed, 101 insertions(+) create mode 100644 clippy_lints/src/vec_resize_to_zero.rs create mode 100644 tests/ui/vec_resize_to_zero.rs create mode 100644 tests/ui/vec_resize_to_zero.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ac9057199f..f7dae3dcfff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1630,6 +1630,7 @@ Released 2018-09-13 [`useless_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute [`useless_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec [`vec_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box +[`vec_resize_to_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_resize_to_zero [`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask [`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads [`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 902f3d56c1e..4f0ecab393d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -325,6 +325,7 @@ mod unwrap; mod use_self; mod useless_conversion; mod vec; +mod vec_resize_to_zero; mod verbose_file_reads; mod wildcard_dependencies; mod wildcard_imports; @@ -847,6 +848,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &utils::internal_lints::OUTER_EXPN_EXPN_DATA, &utils::internal_lints::PRODUCE_ICE, &vec::USELESS_VEC, + &vec_resize_to_zero::VEC_RESIZE_TO_ZERO, &verbose_file_reads::VERBOSE_FILE_READS, &wildcard_dependencies::WILDCARD_DEPENDENCIES, &wildcard_imports::ENUM_GLOB_USE, @@ -1062,6 +1064,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive); store.register_late_pass(|| box manual_async_fn::ManualAsyncFn); store.register_early_pass(|| box redundant_field_names::RedundantFieldNames); + store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero); let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; store.register_early_pass(move || box non_expressive_names::NonExpressiveNames { single_char_binding_names_threshold, @@ -1430,6 +1433,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&unwrap::UNNECESSARY_UNWRAP), LintId::of(&useless_conversion::USELESS_CONVERSION), LintId::of(&vec::USELESS_VEC), + LintId::of(&vec_resize_to_zero::VEC_RESIZE_TO_ZERO), LintId::of(&write::PRINTLN_EMPTY_STRING), LintId::of(&write::PRINT_LITERAL), LintId::of(&write::PRINT_WITH_NEWLINE), @@ -1677,6 +1681,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS), LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), LintId::of(&unwrap::PANICKING_UNWRAP), + LintId::of(&vec_resize_to_zero::VEC_RESIZE_TO_ZERO), ]); store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![ diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 779da7e6bf2..3b7e9739211 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -138,5 +138,6 @@ pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"]; pub const VEC_DEQUE: [&str; 4] = ["alloc", "collections", "vec_deque", "VecDeque"]; pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"]; pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"]; +pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"]; pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"]; pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"]; diff --git a/clippy_lints/src/vec_resize_to_zero.rs b/clippy_lints/src/vec_resize_to_zero.rs new file mode 100644 index 00000000000..86cbfa8203d --- /dev/null +++ b/clippy_lints/src/vec_resize_to_zero.rs @@ -0,0 +1,59 @@ +use crate::utils::span_lint_and_then; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Spanned; + +use crate::utils::{match_def_path, paths}; +use rustc_ast::ast::LitKind; +use rustc_hir as hir; + +declare_clippy_lint! { + /// **What it does:** Finds occurences of `Vec::resize(0, an_int)` + /// + /// **Why is this bad?** This is probably an argument inversion mistake. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// vec!(1, 2, 3, 4, 5).resize(0, 5) + /// ``` + pub VEC_RESIZE_TO_ZERO, + correctness, + "emptying a vector with `resize(0, an_int)` instead of `clear()` is probably an argument inversion mistake" +} + +declare_lint_pass!(VecResizeToZero => [VEC_RESIZE_TO_ZERO]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VecResizeToZero { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + if_chain! { + if let hir::ExprKind::MethodCall(path_segment, _, ref args) = expr.kind; + if let Some(method_def_id) = cx.tables.type_dependent_def_id(expr.hir_id); + if match_def_path(cx, method_def_id, &paths::VEC_RESIZE) && args.len() == 3; + if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = args[1].kind; + if let ExprKind::Lit(Spanned { node: LitKind::Int(..), .. }) = args[2].kind; + then { + let method_call_span = expr.span.with_lo(path_segment.ident.span.lo()); + span_lint_and_then( + cx, + VEC_RESIZE_TO_ZERO, + expr.span, + "emptying a vector with `resize`", + |db| { + db.help("the arguments may be inverted..."); + db.span_suggestion( + method_call_span, + "...or you can empty the vector with", + "clear()".to_string(), + Applicability::MaybeIncorrect, + ); + }, + ); + } + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index f63301c7db0..1e94ca00c14 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2460,6 +2460,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "types", }, + Lint { + name: "vec_resize_to_zero", + group: "correctness", + desc: "emptying a vector with `resize(0, an_int)` instead of `clear()` is probably an argument inversion mistake", + deprecation: None, + module: "vec_resize_to_zero", + }, Lint { name: "verbose_bit_mask", group: "style", diff --git a/tests/ui/vec_resize_to_zero.rs b/tests/ui/vec_resize_to_zero.rs new file mode 100644 index 00000000000..0263e2f5f20 --- /dev/null +++ b/tests/ui/vec_resize_to_zero.rs @@ -0,0 +1,15 @@ +#![warn(clippy::vec_resize_to_zero)] + +fn main() { + // applicable here + vec![1, 2, 3, 4, 5].resize(0, 5); + + // not applicable + vec![1, 2, 3, 4, 5].resize(2, 5); + + // applicable here, but only implemented for integer litterals for now + vec!["foo", "bar", "baz"].resize(0, "bar"); + + // not applicable + vec!["foo", "bar", "baz"].resize(2, "bar") +} diff --git a/tests/ui/vec_resize_to_zero.stderr b/tests/ui/vec_resize_to_zero.stderr new file mode 100644 index 00000000000..feb846298c6 --- /dev/null +++ b/tests/ui/vec_resize_to_zero.stderr @@ -0,0 +1,13 @@ +error: emptying a vector with `resize` + --> $DIR/vec_resize_to_zero.rs:5:5 + | +LL | vec![1, 2, 3, 4, 5].resize(0, 5); + | ^^^^^^^^^^^^^^^^^^^^------------ + | | + | help: ...or you can empty the vector with: `clear()` + | + = note: `-D clippy::vec-resize-to-zero` implied by `-D warnings` + = help: the arguments may be inverted... + +error: aborting due to previous error + From 37381d33a4761a064311dd95fbc54b5da6ad3766 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sun, 31 May 2020 14:05:57 +0200 Subject: [PATCH 130/526] Fix sync fallout --- clippy_lints/src/needless_pass_by_value.rs | 8 +------- clippy_lints/src/write.rs | 13 ++++++------- tests/compile-test.rs | 7 ++++--- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 218b0d27f74..9c508fc0e4a 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -173,13 +173,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { !preds.is_empty() && { let ty_empty_region = cx.tcx.mk_imm_ref(cx.tcx.lifetimes.re_root_empty, ty); preds.iter().all(|t| { - let ty_params = &t - .skip_binder() - .trait_ref - .substs - .iter() - .skip(1) - .collect::<Vec<_>>(); + let ty_params = &t.skip_binder().trait_ref.substs.iter().skip(1).collect::<Vec<_>>(); implements_trait(cx, ty_empty_region, t.def_id(), ty_params) }) }, diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index dfa6223f1b9..5f794598052 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -279,13 +279,12 @@ impl EarlyLintPass for Write { if let (Some(fmt_str), expr) = self.check_tts(cx, &mac.args.inner_tokens(), true) { if fmt_str.symbol == Symbol::intern("") { let mut applicability = Applicability::MachineApplicable; - let suggestion = expr.map_or_else( - move || { - applicability = Applicability::HasPlaceholders; - Cow::Borrowed("v") - }, - move |expr| snippet_with_applicability(cx, expr.span, "v", &mut applicability), - ); + let suggestion = if let Some(e) = expr { + snippet_with_applicability(cx, e.span, "v", &mut applicability) + } else { + applicability = Applicability::HasPlaceholders; + Cow::Borrowed("v") + }; span_lint_and_sugg( cx, diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 1c4914a470c..7bd5f09f333 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -153,9 +153,6 @@ fn run_ui_toml(config: &mut compiletest::Config) { } fn run_ui_cargo(config: &mut compiletest::Config) { - if cargo::is_rustc_test_suite() { - return; - } fn run_tests( config: &compiletest::Config, filter: &Option<String>, @@ -216,6 +213,10 @@ fn run_ui_cargo(config: &mut compiletest::Config) { Ok(result) } + if cargo::is_rustc_test_suite() { + return; + } + config.mode = TestMode::Ui; config.src_base = Path::new("tests").join("ui-cargo").canonicalize().unwrap(); From 0bcfae92f80d31cad4e5fb687da8033a38d06a32 Mon Sep 17 00:00:00 2001 From: djugei <ddjugei@gmail.com> Date: Sun, 31 May 2020 15:41:33 +0200 Subject: [PATCH 131/526] moved cast_ptr_alignment to pedantic and expanded documentation --- clippy_lints/src/types.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 6ed9ff22e46..3ac99e24684 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -974,7 +974,8 @@ declare_clippy_lint! { /// behavior. /// /// **Known problems:** Using `std::ptr::read_unaligned` and `std::ptr::write_unaligned` or similar - /// on the resulting pointer is fine. + /// on the resulting pointer is fine. Is over-zealous: Casts with manual alignment checks or casts like + /// u64-> u8 -> u16 can be fine. Miri is able to do a more in-depth analysis. /// /// **Example:** /// ```rust @@ -982,7 +983,7 @@ declare_clippy_lint! { /// let _ = (&mut 1u8 as *mut u8) as *mut u16; /// ``` pub CAST_PTR_ALIGNMENT, - correctness, + pedantic, "cast from a pointer to a more-strictly-aligned pointer" } From 18b5ceed7991e3d8616b74b42de26330ca4c40db Mon Sep 17 00:00:00 2001 From: djugei <ddjugei@gmail.com> Date: Sun, 31 May 2020 16:00:29 +0200 Subject: [PATCH 132/526] ran update_lints --- clippy_lints/src/lib.rs | 3 +-- src/lintlist/mod.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 902f3d56c1e..6475fa67d25 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1164,6 +1164,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::CAST_POSSIBLE_TRUNCATION), LintId::of(&types::CAST_POSSIBLE_WRAP), LintId::of(&types::CAST_PRECISION_LOSS), + LintId::of(&types::CAST_PTR_ALIGNMENT), LintId::of(&types::CAST_SIGN_LOSS), LintId::of(&types::IMPLICIT_HASHER), LintId::of(&types::INVALID_UPCAST_COMPARISONS), @@ -1410,7 +1411,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::ABSURD_EXTREME_COMPARISONS), LintId::of(&types::BORROWED_BOX), LintId::of(&types::BOX_VEC), - LintId::of(&types::CAST_PTR_ALIGNMENT), LintId::of(&types::CAST_REF_TO_MUT), LintId::of(&types::CHAR_LIT_AS_U8), LintId::of(&types::FN_TO_NUMERIC_CAST), @@ -1669,7 +1669,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&transmute::WRONG_TRANSMUTE), LintId::of(&transmuting_null::TRANSMUTING_NULL), LintId::of(&types::ABSURD_EXTREME_COMPARISONS), - LintId::of(&types::CAST_PTR_ALIGNMENT), LintId::of(&types::CAST_REF_TO_MUT), LintId::of(&types::UNIT_CMP), LintId::of(&unicode::ZERO_WIDTH_SPACE), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index f63301c7db0..b9c84654593 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -166,7 +166,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ }, Lint { name: "cast_ptr_alignment", - group: "correctness", + group: "pedantic", desc: "cast from a pointer to a more-strictly-aligned pointer", deprecation: None, module: "types", From 6122612232976c1ac766a5d415265eb3eb30e72c Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Sun, 31 May 2020 17:38:59 +0200 Subject: [PATCH 133/526] Increase cargo_metadata version to 0.9.1 `clippy_lints` makes use of `dep_kinds` on `NodeDep` but this was only added in versoin 0.9.1. Compiling with 0.9.0 will fail because of this. --- Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6999b6bd740..836897927b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tempfile = { version = "3.1.0", optional = true } lazy_static = "1.0" [dev-dependencies] -cargo_metadata = "0.9.0" +cargo_metadata = "0.9.1" compiletest_rs = { version = "0.5.0", features = ["tmp"] } tester = "0.7" lazy_static = "1.0" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 76baf27fb2d..98391732d18 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -17,7 +17,7 @@ keywords = ["clippy", "lint", "plugin"] edition = "2018" [dependencies] -cargo_metadata = "0.9.0" +cargo_metadata = "0.9.1" if_chain = "1.0.0" itertools = "0.9" lazy_static = "1.0.2" From 0ab823c509897ce2f516feb760fe1bf02cf77443 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 26 Aug 2019 18:34:30 +0200 Subject: [PATCH 134/526] Rework suggestion generation of `unit_arg` lint --- clippy_lints/src/types.rs | 42 ++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 3ac99e24684..8fcca4b7bb9 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -779,6 +779,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { match expr.kind { ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args) => { + let mut args_to_recover = vec![]; for arg in args { if is_unit(cx.tables.expr_ty(arg)) && !is_unit_literal(arg) { if let ExprKind::Match(.., match_source) = &arg.kind { @@ -787,17 +788,40 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { } } - span_lint_and_sugg( - cx, - UNIT_ARG, - arg.span, - "passing a unit value to a function", - "if you intended to pass a unit value, use a unit literal instead", - "()".to_string(), - Applicability::MaybeIncorrect, - ); + args_to_recover.push(arg); } } + if !args_to_recover.is_empty() { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_then(cx, UNIT_ARG, expr.span, "passing a unit value to a function", |db| { + db.span_suggestion( + expr.span.with_hi(expr.span.lo()), + "move the expressions in front of the call...", + format!( + "{} ", + args_to_recover + .iter() + .map(|arg| { + format!( + "{};", + snippet_with_applicability(cx, arg.span, "..", &mut applicability) + ) + }) + .collect::<Vec<String>>() + .join(" ") + ), + applicability, + ); + db.multipart_suggestion( + "...and use unit literals instead", + args_to_recover + .iter() + .map(|arg| (arg.span, "()".to_string())) + .collect::<Vec<_>>(), + applicability, + ); + }); + } }, _ => (), } From 380d941a045dc213ae28807d74fc32d1b1841e22 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 26 Aug 2019 19:35:25 +0200 Subject: [PATCH 135/526] Adapt stderr and fixed files --- tests/ui/unit_arg.fixed | 29 +++++++--- tests/ui/unit_arg.rs | 10 +++- tests/ui/unit_arg.stderr | 112 ++++++++++++++++++++++++++++++--------- 3 files changed, 118 insertions(+), 33 deletions(-) diff --git a/tests/ui/unit_arg.fixed b/tests/ui/unit_arg.fixed index a739cf7ad81..67c6bdf8873 100644 --- a/tests/ui/unit_arg.fixed +++ b/tests/ui/unit_arg.fixed @@ -1,6 +1,6 @@ // run-rustfix #![warn(clippy::unit_arg)] -#![allow(unused_braces, clippy::no_effect, unused_must_use)] +#![allow(clippy::no_effect, unused_must_use, unused_variables)] use std::fmt::Debug; @@ -21,13 +21,21 @@ impl Bar { } fn bad() { - foo(()); - foo(()); - foo(()); - foo(()); - foo3((), 2, 2); + {}; foo(()); + { + 1; + }; foo(()); + foo(1); foo(()); + { + foo(1); + foo(2); + }; foo(()); + {}; foo3((), 2, 2); let b = Bar; - b.bar(()); + { + 1; + }; b.bar(()); + foo(0); foo(1); taking_multiple_units((), ()); } fn ok() { @@ -58,6 +66,13 @@ mod issue_2945 { } } +#[allow(dead_code)] +fn returning_expr() -> Option<()> { + foo(1); Some(()) +} + +fn taking_multiple_units(a: (), b: ()) {} + fn main() { bad(); ok(); diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index d90c49f79de..c6e465b2e4c 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -1,6 +1,6 @@ // run-rustfix #![warn(clippy::unit_arg)] -#![allow(unused_braces, clippy::no_effect, unused_must_use)] +#![allow(clippy::no_effect, unused_must_use, unused_variables)] use std::fmt::Debug; @@ -35,6 +35,7 @@ fn bad() { b.bar({ 1; }); + taking_multiple_units(foo(0), foo(1)); } fn ok() { @@ -65,6 +66,13 @@ mod issue_2945 { } } +#[allow(dead_code)] +fn returning_expr() -> Option<()> { + Some(foo(1)) +} + +fn taking_multiple_units(a: (), b: ()) {} + fn main() { bad(); ok(); diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index 21ccc684ea9..ce9ab2f1271 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,79 +1,141 @@ error: passing a unit value to a function - --> $DIR/unit_arg.rs:24:9 + --> $DIR/unit_arg.rs:24:5 | LL | foo({}); - | ^^ + | ^^^^^^^ | = note: `-D clippy::unit-arg` implied by `-D warnings` -help: if you intended to pass a unit value, use a unit literal instead +help: move the expressions in front of the call... + | +LL | {}; foo({}); + | ^^^ +help: ...and use unit literals instead | LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:25:9 + --> $DIR/unit_arg.rs:25:5 | -LL | foo({ - | _________^ +LL | / foo({ LL | | 1; LL | | }); - | |_____^ + | |______^ | -help: if you intended to pass a unit value, use a unit literal instead +help: move the expressions in front of the call... + | +LL | { +LL | 1; +LL | }; foo({ + | +help: ...and use unit literals instead | LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:28:9 + --> $DIR/unit_arg.rs:28:5 | LL | foo(foo(1)); - | ^^^^^^ + | ^^^^^^^^^^^ | -help: if you intended to pass a unit value, use a unit literal instead +help: move the expressions in front of the call... + | +LL | foo(1); foo(foo(1)); + | ^^^^^^^ +help: ...and use unit literals instead | LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:29:9 + --> $DIR/unit_arg.rs:29:5 | -LL | foo({ - | _________^ +LL | / foo({ LL | | foo(1); LL | | foo(2); LL | | }); - | |_____^ + | |______^ | -help: if you intended to pass a unit value, use a unit literal instead +help: move the expressions in front of the call... + | +LL | { +LL | foo(1); +LL | foo(2); +LL | }; foo({ + | +help: ...and use unit literals instead | LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:33:10 + --> $DIR/unit_arg.rs:33:5 | LL | foo3({}, 2, 2); - | ^^ + | ^^^^^^^^^^^^^^ | -help: if you intended to pass a unit value, use a unit literal instead +help: move the expressions in front of the call... + | +LL | {}; foo3({}, 2, 2); + | ^^^ +help: ...and use unit literals instead | LL | foo3((), 2, 2); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:35:11 + --> $DIR/unit_arg.rs:35:5 | -LL | b.bar({ - | ___________^ +LL | / b.bar({ LL | | 1; LL | | }); - | |_____^ + | |______^ | -help: if you intended to pass a unit value, use a unit literal instead +help: move the expressions in front of the call... + | +LL | { +LL | 1; +LL | }; b.bar({ + | +help: ...and use unit literals instead | LL | b.bar(()); | ^^ -error: aborting due to 6 previous errors +error: passing a unit value to a function + --> $DIR/unit_arg.rs:38:5 + | +LL | taking_multiple_units(foo(0), foo(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: move the expressions in front of the call... + | +LL | foo(0); foo(1); taking_multiple_units(foo(0), foo(1)); + | ^^^^^^^^^^^^^^^ +help: ...and use unit literals instead + | +LL | taking_multiple_units((), foo(1)); + | ^^ +help: ...and use unit literals instead + | +LL | taking_multiple_units(foo(0), ()); + | ^^ + +error: passing a unit value to a function + --> $DIR/unit_arg.rs:71:5 + | +LL | Some(foo(1)) + | ^^^^^^^^^^^^ + | +help: move the expressions in front of the call... + | +LL | foo(1); Some(foo(1)) + | ^^^^^^^ +help: ...and use unit literals instead + | +LL | Some(()) + | ^^ + +error: aborting due to 8 previous errors From a1a1a4b82a35b810570dbf7d2ee7f00896bee232 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 26 Aug 2019 21:43:29 +0200 Subject: [PATCH 136/526] Use multiple span_suggestions instead of multipart_suggestion multipart suggestions aren't autofixable by rustfix yet --- clippy_lints/src/types.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 8fcca4b7bb9..3fbea77757d 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -812,14 +812,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { ), applicability, ); - db.multipart_suggestion( - "...and use unit literals instead", - args_to_recover - .iter() - .map(|arg| (arg.span, "()".to_string())) - .collect::<Vec<_>>(), - applicability, - ); + for arg in args_to_recover { + db.span_suggestion( + arg.span, + "...and use unit literals instead", + "()".to_string(), + applicability, + ); + } }); } }, From 0f69cafc2dd77d573e24870887a4a13cfe50515a Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 17 Feb 2020 18:10:59 +0100 Subject: [PATCH 137/526] Rework suggestion generation and use multipart_suggestion again --- clippy_lints/src/types.rs | 55 +++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 3fbea77757d..c95bd5d72bc 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -794,32 +794,43 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { if !args_to_recover.is_empty() { let mut applicability = Applicability::MachineApplicable; span_lint_and_then(cx, UNIT_ARG, expr.span, "passing a unit value to a function", |db| { + let sugg = args_to_recover + .iter() + .enumerate() + .map(|(i, arg)| { + let indent = if i == 0 { + 0 + } else { + indent_of(cx, expr.span).unwrap_or(0) + }; + format!( + "{}{};", + " ".repeat(indent), + snippet_block_with_applicability( + cx, + arg.span, + "..", + Some(expr.span), + &mut applicability + ) + ) + }) + .collect::<Vec<String>>() + .join("\n"); db.span_suggestion( expr.span.with_hi(expr.span.lo()), - "move the expressions in front of the call...", - format!( - "{} ", - args_to_recover - .iter() - .map(|arg| { - format!( - "{};", - snippet_with_applicability(cx, arg.span, "..", &mut applicability) - ) - }) - .collect::<Vec<String>>() - .join(" ") - ), + &format!("{}move the expressions in front of the call...", or), + format!("{}\n", sugg), + applicability, + ); + db.multipart_suggestion( + "...and use unit literals instead", + args_to_recover + .iter() + .map(|arg| (arg.span, "()".to_string())) + .collect::<Vec<_>>(), applicability, ); - for arg in args_to_recover { - db.span_suggestion( - arg.span, - "...and use unit literals instead", - "()".to_string(), - applicability, - ); - } }); } }, From f9c325f5b657e0c37ba2016a51cddbeab7f7693f Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 17 Feb 2020 18:11:50 +0100 Subject: [PATCH 138/526] Suggest to remove the semicolon of the last stmt in a block --- clippy_lints/src/types.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c95bd5d72bc..51d7d9b3ab7 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -794,6 +794,36 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { if !args_to_recover.is_empty() { let mut applicability = Applicability::MachineApplicable; span_lint_and_then(cx, UNIT_ARG, expr.span, "passing a unit value to a function", |db| { + let mut or = ""; + args_to_recover + .iter() + .filter_map(|arg| { + if_chain! { + if let ExprKind::Block(block, _) = arg.kind; + if block.expr.is_none(); + if let Some(last_stmt) = block.stmts.iter().last(); + if let StmtKind::Semi(last_expr) = last_stmt.kind; + if let Some(snip) = snippet_opt(cx, last_expr.span); + then { + Some(( + last_stmt.span, + snip, + )) + } + else { + None + } + } + }) + .for_each(|(span, sugg)| { + db.span_suggestion( + span, + "remove the semicolon from the last statement in the block", + sugg, + Applicability::MaybeIncorrect, + ); + or = "or "; + }); let sugg = args_to_recover .iter() .enumerate() From 4c9cefa12232aa0224b1680f51654fe10f5cf3b7 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 18 Feb 2020 09:51:52 +0100 Subject: [PATCH 139/526] Move linting out in its own function --- clippy_lints/src/types.rs | 171 ++++++++++++++++++++------------------ 1 file changed, 91 insertions(+), 80 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 51d7d9b3ab7..6866635b904 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -779,89 +779,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { match expr.kind { ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args) => { - let mut args_to_recover = vec![]; - for arg in args { - if is_unit(cx.tables.expr_ty(arg)) && !is_unit_literal(arg) { - if let ExprKind::Match(.., match_source) = &arg.kind { - if *match_source == MatchSource::TryDesugar { - continue; + let args_to_recover = args + .iter() + .filter(|arg| { + if is_unit(cx.tables.expr_ty(arg)) && !is_unit_literal(arg) { + if let ExprKind::Match(.., MatchSource::TryDesugar) = &arg.kind { + false + } else { + true } + } else { + false } - - args_to_recover.push(arg); - } - } + }) + .collect::<Vec<_>>(); if !args_to_recover.is_empty() { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_then(cx, UNIT_ARG, expr.span, "passing a unit value to a function", |db| { - let mut or = ""; - args_to_recover - .iter() - .filter_map(|arg| { - if_chain! { - if let ExprKind::Block(block, _) = arg.kind; - if block.expr.is_none(); - if let Some(last_stmt) = block.stmts.iter().last(); - if let StmtKind::Semi(last_expr) = last_stmt.kind; - if let Some(snip) = snippet_opt(cx, last_expr.span); - then { - Some(( - last_stmt.span, - snip, - )) - } - else { - None - } - } - }) - .for_each(|(span, sugg)| { - db.span_suggestion( - span, - "remove the semicolon from the last statement in the block", - sugg, - Applicability::MaybeIncorrect, - ); - or = "or "; - }); - let sugg = args_to_recover - .iter() - .enumerate() - .map(|(i, arg)| { - let indent = if i == 0 { - 0 - } else { - indent_of(cx, expr.span).unwrap_or(0) - }; - format!( - "{}{};", - " ".repeat(indent), - snippet_block_with_applicability( - cx, - arg.span, - "..", - Some(expr.span), - &mut applicability - ) - ) - }) - .collect::<Vec<String>>() - .join("\n"); - db.span_suggestion( - expr.span.with_hi(expr.span.lo()), - &format!("{}move the expressions in front of the call...", or), - format!("{}\n", sugg), - applicability, - ); - db.multipart_suggestion( - "...and use unit literals instead", - args_to_recover - .iter() - .map(|arg| (arg.span, "()".to_string())) - .collect::<Vec<_>>(), - applicability, - ); - }); + lint_unit_args(cx, expr, &args_to_recover); } }, _ => (), @@ -869,6 +802,84 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { } } +fn lint_unit_args(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) { + let mut applicability = Applicability::MachineApplicable; + let (singular, plural) = if args_to_recover.len() > 1 { + ("", "s") + } else { + ("a ", "") + }; + span_lint_and_then( + cx, + UNIT_ARG, + expr.span, + &format!("passing {}unit value{} to a function", singular, plural), + |db| { + let mut or = ""; + args_to_recover + .iter() + .filter_map(|arg| { + if_chain! { + if let ExprKind::Block(block, _) = arg.kind; + if block.expr.is_none(); + if let Some(last_stmt) = block.stmts.iter().last(); + if let StmtKind::Semi(last_expr) = last_stmt.kind; + if let Some(snip) = snippet_opt(cx, last_expr.span); + then { + Some(( + last_stmt.span, + snip, + )) + } + else { + None + } + } + }) + .for_each(|(span, sugg)| { + db.span_suggestion( + span, + "remove the semicolon from the last statement in the block", + sugg, + Applicability::MaybeIncorrect, + ); + or = "or "; + }); + let sugg = args_to_recover + .iter() + .enumerate() + .map(|(i, arg)| { + let indent = if i == 0 { + 0 + } else { + indent_of(cx, expr.span).unwrap_or(0) + }; + format!( + "{}{};", + " ".repeat(indent), + snippet_block_with_applicability(cx, arg.span, "..", Some(expr.span), &mut applicability) + ) + }) + .collect::<Vec<String>>() + .join("\n"); + db.span_suggestion( + expr.span.with_hi(expr.span.lo()), + &format!("{}move the expression{} in front of the call...", or, plural), + format!("{}\n", sugg), + applicability, + ); + db.multipart_suggestion( + &format!("...and use {}unit literal{} instead", singular, plural), + args_to_recover + .iter() + .map(|arg| (arg.span, "()".to_string())) + .collect::<Vec<_>>(), + applicability, + ); + }, + ); +} + fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool { use rustc_span::hygiene::DesugaringKind; if let ExprKind::Call(ref callee, _) = expr.kind { From 6d15a149640e5647ce232690d54b540346fa1641 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 17 Feb 2020 18:12:01 +0100 Subject: [PATCH 140/526] Update test files --- tests/ui/unit_arg.fixed | 79 ------------------ tests/ui/unit_arg.rs | 15 +++- tests/ui/unit_arg.stderr | 170 +++++++++++++++++++++++++++------------ 3 files changed, 134 insertions(+), 130 deletions(-) delete mode 100644 tests/ui/unit_arg.fixed diff --git a/tests/ui/unit_arg.fixed b/tests/ui/unit_arg.fixed deleted file mode 100644 index 67c6bdf8873..00000000000 --- a/tests/ui/unit_arg.fixed +++ /dev/null @@ -1,79 +0,0 @@ -// run-rustfix -#![warn(clippy::unit_arg)] -#![allow(clippy::no_effect, unused_must_use, unused_variables)] - -use std::fmt::Debug; - -fn foo<T: Debug>(t: T) { - println!("{:?}", t); -} - -fn foo3<T1: Debug, T2: Debug, T3: Debug>(t1: T1, t2: T2, t3: T3) { - println!("{:?}, {:?}, {:?}", t1, t2, t3); -} - -struct Bar; - -impl Bar { - fn bar<T: Debug>(&self, t: T) { - println!("{:?}", t); - } -} - -fn bad() { - {}; foo(()); - { - 1; - }; foo(()); - foo(1); foo(()); - { - foo(1); - foo(2); - }; foo(()); - {}; foo3((), 2, 2); - let b = Bar; - { - 1; - }; b.bar(()); - foo(0); foo(1); taking_multiple_units((), ()); -} - -fn ok() { - foo(()); - foo(1); - foo({ 1 }); - foo3("a", 3, vec![3]); - let b = Bar; - b.bar({ 1 }); - b.bar(()); - question_mark(); -} - -fn question_mark() -> Result<(), ()> { - Ok(Ok(())?)?; - Ok(Ok(()))??; - Ok(()) -} - -#[allow(dead_code)] -mod issue_2945 { - fn unit_fn() -> Result<(), i32> { - Ok(()) - } - - fn fallible() -> Result<(), i32> { - Ok(unit_fn()?) - } -} - -#[allow(dead_code)] -fn returning_expr() -> Option<()> { - foo(1); Some(()) -} - -fn taking_multiple_units(a: (), b: ()) {} - -fn main() { - bad(); - ok(); -} diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index c6e465b2e4c..7d1b99fedc9 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -1,4 +1,3 @@ -// run-rustfix #![warn(clippy::unit_arg)] #![allow(clippy::no_effect, unused_must_use, unused_variables)] @@ -36,6 +35,20 @@ fn bad() { 1; }); taking_multiple_units(foo(0), foo(1)); + taking_multiple_units(foo(0), { + foo(1); + foo(2); + }); + taking_multiple_units( + { + foo(0); + foo(1); + }, + { + foo(2); + foo(3); + }, + ); } fn ok() { diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index ce9ab2f1271..145b3c62b06 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,34 +1,53 @@ error: passing a unit value to a function - --> $DIR/unit_arg.rs:24:5 + --> $DIR/unit_arg.rs:23:5 | LL | foo({}); | ^^^^^^^ | = note: `-D clippy::unit-arg` implied by `-D warnings` -help: move the expressions in front of the call... +help: move the expression in front of the call... | -LL | {}; foo({}); - | ^^^ -help: ...and use unit literals instead +LL | {}; + | +help: ...and use a unit literal instead | LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:25:5 + --> $DIR/unit_arg.rs:24:5 | LL | / foo({ LL | | 1; LL | | }); | |______^ | -help: move the expressions in front of the call... +help: remove the semicolon from the last statement in the block + | +LL | 1 + | +help: or move the expression in front of the call... | LL | { LL | 1; -LL | }; foo({ +LL | }; | -help: ...and use unit literals instead +help: ...and use a unit literal instead + | +LL | foo(()); + | ^^ + +error: passing a unit value to a function + --> $DIR/unit_arg.rs:27:5 + | +LL | foo(foo(1)); + | ^^^^^^^^^^^ + | +help: move the expression in front of the call... + | +LL | foo(1); + | +help: ...and use a unit literal instead | LL | foo(()); | ^^ @@ -36,106 +55,157 @@ LL | foo(()); error: passing a unit value to a function --> $DIR/unit_arg.rs:28:5 | -LL | foo(foo(1)); - | ^^^^^^^^^^^ - | -help: move the expressions in front of the call... - | -LL | foo(1); foo(foo(1)); - | ^^^^^^^ -help: ...and use unit literals instead - | -LL | foo(()); - | ^^ - -error: passing a unit value to a function - --> $DIR/unit_arg.rs:29:5 - | LL | / foo({ LL | | foo(1); LL | | foo(2); LL | | }); | |______^ | -help: move the expressions in front of the call... +help: remove the semicolon from the last statement in the block + | +LL | foo(2) + | +help: or move the expression in front of the call... | LL | { LL | foo(1); LL | foo(2); -LL | }; foo({ +LL | }; | -help: ...and use unit literals instead +help: ...and use a unit literal instead | LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:33:5 + --> $DIR/unit_arg.rs:32:5 | LL | foo3({}, 2, 2); | ^^^^^^^^^^^^^^ | -help: move the expressions in front of the call... +help: move the expression in front of the call... | -LL | {}; foo3({}, 2, 2); - | ^^^ -help: ...and use unit literals instead +LL | {}; + | +help: ...and use a unit literal instead | LL | foo3((), 2, 2); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:35:5 + --> $DIR/unit_arg.rs:34:5 | LL | / b.bar({ LL | | 1; LL | | }); | |______^ | -help: move the expressions in front of the call... +help: remove the semicolon from the last statement in the block + | +LL | 1 + | +help: or move the expression in front of the call... | LL | { LL | 1; -LL | }; b.bar({ +LL | }; | -help: ...and use unit literals instead +help: ...and use a unit literal instead | LL | b.bar(()); | ^^ -error: passing a unit value to a function - --> $DIR/unit_arg.rs:38:5 +error: passing unit values to a function + --> $DIR/unit_arg.rs:37:5 | LL | taking_multiple_units(foo(0), foo(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: move the expressions in front of the call... | -LL | foo(0); foo(1); taking_multiple_units(foo(0), foo(1)); - | ^^^^^^^^^^^^^^^ +LL | foo(0); +LL | foo(1); + | help: ...and use unit literals instead | -LL | taking_multiple_units((), foo(1)); - | ^^ +LL | taking_multiple_units((), ()); + | ^^ ^^ + +error: passing unit values to a function + --> $DIR/unit_arg.rs:38:5 + | +LL | / taking_multiple_units(foo(0), { +LL | | foo(1); +LL | | foo(2); +LL | | }); + | |______^ + | +help: remove the semicolon from the last statement in the block + | +LL | foo(2) + | +help: or move the expressions in front of the call... + | +LL | foo(0); +LL | { +LL | foo(1); +LL | foo(2); +LL | }; + | help: ...and use unit literals instead | -LL | taking_multiple_units(foo(0), ()); - | ^^ +LL | taking_multiple_units((), ()); + | ^^ ^^ + +error: passing unit values to a function + --> $DIR/unit_arg.rs:42:5 + | +LL | / taking_multiple_units( +LL | | { +LL | | foo(0); +LL | | foo(1); +... | +LL | | }, +LL | | ); + | |_____^ + | +help: remove the semicolon from the last statement in the block + | +LL | foo(1) + | +help: remove the semicolon from the last statement in the block + | +LL | foo(3) + | +help: or move the expressions in front of the call... + | +LL | { +LL | foo(0); +LL | foo(1); +LL | }; +LL | { +LL | foo(2); + ... +help: ...and use unit literals instead + | +LL | (), +LL | (), + | error: passing a unit value to a function - --> $DIR/unit_arg.rs:71:5 + --> $DIR/unit_arg.rs:84:5 | LL | Some(foo(1)) | ^^^^^^^^^^^^ | -help: move the expressions in front of the call... +help: move the expression in front of the call... | -LL | foo(1); Some(foo(1)) - | ^^^^^^^ -help: ...and use unit literals instead +LL | foo(1); + | +help: ...and use a unit literal instead | LL | Some(()) | ^^ -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors From a9cde3a804808e82402888a20878053404a8eded Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sun, 31 May 2020 18:45:16 +0200 Subject: [PATCH 141/526] Don't suggest to move empty blocks --- clippy_lints/src/types.rs | 43 +++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 6866635b904..5ca30d598eb 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -10,7 +10,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{ - BinOpKind, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem, + BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, Local, MatchSource, MutTy, Mutability, QPath, Stmt, StmtKind, TraitFn, TraitItem, TraitItemKind, TyKind, UnOp, }; @@ -29,10 +29,10 @@ use rustc_typeck::hir_ty_to_ty; use crate::consts::{constant, Constant}; use crate::utils::paths; use crate::utils::{ - clip, comparisons, differing_macro_contexts, higher, in_constant, int_bits, is_type_diagnostic_item, + clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_type_diagnostic_item, last_path_segment, match_def_path, match_path, method_chain_args, multispan_sugg, numeric_literal::NumericLiteral, - qpath_res, same_tys, sext, snippet, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite, - span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext, + qpath_res, same_tys, sext, snippet, snippet_block_with_applicability, snippet_opt, snippet_with_applicability, + snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext, }; declare_clippy_lint! { @@ -847,6 +847,7 @@ fn lint_unit_args(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args_to_recover: &[ }); let sugg = args_to_recover .iter() + .filter(|arg| !is_empty_block(arg)) .enumerate() .map(|(i, arg)| { let indent = if i == 0 { @@ -860,16 +861,20 @@ fn lint_unit_args(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args_to_recover: &[ snippet_block_with_applicability(cx, arg.span, "..", Some(expr.span), &mut applicability) ) }) - .collect::<Vec<String>>() - .join("\n"); - db.span_suggestion( - expr.span.with_hi(expr.span.lo()), - &format!("{}move the expression{} in front of the call...", or, plural), - format!("{}\n", sugg), - applicability, - ); + .collect::<Vec<String>>(); + let mut and = ""; + if !sugg.is_empty() { + let plural = if sugg.len() > 1 { "s" } else { "" }; + db.span_suggestion( + expr.span.with_hi(expr.span.lo()), + &format!("{}move the expression{} in front of the call...", or, plural), + format!("{}\n", sugg.join("\n")), + applicability, + ); + and = "...and " + } db.multipart_suggestion( - &format!("...and use {}unit literal{} instead", singular, plural), + &format!("{}use {}unit literal{} instead", and, singular, plural), args_to_recover .iter() .map(|arg| (arg.span, "()".to_string())) @@ -880,6 +885,18 @@ fn lint_unit_args(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args_to_recover: &[ ); } +fn is_empty_block(expr: &Expr<'_>) -> bool { + matches!( + expr.kind, + ExprKind::Block( + Block { + stmts: &[], expr: None, .. + }, + _, + ) + ) +} + fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool { use rustc_span::hygiene::DesugaringKind; if let ExprKind::Call(ref callee, _) = expr.kind { From 77dd0ea62aa6a2af70da4c5e05de064eee182a6c Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sun, 31 May 2020 19:29:36 +0200 Subject: [PATCH 142/526] Add tests for empty blocks --- tests/ui/unit_arg.rs | 2 -- tests/ui/unit_arg.stderr | 46 +++++------------------- tests/ui/unit_arg_empty_blocks.rs | 26 ++++++++++++++ tests/ui/unit_arg_empty_blocks.stderr | 51 +++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 40 deletions(-) create mode 100644 tests/ui/unit_arg_empty_blocks.rs create mode 100644 tests/ui/unit_arg_empty_blocks.stderr diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 7d1b99fedc9..2992abae775 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -20,7 +20,6 @@ impl Bar { } fn bad() { - foo({}); foo({ 1; }); @@ -29,7 +28,6 @@ fn bad() { foo(1); foo(2); }); - foo3({}, 2, 2); let b = Bar; b.bar({ 1; diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index 145b3c62b06..56f6a855dfa 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,27 +1,12 @@ error: passing a unit value to a function --> $DIR/unit_arg.rs:23:5 | -LL | foo({}); - | ^^^^^^^ - | - = note: `-D clippy::unit-arg` implied by `-D warnings` -help: move the expression in front of the call... - | -LL | {}; - | -help: ...and use a unit literal instead - | -LL | foo(()); - | ^^ - -error: passing a unit value to a function - --> $DIR/unit_arg.rs:24:5 - | LL | / foo({ LL | | 1; LL | | }); | |______^ | + = note: `-D clippy::unit-arg` implied by `-D warnings` help: remove the semicolon from the last statement in the block | LL | 1 @@ -38,7 +23,7 @@ LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:27:5 + --> $DIR/unit_arg.rs:26:5 | LL | foo(foo(1)); | ^^^^^^^^^^^ @@ -53,7 +38,7 @@ LL | foo(()); | ^^ error: passing a unit value to a function - --> $DIR/unit_arg.rs:28:5 + --> $DIR/unit_arg.rs:27:5 | LL | / foo({ LL | | foo(1); @@ -80,21 +65,6 @@ LL | foo(()); error: passing a unit value to a function --> $DIR/unit_arg.rs:32:5 | -LL | foo3({}, 2, 2); - | ^^^^^^^^^^^^^^ - | -help: move the expression in front of the call... - | -LL | {}; - | -help: ...and use a unit literal instead - | -LL | foo3((), 2, 2); - | ^^ - -error: passing a unit value to a function - --> $DIR/unit_arg.rs:34:5 - | LL | / b.bar({ LL | | 1; LL | | }); @@ -116,7 +86,7 @@ LL | b.bar(()); | ^^ error: passing unit values to a function - --> $DIR/unit_arg.rs:37:5 + --> $DIR/unit_arg.rs:35:5 | LL | taking_multiple_units(foo(0), foo(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +102,7 @@ LL | taking_multiple_units((), ()); | ^^ ^^ error: passing unit values to a function - --> $DIR/unit_arg.rs:38:5 + --> $DIR/unit_arg.rs:36:5 | LL | / taking_multiple_units(foo(0), { LL | | foo(1); @@ -158,7 +128,7 @@ LL | taking_multiple_units((), ()); | ^^ ^^ error: passing unit values to a function - --> $DIR/unit_arg.rs:42:5 + --> $DIR/unit_arg.rs:40:5 | LL | / taking_multiple_units( LL | | { @@ -193,7 +163,7 @@ LL | (), | error: passing a unit value to a function - --> $DIR/unit_arg.rs:84:5 + --> $DIR/unit_arg.rs:82:5 | LL | Some(foo(1)) | ^^^^^^^^^^^^ @@ -207,5 +177,5 @@ help: ...and use a unit literal instead LL | Some(()) | ^^ -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/unit_arg_empty_blocks.rs b/tests/ui/unit_arg_empty_blocks.rs new file mode 100644 index 00000000000..18a31eb3dee --- /dev/null +++ b/tests/ui/unit_arg_empty_blocks.rs @@ -0,0 +1,26 @@ +#![warn(clippy::unit_arg)] +#![allow(clippy::no_effect, unused_must_use, unused_variables)] + +use std::fmt::Debug; + +fn foo<T: Debug>(t: T) { + println!("{:?}", t); +} + +fn foo3<T1: Debug, T2: Debug, T3: Debug>(t1: T1, t2: T2, t3: T3) { + println!("{:?}, {:?}, {:?}", t1, t2, t3); +} + +fn bad() { + foo({}); + foo3({}, 2, 2); + taking_two_units({}, foo(0)); + taking_three_units({}, foo(0), foo(1)); +} + +fn taking_two_units(a: (), b: ()) {} +fn taking_three_units(a: (), b: (), c: ()) {} + +fn main() { + bad(); +} diff --git a/tests/ui/unit_arg_empty_blocks.stderr b/tests/ui/unit_arg_empty_blocks.stderr new file mode 100644 index 00000000000..bb58483584b --- /dev/null +++ b/tests/ui/unit_arg_empty_blocks.stderr @@ -0,0 +1,51 @@ +error: passing a unit value to a function + --> $DIR/unit_arg_empty_blocks.rs:15:5 + | +LL | foo({}); + | ^^^^--^ + | | + | help: use a unit literal instead: `()` + | + = note: `-D clippy::unit-arg` implied by `-D warnings` + +error: passing a unit value to a function + --> $DIR/unit_arg_empty_blocks.rs:16:5 + | +LL | foo3({}, 2, 2); + | ^^^^^--^^^^^^^ + | | + | help: use a unit literal instead: `()` + +error: passing unit values to a function + --> $DIR/unit_arg_empty_blocks.rs:17:5 + | +LL | taking_two_units({}, foo(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: move the expression in front of the call... + | +LL | foo(0); + | +help: ...and use unit literals instead + | +LL | taking_two_units((), ()); + | ^^ ^^ + +error: passing unit values to a function + --> $DIR/unit_arg_empty_blocks.rs:18:5 + | +LL | taking_three_units({}, foo(0), foo(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: move the expressions in front of the call... + | +LL | foo(0); +LL | foo(1); + | +help: ...and use unit literals instead + | +LL | taking_three_units((), (), ()); + | ^^ ^^ ^^ + +error: aborting due to 4 previous errors + From 14e9100543166e48acd0ea00233249d2cddf09c2 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 25 May 2020 00:41:13 +0200 Subject: [PATCH 143/526] cargo-ui tests: check that <dir>/src exists before processing test --- tests/compile-test.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 7bd5f09f333..194354b291f 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -181,8 +181,15 @@ fn run_ui_cargo(config: &mut compiletest::Config) { } let src_path = case.path().join("src"); - env::set_current_dir(&src_path)?; + // When switching between branches, if the previous branch had a test + // that the current branch does not have, the directory is not removed + // because an ignored Cargo.lock file exists. + if !src_path.exists() { + continue; + } + + env::set_current_dir(&src_path)?; for file in fs::read_dir(&src_path)? { let file = file?; if file.file_type()?.is_dir() { From 7e843515d9525b6389c3fc1bcfa6ae046c1351dc Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 14 May 2020 15:06:05 -0700 Subject: [PATCH 144/526] Created lint --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 4 ++++ clippy_lints/src/sort_by_key_reverse.rs | 28 +++++++++++++++++++++++++ src/lintlist/mod.rs | 7 +++++++ tests/ui/sort_by_key_reverse.rs | 5 +++++ 5 files changed, 45 insertions(+) create mode 100644 clippy_lints/src/sort_by_key_reverse.rs create mode 100644 tests/ui/sort_by_key_reverse.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index f7dae3dcfff..c00f84bdb85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1555,6 +1555,7 @@ Released 2018-09-13 [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next [`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization +[`sort_by_key_reverse`]: https://rust-lang.github.io/rust-clippy/master/index.html#sort_by_key_reverse [`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string [`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add [`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 38cfa212d9f..f51855badff 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -304,6 +304,7 @@ mod serde_api; mod shadow; mod single_component_path_imports; mod slow_vector_initialization; +mod sort_by_key_reverse; mod strings; mod suspicious_trait_impl; mod swap; @@ -779,6 +780,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &shadow::SHADOW_UNRELATED, &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, + &sort_by_key_reverse::SORT_BY_KEY_REVERSE, &strings::STRING_ADD, &strings::STRING_ADD_ASSIGN, &strings::STRING_LIT_AS_BYTES, @@ -1391,6 +1393,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), + LintId::of(&sort_by_key_reverse::SORT_BY_KEY_REVERSE), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), @@ -1592,6 +1595,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ranges::RANGE_ZIP_WITH_LEN), LintId::of(&reference::DEREF_ADDROF), LintId::of(&reference::REF_IN_DEREF), + LintId::of(&sort_by_key_reverse::SORT_BY_KEY_REVERSE), LintId::of(&swap::MANUAL_SWAP), LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT), LintId::of(&transmute::CROSSPOINTER_TRANSMUTE), diff --git a/clippy_lints/src/sort_by_key_reverse.rs b/clippy_lints/src/sort_by_key_reverse.rs new file mode 100644 index 00000000000..65830afd0f8 --- /dev/null +++ b/clippy_lints/src/sort_by_key_reverse.rs @@ -0,0 +1,28 @@ +use rustc_lint::{LateLintPass, LateContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_hir::*; + +declare_clippy_lint! { + /// **What it does:** + /// + /// **Why is this bad?** + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + pub SORT_BY_KEY_REVERSE, + complexity, + "default lint description" +} + +declare_lint_pass!(SortByKeyReverse => [SORT_BY_KEY_REVERSE]); + +impl LateLintPass<'_, '_> for SortByKeyReverse {} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 69578732898..1b82f34c863 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1984,6 +1984,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "slow_vector_initialization", }, + Lint { + name: "sort_by_key_reverse", + group: "complexity", + desc: "default lint description", + deprecation: None, + module: "sort_by_key_reverse", + }, Lint { name: "string_add", group: "restriction", diff --git a/tests/ui/sort_by_key_reverse.rs b/tests/ui/sort_by_key_reverse.rs new file mode 100644 index 00000000000..2338dc6e594 --- /dev/null +++ b/tests/ui/sort_by_key_reverse.rs @@ -0,0 +1,5 @@ +#![warn(clippy::sort_by_key_reverse)] + +fn main() { + // test code goes here +} From 24847ea53e332853597aca2c7dfe48a9f3be1de8 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sat, 16 May 2020 13:50:33 -0700 Subject: [PATCH 145/526] Attempted start at sort_by_key_reverse lint --- clippy_lints/src/sort_by_key_reverse.rs | 71 +++++++++++++++++++++++-- src/lintlist/mod.rs | 2 +- tests/ui/sort_by_key_reverse.fixed | 0 tests/ui/sort_by_key_reverse.rs | 3 +- tests/ui/sort_by_key_reverse.stderr | 0 5 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 tests/ui/sort_by_key_reverse.fixed create mode 100644 tests/ui/sort_by_key_reverse.stderr diff --git a/clippy_lints/src/sort_by_key_reverse.rs b/clippy_lints/src/sort_by_key_reverse.rs index 65830afd0f8..7d7097a8125 100644 --- a/clippy_lints/src/sort_by_key_reverse.rs +++ b/clippy_lints/src/sort_by_key_reverse.rs @@ -1,28 +1,91 @@ +use crate::utils::{match_type, span_lint_and_sugg}; +use crate::utils::paths; +use crate::utils::sugg::Sugg; +use if_chain::if_chain; +use rustc_errors::Applicability; use rustc_lint::{LateLintPass, LateContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_hir::*; declare_clippy_lint! { /// **What it does:** + /// Detects when people use `Vec::sort_by` and pass in a function + /// which compares the second argument to the first. /// /// **Why is this bad?** + /// It is more clear to use `Vec::sort_by_key` and `std::cmp::Reverse` /// /// **Known problems:** None. /// /// **Example:** /// /// ```rust - /// // example code where clippy issues a warning + /// vec.sort_by(|a, b| b.foo().cmp(&a.foo())); /// ``` /// Use instead: /// ```rust - /// // example code which does not raise clippy warning + /// vec.sort_by_key(|e| Reverse(e.foo())); /// ``` pub SORT_BY_KEY_REVERSE, complexity, - "default lint description" + "Use of `Vec::sort_by` when `Vec::sort_by_key` would be clearer" } declare_lint_pass!(SortByKeyReverse => [SORT_BY_KEY_REVERSE]); -impl LateLintPass<'_, '_> for SortByKeyReverse {} +struct LintTrigger { + vec_name: String, + closure_arg: String, + closure_reverse_body: String, + unstable: bool, +} + +fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> { + if_chain! { + if let ExprKind::MethodCall(name_ident, _, args) = &expr.kind; + if let name = name_ident.ident.name.to_ident_string(); + if name == "sort_by" || name == "sort_unstable_by"; + if let [vec, Expr { kind: ExprKind::Closure(_, closure_decl, closure_body_id, _, _), .. }] = args; + if closure_decl.inputs.len() == 2; + if match_type(cx, &cx.tables.expr_ty(vec), &paths::VEC); + then { + let vec_name = Sugg::hir(cx, &args[0], "..").to_string(); + let unstable = name == "sort_unstable_by"; + Some(LintTrigger { vec_name, unstable, closure_arg: "e".to_string(), closure_reverse_body: "e".to_string() }) + } else { + None + } + } +} + +impl LateLintPass<'_, '_> for SortByKeyReverse { + fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + println!("{:?}", expr); + span_lint_and_sugg( + cx, + SORT_BY_KEY_REVERSE, + expr.span, + "use Vec::sort_by_key here instead", + "try", + String::from("being a better person"), + Applicability::MachineApplicable, + ); + if let Some(trigger) = detect_lint(cx, expr) { + span_lint_and_sugg( + cx, + SORT_BY_KEY_REVERSE, + expr.span, + "use Vec::sort_by_key here instead", + "try", + format!( + "{}.sort{}_by_key(|{}| Reverse({}))", + trigger.vec_name, + if trigger.unstable { "_unstable" } else { "" }, + trigger.closure_arg, + trigger.closure_reverse_body, + ), + Applicability::MachineApplicable, + ); + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 1b82f34c863..b5d9ef0110e 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1987,7 +1987,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ Lint { name: "sort_by_key_reverse", group: "complexity", - desc: "default lint description", + desc: "Use of `Vec::sort_by` when `Vec::sort_by_key` would be clearer", deprecation: None, module: "sort_by_key_reverse", }, diff --git a/tests/ui/sort_by_key_reverse.fixed b/tests/ui/sort_by_key_reverse.fixed new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/ui/sort_by_key_reverse.rs b/tests/ui/sort_by_key_reverse.rs index 2338dc6e594..c0350f243c7 100644 --- a/tests/ui/sort_by_key_reverse.rs +++ b/tests/ui/sort_by_key_reverse.rs @@ -1,5 +1,6 @@ #![warn(clippy::sort_by_key_reverse)] fn main() { - // test code goes here + let mut vec = vec![3, 6, 1, 2, 5]; + vec.sort_by(|a, b| b.cmp(a)); } diff --git a/tests/ui/sort_by_key_reverse.stderr b/tests/ui/sort_by_key_reverse.stderr new file mode 100644 index 00000000000..e69de29bb2d From 8590ab4d46de4eb43e7ebd42cb2f13b0064573e6 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Mon, 18 May 2020 21:48:35 -0700 Subject: [PATCH 146/526] More progress towards sort_by_key_reverse lint --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/sort_by_key_reverse.rs | 131 ++++++++++++++++++++---- tests/ui/sort_by_key_reverse.fixed | 9 ++ tests/ui/sort_by_key_reverse.rs | 5 +- tests/ui/sort_by_key_reverse.stderr | 22 ++++ 5 files changed, 149 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f51855badff..e7a4c1ecaa9 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -998,6 +998,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast); store.register_late_pass(|| box redundant_clone::RedundantClone); store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit); + store.register_late_pass(|| box sort_by_key_reverse::SortByKeyReverse); store.register_late_pass(|| box types::RefToMut); store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants); store.register_late_pass(|| box missing_const_for_fn::MissingConstForFn); diff --git a/clippy_lints/src/sort_by_key_reverse.rs b/clippy_lints/src/sort_by_key_reverse.rs index 7d7097a8125..d70391999a0 100644 --- a/clippy_lints/src/sort_by_key_reverse.rs +++ b/clippy_lints/src/sort_by_key_reverse.rs @@ -1,11 +1,12 @@ -use crate::utils::{match_type, span_lint_and_sugg}; +use crate::utils; use crate::utils::paths; use crate::utils::sugg::Sugg; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_lint::{LateLintPass, LateContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::Ident; declare_clippy_lint! { /// **What it does:** @@ -40,18 +41,122 @@ struct LintTrigger { unstable: bool, } +/// Detect if the two expressions are mirrored (identical, except one +/// contains a and the other replaces it with b) +fn mirrored_exprs(cx: &LateContext<'_, '_>, a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident: &Ident) -> bool { + match (&a_expr.kind, &b_expr.kind) { + // Two boxes with mirrored contents + (ExprKind::Box(left_expr), ExprKind::Box(right_expr)) => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), + // Two arrays with mirrored contents + (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) + => left_exprs.iter().zip(right_exprs.iter()).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + // The two exprs are function calls. + // Check to see that the function itself and its arguments are mirrored + (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) + => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) + && left_args.iter().zip(right_args.iter()).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + // The two exprs are method calls. + // Check to see that the function is the same and the arguments are mirrored + // This is enough because the receiver of the method is listed in the arguments + (ExprKind::MethodCall(left_segment, _, left_args), ExprKind::MethodCall(right_segment, _, right_args)) + => left_segment.ident == right_segment.ident + && left_args.iter().zip(right_args.iter()).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + // Two tuples with mirrored contents + (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) + => left_exprs.iter().zip(right_exprs.iter()).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + // Two binary ops, which are the same operation and which have mirrored arguments + (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) + => left_op.node == right_op.node + && mirrored_exprs(cx, left_left, a_ident, right_left, b_ident) + && mirrored_exprs(cx, left_right, a_ident, right_right, b_ident), + // Two unary ops, which are the same operation and which have the same argument + (ExprKind::Unary(left_op, left_expr), ExprKind::Unary(right_op, right_expr)) + => left_op == right_op && mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), + // The two exprs are literals of some kind + (ExprKind::Lit(left_lit), ExprKind::Lit(right_lit)) => left_lit.node == right_lit.node, + (ExprKind::Cast(left_expr, _), ExprKind::Cast(right_expr, _)) + => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), + (ExprKind::DropTemps(left), ExprKind::DropTemps(right)) => mirrored_exprs(cx, left, a_ident, right, b_ident), + (ExprKind::Block(left, _), ExprKind::Block(right, _)) => mirrored_blocks(cx, left, a_ident, right, b_ident), + (ExprKind::Field(left_expr, left_ident), ExprKind::Field(right_expr, right_ident)) + => left_ident.name == right_ident.name && mirrored_exprs(cx, left_expr, a_ident, right_expr, right_ident), + // The two exprs are `a` and `b`, directly + (ExprKind::Path(QPath::Resolved(_, Path { segments: &[PathSegment { ident: left_ident, .. }], .. },)), + ExprKind::Path(QPath::Resolved(_, Path { segments: &[PathSegment { ident: right_ident, .. }], .. },)), + ) => &left_ident == a_ident && &right_ident == b_ident, + // The two exprs are Paths to the same name (which is neither a nor b) + (ExprKind::Path(QPath::Resolved(_, Path { segments: left_segments, .. })), + ExprKind::Path(QPath::Resolved(_, Path { segments: right_segments, .. }))) + => left_segments.iter().zip(right_segments.iter()).all(|(left, right)| left.ident == right.ident) + && left_segments.iter().all(|seg| &seg.ident != a_ident && &seg.ident != b_ident), + // Matching expressions, but one or both is borrowed + (ExprKind::AddrOf(left_kind, Mutability::Not, left_expr), ExprKind::AddrOf(right_kind, Mutability::Not, right_expr)) + => left_kind == right_kind && mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), + (_, ExprKind::AddrOf(_, Mutability::Not, right_expr)) + => mirrored_exprs(cx, a_expr, a_ident, right_expr, b_ident), + (ExprKind::AddrOf(_, Mutability::Not, left_expr), _) + => mirrored_exprs(cx, left_expr, a_ident, b_expr, b_ident), + // _ => false, + (left, right) => { + println!("{:?}\n{:?}", left, right); + false + }, + } +} + +/// Detect if the two blocks are mirrored (identical, except one +/// contains a and the other replaces it with b) +fn mirrored_blocks(cx: &LateContext<'_, '_>, a_block: &Block<'_>, a_ident: &Ident, b_block: &Block<'_>, b_ident: &Ident) -> bool { + match (a_block, b_block) { + (Block { stmts: left_stmts, expr: left_expr, .. }, + Block { stmts: right_stmts, expr: right_expr, .. }) + => left_stmts.iter().zip(right_stmts.iter()).all(|(left, right)| match (&left.kind, &right.kind) { + (StmtKind::Expr(left_expr), StmtKind::Expr(right_expr)) => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), + (StmtKind::Semi(left_expr), StmtKind::Semi(right_expr)) => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), + (StmtKind::Item(left_item), StmtKind::Item(right_item)) => left_item.id == right_item.id, + (StmtKind::Local(left), StmtKind::Local(right)) => mirrored_locals(cx, left, a_ident, right, b_ident), + _ => false, + }) && match (left_expr, right_expr) { + (None, None) => true, + (Some(left), Some(right)) => mirrored_exprs(cx, left, a_ident, right, b_ident), + _ => false, + }, + } +} + +/// Check that the two "Local"s (let statements) are equal +fn mirrored_locals(cx: &LateContext<'_, '_>, a_local: &Local<'_>, a_ident: &Ident, b_local: &Local<'_>, b_ident: &Ident) -> bool { + match (a_local, b_local) { + (Local { pat: left_pat, init: left_expr, .. }, Local { pat: right_pat, init: right_expr, .. }) + => match (left_expr, right_expr) { + (None, None) => true, + (Some(left), Some(right)) => mirrored_exprs(cx, left, a_ident, right, b_ident), + _ => false, + }, + } +} + fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> { if_chain! { if let ExprKind::MethodCall(name_ident, _, args) = &expr.kind; if let name = name_ident.ident.name.to_ident_string(); if name == "sort_by" || name == "sort_unstable_by"; - if let [vec, Expr { kind: ExprKind::Closure(_, closure_decl, closure_body_id, _, _), .. }] = args; - if closure_decl.inputs.len() == 2; - if match_type(cx, &cx.tables.expr_ty(vec), &paths::VEC); + if let [vec, Expr { kind: ExprKind::Closure(_, _, closure_body_id, _, _), .. }] = args; + if utils::match_type(cx, &cx.tables.expr_ty(vec), &paths::VEC); + if let closure_body = cx.tcx.hir().body(*closure_body_id); + if let &[ + Param { pat: Pat { kind: PatKind::Binding(_, _, a_ident, _), .. }, ..}, + Param { pat: Pat { kind: PatKind::Binding(_, _, b_ident, _), .. }, .. } + ] = &closure_body.params; + if let ExprKind::MethodCall(method_path, _, [ref b_expr, ref a_expr]) = &closure_body.value.kind; + if method_path.ident.name.to_ident_string() == "cmp"; + if mirrored_exprs(&cx, &a_expr, &a_ident, &b_expr, &b_ident); then { let vec_name = Sugg::hir(cx, &args[0], "..").to_string(); let unstable = name == "sort_unstable_by"; - Some(LintTrigger { vec_name, unstable, closure_arg: "e".to_string(), closure_reverse_body: "e".to_string() }) + let closure_arg = a_ident.name.to_ident_string(); + let closure_reverse_body = Sugg::hir(cx, &a_expr, "..").to_string(); + Some(LintTrigger { vec_name, unstable, closure_arg, closure_reverse_body }) } else { None } @@ -60,18 +165,8 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> impl LateLintPass<'_, '_> for SortByKeyReverse { fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { - println!("{:?}", expr); - span_lint_and_sugg( - cx, - SORT_BY_KEY_REVERSE, - expr.span, - "use Vec::sort_by_key here instead", - "try", - String::from("being a better person"), - Applicability::MachineApplicable, - ); if let Some(trigger) = detect_lint(cx, expr) { - span_lint_and_sugg( + utils::span_lint_and_sugg( cx, SORT_BY_KEY_REVERSE, expr.span, diff --git a/tests/ui/sort_by_key_reverse.fixed b/tests/ui/sort_by_key_reverse.fixed index e69de29bb2d..4b18a073e1a 100644 --- a/tests/ui/sort_by_key_reverse.fixed +++ b/tests/ui/sort_by_key_reverse.fixed @@ -0,0 +1,9 @@ +// run-rustfix +#![warn(clippy::sort_by_key_reverse)] + +fn main() { + let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; + vec.sort_by_key(|a| Reverse(a)); + vec.sort_by_key(|a| Reverse(&(a+5).abs())); + vec.sort_by_key(|a| Reverse(&-a)); +} diff --git a/tests/ui/sort_by_key_reverse.rs b/tests/ui/sort_by_key_reverse.rs index c0350f243c7..f4fb70b7b1d 100644 --- a/tests/ui/sort_by_key_reverse.rs +++ b/tests/ui/sort_by_key_reverse.rs @@ -1,6 +1,9 @@ +// run-rustfix #![warn(clippy::sort_by_key_reverse)] fn main() { - let mut vec = vec![3, 6, 1, 2, 5]; + let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; vec.sort_by(|a, b| b.cmp(a)); + vec.sort_by(|a, b| (b + 5).abs().cmp(&(a+5).abs())); + vec.sort_by(|a, b| (-b).cmp(&-a)); } diff --git a/tests/ui/sort_by_key_reverse.stderr b/tests/ui/sort_by_key_reverse.stderr index e69de29bb2d..36a28c04b1c 100644 --- a/tests/ui/sort_by_key_reverse.stderr +++ b/tests/ui/sort_by_key_reverse.stderr @@ -0,0 +1,22 @@ +error: use Vec::sort_by_key here instead + --> $DIR/sort_by_key_reverse.rs:6:5 + | +LL | vec.sort_by(|a, b| b.cmp(a)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| Reverse(a))` + | + = note: `-D clippy::sort-by-key-reverse` implied by `-D warnings` + +error: use Vec::sort_by_key here instead + --> $DIR/sort_by_key_reverse.rs:7:5 + | +LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a+5).abs())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| Reverse(&(a+5).abs()))` + +error: use Vec::sort_by_key here instead + --> $DIR/sort_by_key_reverse.rs:8:5 + | +LL | vec.sort_by(|a, b| (-b).cmp(&-a)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| Reverse(&-a))` + +error: aborting due to 3 previous errors + From 943cb94dce8fca6f3a3f7f011a2a2f9f0a665b97 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Tue, 19 May 2020 22:57:27 -0700 Subject: [PATCH 147/526] Passes all tests now! --- clippy_lints/src/sort_by_key_reverse.rs | 72 ++++++++----------------- tests/ui/sort_by_key_reverse.fixed | 12 +++-- tests/ui/sort_by_key_reverse.rs | 8 ++- tests/ui/sort_by_key_reverse.stderr | 14 ++--- 4 files changed, 45 insertions(+), 61 deletions(-) diff --git a/clippy_lints/src/sort_by_key_reverse.rs b/clippy_lints/src/sort_by_key_reverse.rs index d70391999a0..31629a1dbc1 100644 --- a/clippy_lints/src/sort_by_key_reverse.rs +++ b/clippy_lints/src/sort_by_key_reverse.rs @@ -53,8 +53,12 @@ fn mirrored_exprs(cx: &LateContext<'_, '_>, a_expr: &Expr<'_>, a_ident: &Ident, // The two exprs are function calls. // Check to see that the function itself and its arguments are mirrored (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) - => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) - && left_args.iter().zip(right_args.iter()).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + => { + // println!("{:?}\n{:?}\n", left_expr, left_args); + // println!("{:?}\n{:?}\n", right_expr, right_args); + mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) + && left_args.iter().zip(right_args.iter()).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) + }, // The two exprs are method calls. // Check to see that the function is the same and the arguments are mirrored // This is enough because the receiver of the method is listed in the arguments @@ -74,21 +78,17 @@ fn mirrored_exprs(cx: &LateContext<'_, '_>, a_expr: &Expr<'_>, a_ident: &Ident, => left_op == right_op && mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), // The two exprs are literals of some kind (ExprKind::Lit(left_lit), ExprKind::Lit(right_lit)) => left_lit.node == right_lit.node, - (ExprKind::Cast(left_expr, _), ExprKind::Cast(right_expr, _)) + (ExprKind::Cast(left_expr, left_ty), ExprKind::Cast(right_expr, right_ty)) => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), (ExprKind::DropTemps(left), ExprKind::DropTemps(right)) => mirrored_exprs(cx, left, a_ident, right, b_ident), - (ExprKind::Block(left, _), ExprKind::Block(right, _)) => mirrored_blocks(cx, left, a_ident, right, b_ident), (ExprKind::Field(left_expr, left_ident), ExprKind::Field(right_expr, right_ident)) => left_ident.name == right_ident.name && mirrored_exprs(cx, left_expr, a_ident, right_expr, right_ident), - // The two exprs are `a` and `b`, directly - (ExprKind::Path(QPath::Resolved(_, Path { segments: &[PathSegment { ident: left_ident, .. }], .. },)), - ExprKind::Path(QPath::Resolved(_, Path { segments: &[PathSegment { ident: right_ident, .. }], .. },)), - ) => &left_ident == a_ident && &right_ident == b_ident, - // The two exprs are Paths to the same name (which is neither a nor b) + // Two paths: either one is a and the other is b, or they're identical to each other (ExprKind::Path(QPath::Resolved(_, Path { segments: left_segments, .. })), ExprKind::Path(QPath::Resolved(_, Path { segments: right_segments, .. }))) - => left_segments.iter().zip(right_segments.iter()).all(|(left, right)| left.ident == right.ident) - && left_segments.iter().all(|seg| &seg.ident != a_ident && &seg.ident != b_ident), + => (left_segments.iter().zip(right_segments.iter()).all(|(left, right)| left.ident == right.ident) + && left_segments.iter().all(|seg| &seg.ident != a_ident && &seg.ident != b_ident)) + || (left_segments.len() == 1 && &left_segments[0].ident == a_ident && right_segments.len() == 1 && &right_segments[0].ident == b_ident), // Matching expressions, but one or both is borrowed (ExprKind::AddrOf(left_kind, Mutability::Not, left_expr), ExprKind::AddrOf(right_kind, Mutability::Not, right_expr)) => left_kind == right_kind && mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), @@ -96,43 +96,11 @@ fn mirrored_exprs(cx: &LateContext<'_, '_>, a_expr: &Expr<'_>, a_ident: &Ident, => mirrored_exprs(cx, a_expr, a_ident, right_expr, b_ident), (ExprKind::AddrOf(_, Mutability::Not, left_expr), _) => mirrored_exprs(cx, left_expr, a_ident, b_expr, b_ident), - // _ => false, - (left, right) => { - println!("{:?}\n{:?}", left, right); - false - }, - } -} - -/// Detect if the two blocks are mirrored (identical, except one -/// contains a and the other replaces it with b) -fn mirrored_blocks(cx: &LateContext<'_, '_>, a_block: &Block<'_>, a_ident: &Ident, b_block: &Block<'_>, b_ident: &Ident) -> bool { - match (a_block, b_block) { - (Block { stmts: left_stmts, expr: left_expr, .. }, - Block { stmts: right_stmts, expr: right_expr, .. }) - => left_stmts.iter().zip(right_stmts.iter()).all(|(left, right)| match (&left.kind, &right.kind) { - (StmtKind::Expr(left_expr), StmtKind::Expr(right_expr)) => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), - (StmtKind::Semi(left_expr), StmtKind::Semi(right_expr)) => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), - (StmtKind::Item(left_item), StmtKind::Item(right_item)) => left_item.id == right_item.id, - (StmtKind::Local(left), StmtKind::Local(right)) => mirrored_locals(cx, left, a_ident, right, b_ident), - _ => false, - }) && match (left_expr, right_expr) { - (None, None) => true, - (Some(left), Some(right)) => mirrored_exprs(cx, left, a_ident, right, b_ident), - _ => false, - }, - } -} - -/// Check that the two "Local"s (let statements) are equal -fn mirrored_locals(cx: &LateContext<'_, '_>, a_local: &Local<'_>, a_ident: &Ident, b_local: &Local<'_>, b_ident: &Ident) -> bool { - match (a_local, b_local) { - (Local { pat: left_pat, init: left_expr, .. }, Local { pat: right_pat, init: right_expr, .. }) - => match (left_expr, right_expr) { - (None, None) => true, - (Some(left), Some(right)) => mirrored_exprs(cx, left, a_ident, right, b_ident), - _ => false, - }, + _ => false, + // (left, right) => { + // println!("{:?}\n{:?}", left, right); + // false + // }, } } @@ -154,8 +122,12 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> then { let vec_name = Sugg::hir(cx, &args[0], "..").to_string(); let unstable = name == "sort_unstable_by"; - let closure_arg = a_ident.name.to_ident_string(); - let closure_reverse_body = Sugg::hir(cx, &a_expr, "..").to_string(); + let closure_arg = format!("&{}", b_ident.name.to_ident_string()); + let closure_reverse_body = Sugg::hir(cx, &b_expr, "..").to_string(); + // Get rid of parentheses, because they aren't needed anymore + // while closure_reverse_body.chars().next() == Some('(') && closure_reverse_body.chars().last() == Some(')') { + // closure_reverse_body = String::from(&closure_reverse_body[1..closure_reverse_body.len()-1]); + // } Some(LintTrigger { vec_name, unstable, closure_arg, closure_reverse_body }) } else { None diff --git a/tests/ui/sort_by_key_reverse.fixed b/tests/ui/sort_by_key_reverse.fixed index 4b18a073e1a..d536dc385d5 100644 --- a/tests/ui/sort_by_key_reverse.fixed +++ b/tests/ui/sort_by_key_reverse.fixed @@ -1,9 +1,15 @@ // run-rustfix #![warn(clippy::sort_by_key_reverse)] +use std::cmp::Reverse; + +fn id(x: isize) -> isize { + x +} + fn main() { let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; - vec.sort_by_key(|a| Reverse(a)); - vec.sort_by_key(|a| Reverse(&(a+5).abs())); - vec.sort_by_key(|a| Reverse(&-a)); + vec.sort_by_key(|&b| Reverse(b)); + vec.sort_by_key(|&b| Reverse((b + 5).abs())); + vec.sort_by_key(|&b| Reverse(id(-b))); } diff --git a/tests/ui/sort_by_key_reverse.rs b/tests/ui/sort_by_key_reverse.rs index f4fb70b7b1d..9c42d401755 100644 --- a/tests/ui/sort_by_key_reverse.rs +++ b/tests/ui/sort_by_key_reverse.rs @@ -1,9 +1,15 @@ // run-rustfix #![warn(clippy::sort_by_key_reverse)] +use std::cmp::Reverse; + +fn id(x: isize) -> isize { + x +} + fn main() { let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; vec.sort_by(|a, b| b.cmp(a)); vec.sort_by(|a, b| (b + 5).abs().cmp(&(a+5).abs())); - vec.sort_by(|a, b| (-b).cmp(&-a)); + vec.sort_by(|a, b| id(-b).cmp(&id(-a))); } diff --git a/tests/ui/sort_by_key_reverse.stderr b/tests/ui/sort_by_key_reverse.stderr index 36a28c04b1c..3d26ddae78a 100644 --- a/tests/ui/sort_by_key_reverse.stderr +++ b/tests/ui/sort_by_key_reverse.stderr @@ -1,22 +1,22 @@ error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key_reverse.rs:6:5 + --> $DIR/sort_by_key_reverse.rs:12:5 | LL | vec.sort_by(|a, b| b.cmp(a)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| Reverse(a))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(b))` | = note: `-D clippy::sort-by-key-reverse` implied by `-D warnings` error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key_reverse.rs:7:5 + --> $DIR/sort_by_key_reverse.rs:13:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a+5).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| Reverse(&(a+5).abs()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse((b + 5).abs()))` error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key_reverse.rs:8:5 + --> $DIR/sort_by_key_reverse.rs:14:5 | -LL | vec.sort_by(|a, b| (-b).cmp(&-a)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| Reverse(&-a))` +LL | vec.sort_by(|a, b| id(-b).cmp(&id(-a))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(id(-b)))` error: aborting due to 3 previous errors From 955a25ee7db234a8ab697176a433070702aabe59 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Wed, 20 May 2020 09:23:00 -0700 Subject: [PATCH 148/526] Added negative test cases and ran cargo dev fmt --- clippy_lints/src/sort_by_key_reverse.rs | 125 ++++++++++++++++-------- tests/ui/sort_by_key_reverse.fixed | 7 ++ tests/ui/sort_by_key_reverse.rs | 9 +- tests/ui/sort_by_key_reverse.stderr | 4 +- 4 files changed, 100 insertions(+), 45 deletions(-) diff --git a/clippy_lints/src/sort_by_key_reverse.rs b/clippy_lints/src/sort_by_key_reverse.rs index 31629a1dbc1..ea850955db1 100644 --- a/clippy_lints/src/sort_by_key_reverse.rs +++ b/clippy_lints/src/sort_by_key_reverse.rs @@ -3,7 +3,7 @@ use crate::utils::paths; use crate::utils::sugg::Sugg; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Ident; @@ -43,64 +43,105 @@ struct LintTrigger { /// Detect if the two expressions are mirrored (identical, except one /// contains a and the other replaces it with b) -fn mirrored_exprs(cx: &LateContext<'_, '_>, a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident: &Ident) -> bool { +fn mirrored_exprs( + cx: &LateContext<'_, '_>, + a_expr: &Expr<'_>, + a_ident: &Ident, + b_expr: &Expr<'_>, + b_ident: &Ident, +) -> bool { match (&a_expr.kind, &b_expr.kind) { // Two boxes with mirrored contents - (ExprKind::Box(left_expr), ExprKind::Box(right_expr)) => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), + (ExprKind::Box(left_expr), ExprKind::Box(right_expr)) => { + mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) + }, // Two arrays with mirrored contents - (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) - => left_exprs.iter().zip(right_exprs.iter()).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => left_exprs + .iter() + .zip(right_exprs.iter()) + .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), // The two exprs are function calls. // Check to see that the function itself and its arguments are mirrored - (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) - => { - // println!("{:?}\n{:?}\n", left_expr, left_args); - // println!("{:?}\n{:?}\n", right_expr, right_args); - mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) - && left_args.iter().zip(right_args.iter()).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) - }, + (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) => { + mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) + && left_args + .iter() + .zip(right_args.iter()) + .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) + }, // The two exprs are method calls. // Check to see that the function is the same and the arguments are mirrored // This is enough because the receiver of the method is listed in the arguments - (ExprKind::MethodCall(left_segment, _, left_args), ExprKind::MethodCall(right_segment, _, right_args)) - => left_segment.ident == right_segment.ident - && left_args.iter().zip(right_args.iter()).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + (ExprKind::MethodCall(left_segment, _, left_args), ExprKind::MethodCall(right_segment, _, right_args)) => { + left_segment.ident == right_segment.ident + && left_args + .iter() + .zip(right_args.iter()) + .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) + }, // Two tuples with mirrored contents - (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) - => left_exprs.iter().zip(right_exprs.iter()).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => left_exprs + .iter() + .zip(right_exprs.iter()) + .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), // Two binary ops, which are the same operation and which have mirrored arguments - (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) - => left_op.node == right_op.node + (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) => { + left_op.node == right_op.node && mirrored_exprs(cx, left_left, a_ident, right_left, b_ident) - && mirrored_exprs(cx, left_right, a_ident, right_right, b_ident), + && mirrored_exprs(cx, left_right, a_ident, right_right, b_ident) + }, // Two unary ops, which are the same operation and which have the same argument - (ExprKind::Unary(left_op, left_expr), ExprKind::Unary(right_op, right_expr)) - => left_op == right_op && mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), + (ExprKind::Unary(left_op, left_expr), ExprKind::Unary(right_op, right_expr)) => { + left_op == right_op && mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) + }, // The two exprs are literals of some kind (ExprKind::Lit(left_lit), ExprKind::Lit(right_lit)) => left_lit.node == right_lit.node, - (ExprKind::Cast(left_expr, left_ty), ExprKind::Cast(right_expr, right_ty)) - => mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), - (ExprKind::DropTemps(left), ExprKind::DropTemps(right)) => mirrored_exprs(cx, left, a_ident, right, b_ident), - (ExprKind::Field(left_expr, left_ident), ExprKind::Field(right_expr, right_ident)) - => left_ident.name == right_ident.name && mirrored_exprs(cx, left_expr, a_ident, right_expr, right_ident), + (ExprKind::Cast(left, _), ExprKind::Cast(right, _)) => mirrored_exprs(cx, left, a_ident, right, b_ident), + (ExprKind::DropTemps(left_block), ExprKind::DropTemps(right_block)) => { + mirrored_exprs(cx, left_block, a_ident, right_block, b_ident) + }, + (ExprKind::Field(left_expr, left_ident), ExprKind::Field(right_expr, right_ident)) => { + left_ident.name == right_ident.name && mirrored_exprs(cx, left_expr, a_ident, right_expr, right_ident) + }, // Two paths: either one is a and the other is b, or they're identical to each other - (ExprKind::Path(QPath::Resolved(_, Path { segments: left_segments, .. })), - ExprKind::Path(QPath::Resolved(_, Path { segments: right_segments, .. }))) - => (left_segments.iter().zip(right_segments.iter()).all(|(left, right)| left.ident == right.ident) - && left_segments.iter().all(|seg| &seg.ident != a_ident && &seg.ident != b_ident)) - || (left_segments.len() == 1 && &left_segments[0].ident == a_ident && right_segments.len() == 1 && &right_segments[0].ident == b_ident), + ( + ExprKind::Path(QPath::Resolved( + _, + Path { + segments: left_segments, + .. + }, + )), + ExprKind::Path(QPath::Resolved( + _, + Path { + segments: right_segments, + .. + }, + )), + ) => { + (left_segments + .iter() + .zip(right_segments.iter()) + .all(|(left, right)| left.ident == right.ident) + && left_segments + .iter() + .all(|seg| &seg.ident != a_ident && &seg.ident != b_ident)) + || (left_segments.len() == 1 + && &left_segments[0].ident == a_ident + && right_segments.len() == 1 + && &right_segments[0].ident == b_ident) + }, // Matching expressions, but one or both is borrowed - (ExprKind::AddrOf(left_kind, Mutability::Not, left_expr), ExprKind::AddrOf(right_kind, Mutability::Not, right_expr)) - => left_kind == right_kind && mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), - (_, ExprKind::AddrOf(_, Mutability::Not, right_expr)) - => mirrored_exprs(cx, a_expr, a_ident, right_expr, b_ident), - (ExprKind::AddrOf(_, Mutability::Not, left_expr), _) - => mirrored_exprs(cx, left_expr, a_ident, b_expr, b_ident), + ( + ExprKind::AddrOf(left_kind, Mutability::Not, left_expr), + ExprKind::AddrOf(right_kind, Mutability::Not, right_expr), + ) => left_kind == right_kind && mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident), + (_, ExprKind::AddrOf(_, Mutability::Not, right_expr)) => { + mirrored_exprs(cx, a_expr, a_ident, right_expr, b_ident) + }, + (ExprKind::AddrOf(_, Mutability::Not, left_expr), _) => mirrored_exprs(cx, left_expr, a_ident, b_expr, b_ident), _ => false, - // (left, right) => { - // println!("{:?}\n{:?}", left, right); - // false - // }, } } diff --git a/tests/ui/sort_by_key_reverse.fixed b/tests/ui/sort_by_key_reverse.fixed index d536dc385d5..722675a6b71 100644 --- a/tests/ui/sort_by_key_reverse.fixed +++ b/tests/ui/sort_by_key_reverse.fixed @@ -12,4 +12,11 @@ fn main() { vec.sort_by_key(|&b| Reverse(b)); vec.sort_by_key(|&b| Reverse((b + 5).abs())); vec.sort_by_key(|&b| Reverse(id(-b))); + // Negative examples (shouldn't be changed) + let c = &7; + vec.sort_by(|a, b| (b - a).cmp(&(a - b))); + vec.sort_by(|_, b| b.cmp(&5)); + vec.sort_by(|_, b| b.cmp(c)); + vec.sort_by(|a, _| a.cmp(c)); + vec.sort_by(|a, b| a.cmp(b)); } diff --git a/tests/ui/sort_by_key_reverse.rs b/tests/ui/sort_by_key_reverse.rs index 9c42d401755..601621ffa9f 100644 --- a/tests/ui/sort_by_key_reverse.rs +++ b/tests/ui/sort_by_key_reverse.rs @@ -10,6 +10,13 @@ fn id(x: isize) -> isize { fn main() { let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; vec.sort_by(|a, b| b.cmp(a)); - vec.sort_by(|a, b| (b + 5).abs().cmp(&(a+5).abs())); + vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); vec.sort_by(|a, b| id(-b).cmp(&id(-a))); + // Negative examples (shouldn't be changed) + let c = &7; + vec.sort_by(|a, b| (b - a).cmp(&(a - b))); + vec.sort_by(|_, b| b.cmp(&5)); + vec.sort_by(|_, b| b.cmp(c)); + vec.sort_by(|a, _| a.cmp(c)); + vec.sort_by(|a, b| a.cmp(b)); } diff --git a/tests/ui/sort_by_key_reverse.stderr b/tests/ui/sort_by_key_reverse.stderr index 3d26ddae78a..b757c8a6176 100644 --- a/tests/ui/sort_by_key_reverse.stderr +++ b/tests/ui/sort_by_key_reverse.stderr @@ -9,8 +9,8 @@ LL | vec.sort_by(|a, b| b.cmp(a)); error: use Vec::sort_by_key here instead --> $DIR/sort_by_key_reverse.rs:13:5 | -LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a+5).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse((b + 5).abs()))` +LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse((b + 5).abs()))` error: use Vec::sort_by_key here instead --> $DIR/sort_by_key_reverse.rs:14:5 From 059e8edd15401d5544260e4058731dc8818578d5 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sun, 24 May 2020 19:45:41 -0700 Subject: [PATCH 149/526] Detect also a non-reversed comparison --- clippy_lints/src/lib.rs | 10 ++-- ...{sort_by_key_reverse.rs => sort_by_key.rs} | 52 +++++++++++-------- ...by_key_reverse.fixed => sort_by_key.fixed} | 8 ++- ...{sort_by_key_reverse.rs => sort_by_key.rs} | 6 ++- tests/ui/sort_by_key.stderr | 48 +++++++++++++++++ tests/ui/sort_by_key_reverse.stderr | 22 -------- 6 files changed, 94 insertions(+), 52 deletions(-) rename clippy_lints/src/{sort_by_key_reverse.rs => sort_by_key.rs} (83%) rename tests/ui/{sort_by_key_reverse.fixed => sort_by_key.fixed} (72%) rename tests/ui/{sort_by_key_reverse.rs => sort_by_key.rs} (78%) create mode 100644 tests/ui/sort_by_key.stderr delete mode 100644 tests/ui/sort_by_key_reverse.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e7a4c1ecaa9..9e826316f21 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -304,7 +304,7 @@ mod serde_api; mod shadow; mod single_component_path_imports; mod slow_vector_initialization; -mod sort_by_key_reverse; +mod sort_by_key; mod strings; mod suspicious_trait_impl; mod swap; @@ -780,7 +780,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &shadow::SHADOW_UNRELATED, &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, - &sort_by_key_reverse::SORT_BY_KEY_REVERSE, + &sort_by_key::SORT_BY_KEY, &strings::STRING_ADD, &strings::STRING_ADD_ASSIGN, &strings::STRING_LIT_AS_BYTES, @@ -998,7 +998,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast); store.register_late_pass(|| box redundant_clone::RedundantClone); store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit); - store.register_late_pass(|| box sort_by_key_reverse::SortByKeyReverse); + store.register_late_pass(|| box sort_by_key::SortByKey); store.register_late_pass(|| box types::RefToMut); store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants); store.register_late_pass(|| box missing_const_for_fn::MissingConstForFn); @@ -1394,7 +1394,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), - LintId::of(&sort_by_key_reverse::SORT_BY_KEY_REVERSE), + LintId::of(&sort_by_key::SORT_BY_KEY), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), @@ -1596,7 +1596,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ranges::RANGE_ZIP_WITH_LEN), LintId::of(&reference::DEREF_ADDROF), LintId::of(&reference::REF_IN_DEREF), - LintId::of(&sort_by_key_reverse::SORT_BY_KEY_REVERSE), + LintId::of(&sort_by_key::SORT_BY_KEY), LintId::of(&swap::MANUAL_SWAP), LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT), LintId::of(&transmute::CROSSPOINTER_TRANSMUTE), diff --git a/clippy_lints/src/sort_by_key_reverse.rs b/clippy_lints/src/sort_by_key.rs similarity index 83% rename from clippy_lints/src/sort_by_key_reverse.rs rename to clippy_lints/src/sort_by_key.rs index ea850955db1..109845a28f4 100644 --- a/clippy_lints/src/sort_by_key_reverse.rs +++ b/clippy_lints/src/sort_by_key.rs @@ -11,33 +11,35 @@ use rustc_span::symbol::Ident; declare_clippy_lint! { /// **What it does:** /// Detects when people use `Vec::sort_by` and pass in a function - /// which compares the second argument to the first. + /// which compares the two arguments, either directly or indirectly. /// /// **Why is this bad?** - /// It is more clear to use `Vec::sort_by_key` and `std::cmp::Reverse` + /// It is more clear to use `Vec::sort_by_key` (or + /// `Vec::sort_by_key` and `std::cmp::Reverse` if necessary) than + /// using /// /// **Known problems:** None. /// /// **Example:** /// /// ```rust - /// vec.sort_by(|a, b| b.foo().cmp(&a.foo())); + /// vec.sort_by(|a, b| a.foo().cmp(b.foo())); /// ``` /// Use instead: /// ```rust - /// vec.sort_by_key(|e| Reverse(e.foo())); + /// vec.sort_by_key(|a| a.foo()); /// ``` - pub SORT_BY_KEY_REVERSE, + pub SORT_BY_KEY, complexity, "Use of `Vec::sort_by` when `Vec::sort_by_key` would be clearer" } -declare_lint_pass!(SortByKeyReverse => [SORT_BY_KEY_REVERSE]); +declare_lint_pass!(SortByKey => [SORT_BY_KEY]); struct LintTrigger { vec_name: String, closure_arg: String, - closure_reverse_body: String, + closure_body: String, unstable: bool, } @@ -154,43 +156,49 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> if utils::match_type(cx, &cx.tables.expr_ty(vec), &paths::VEC); if let closure_body = cx.tcx.hir().body(*closure_body_id); if let &[ - Param { pat: Pat { kind: PatKind::Binding(_, _, a_ident, _), .. }, ..}, - Param { pat: Pat { kind: PatKind::Binding(_, _, b_ident, _), .. }, .. } + Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..}, + Param { pat: Pat { kind: PatKind::Binding(_, _, right_ident, _), .. }, .. } ] = &closure_body.params; - if let ExprKind::MethodCall(method_path, _, [ref b_expr, ref a_expr]) = &closure_body.value.kind; + if let ExprKind::MethodCall(method_path, _, [ref left_expr, ref right_expr]) = &closure_body.value.kind; if method_path.ident.name.to_ident_string() == "cmp"; - if mirrored_exprs(&cx, &a_expr, &a_ident, &b_expr, &b_ident); then { + let (closure_body, closure_arg) = if mirrored_exprs( + &cx, + &left_expr, + &left_ident, + &right_expr, + &right_ident + ) { + (Sugg::hir(cx, &left_expr, "..").to_string(), left_ident.name.to_string()) + } else if mirrored_exprs(&cx, &left_expr, &right_ident, &right_expr, &left_ident) { + (format!("Reverse({})", Sugg::hir(cx, &left_expr, "..").to_string()), right_ident.name.to_string()) + } else { + return None; + }; let vec_name = Sugg::hir(cx, &args[0], "..").to_string(); let unstable = name == "sort_unstable_by"; - let closure_arg = format!("&{}", b_ident.name.to_ident_string()); - let closure_reverse_body = Sugg::hir(cx, &b_expr, "..").to_string(); - // Get rid of parentheses, because they aren't needed anymore - // while closure_reverse_body.chars().next() == Some('(') && closure_reverse_body.chars().last() == Some(')') { - // closure_reverse_body = String::from(&closure_reverse_body[1..closure_reverse_body.len()-1]); - // } - Some(LintTrigger { vec_name, unstable, closure_arg, closure_reverse_body }) + Some(LintTrigger { vec_name, unstable, closure_arg, closure_body }) } else { None } } } -impl LateLintPass<'_, '_> for SortByKeyReverse { +impl LateLintPass<'_, '_> for SortByKey { fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { if let Some(trigger) = detect_lint(cx, expr) { utils::span_lint_and_sugg( cx, - SORT_BY_KEY_REVERSE, + SORT_BY_KEY, expr.span, "use Vec::sort_by_key here instead", "try", format!( - "{}.sort{}_by_key(|{}| Reverse({}))", + "{}.sort{}_by_key(|&{}| {})", trigger.vec_name, if trigger.unstable { "_unstable" } else { "" }, trigger.closure_arg, - trigger.closure_reverse_body, + trigger.closure_body, ), Applicability::MachineApplicable, ); diff --git a/tests/ui/sort_by_key_reverse.fixed b/tests/ui/sort_by_key.fixed similarity index 72% rename from tests/ui/sort_by_key_reverse.fixed rename to tests/ui/sort_by_key.fixed index 722675a6b71..f6535c8d8f5 100644 --- a/tests/ui/sort_by_key_reverse.fixed +++ b/tests/ui/sort_by_key.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::sort_by_key_reverse)] +#![warn(clippy::sort_by_key)] use std::cmp::Reverse; @@ -9,6 +9,11 @@ fn id(x: isize) -> isize { fn main() { let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; + // Forward examples + vec.sort_by_key(|&a| a); + vec.sort_by_key(|&a| (a + 5).abs()); + vec.sort_by_key(|&a| id(-a)); + // Reverse examples vec.sort_by_key(|&b| Reverse(b)); vec.sort_by_key(|&b| Reverse((b + 5).abs())); vec.sort_by_key(|&b| Reverse(id(-b))); @@ -18,5 +23,4 @@ fn main() { vec.sort_by(|_, b| b.cmp(&5)); vec.sort_by(|_, b| b.cmp(c)); vec.sort_by(|a, _| a.cmp(c)); - vec.sort_by(|a, b| a.cmp(b)); } diff --git a/tests/ui/sort_by_key_reverse.rs b/tests/ui/sort_by_key.rs similarity index 78% rename from tests/ui/sort_by_key_reverse.rs rename to tests/ui/sort_by_key.rs index 601621ffa9f..953c573d406 100644 --- a/tests/ui/sort_by_key_reverse.rs +++ b/tests/ui/sort_by_key.rs @@ -9,6 +9,11 @@ fn id(x: isize) -> isize { fn main() { let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; + // Forward examples + vec.sort_by(|a, b| a.cmp(b)); + vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); + vec.sort_by(|a, b| id(-a).cmp(&id(-b))); + // Reverse examples vec.sort_by(|a, b| b.cmp(a)); vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); vec.sort_by(|a, b| id(-b).cmp(&id(-a))); @@ -18,5 +23,4 @@ fn main() { vec.sort_by(|_, b| b.cmp(&5)); vec.sort_by(|_, b| b.cmp(c)); vec.sort_by(|a, _| a.cmp(c)); - vec.sort_by(|a, b| a.cmp(b)); } diff --git a/tests/ui/sort_by_key.stderr b/tests/ui/sort_by_key.stderr new file mode 100644 index 00000000000..fa6a9a0fb10 --- /dev/null +++ b/tests/ui/sort_by_key.stderr @@ -0,0 +1,48 @@ +error: use Vec::sort_by_key here instead + --> $DIR/sort_by_key.rs:13:5 + | +LL | vec.sort_by(|a, b| a.cmp(b)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&a| a)` + | + = note: `-D clippy::sort-by-key` implied by `-D warnings` + +error: use Vec::sort_by_key here instead + --> $DIR/sort_by_key.rs:14:5 + | +LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&a| (a + 5).abs())` + +error: use Vec::sort_by_key here instead + --> $DIR/sort_by_key.rs:15:5 + | +LL | vec.sort_by(|a, b| id(-a).cmp(&id(-b))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&a| id(-a))` + +error: use Vec::sort_by_key here instead + --> $DIR/sort_by_key.rs:17:5 + | +LL | vec.sort_by(|a, b| b.cmp(a)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(b))` + +error: use Vec::sort_by_key here instead + --> $DIR/sort_by_key.rs:18:5 + | +LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse((b + 5).abs()))` + +error: use Vec::sort_by_key here instead + --> $DIR/sort_by_key.rs:19:5 + | +LL | vec.sort_by(|a, b| id(-b).cmp(&id(-a))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(id(-b)))` + +error: unknown clippy lint: clippy::sort_by_key_reverse + --> $DIR/sort_by_key.rs:2:9 + | +LL | #![warn(clippy::sort_by_key_reverse)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::sort_by_key` + | + = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/sort_by_key_reverse.stderr b/tests/ui/sort_by_key_reverse.stderr deleted file mode 100644 index b757c8a6176..00000000000 --- a/tests/ui/sort_by_key_reverse.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key_reverse.rs:12:5 - | -LL | vec.sort_by(|a, b| b.cmp(a)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(b))` - | - = note: `-D clippy::sort-by-key-reverse` implied by `-D warnings` - -error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key_reverse.rs:13:5 - | -LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse((b + 5).abs()))` - -error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key_reverse.rs:14:5 - | -LL | vec.sort_by(|a, b| id(-b).cmp(&id(-a))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(id(-b)))` - -error: aborting due to 3 previous errors - From 07886a97640b89f72b70805f519bd9d42d7d1c4e Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sun, 24 May 2020 20:05:58 -0700 Subject: [PATCH 150/526] Detect also when works --- clippy_lints/src/sort_by_key.rs | 49 ++++++++++++++++++++++++++++----- tests/ui/sort_by_key.fixed | 2 +- tests/ui/sort_by_key.stderr | 4 +-- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/sort_by_key.rs b/clippy_lints/src/sort_by_key.rs index 109845a28f4..f720d14473a 100644 --- a/clippy_lints/src/sort_by_key.rs +++ b/clippy_lints/src/sort_by_key.rs @@ -3,7 +3,7 @@ use crate::utils::paths; use crate::utils::sugg::Sugg; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, QPath}; +use rustc_hir::{Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Ident; @@ -16,7 +16,7 @@ declare_clippy_lint! { /// **Why is this bad?** /// It is more clear to use `Vec::sort_by_key` (or /// `Vec::sort_by_key` and `std::cmp::Reverse` if necessary) than - /// using + /// using /// /// **Known problems:** None. /// @@ -36,7 +36,17 @@ declare_clippy_lint! { declare_lint_pass!(SortByKey => [SORT_BY_KEY]); -struct LintTrigger { +enum LintTrigger { + Sort(SortDetection), + SortByKey(SortByKeyDetection), +} + +struct SortDetection { + vec_name: String, + unstable: bool, +} + +struct SortByKeyDetection { vec_name: String, closure_arg: String, closure_body: String, @@ -177,7 +187,18 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> }; let vec_name = Sugg::hir(cx, &args[0], "..").to_string(); let unstable = name == "sort_unstable_by"; - Some(LintTrigger { vec_name, unstable, closure_arg, closure_body }) + if_chain! { + if let ExprKind::Path(QPath::Resolved(_, Path { + segments: [PathSegment { ident: left_name, .. }], .. + })) = &left_expr.kind; + if left_name == left_ident; + then { + Some(LintTrigger::Sort(SortDetection { vec_name, unstable })) + } + else { + Some(LintTrigger::SortByKey(SortByKeyDetection { vec_name, unstable, closure_arg, closure_body })) + } + } } else { None } @@ -186,8 +207,8 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> impl LateLintPass<'_, '_> for SortByKey { fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { - if let Some(trigger) = detect_lint(cx, expr) { - utils::span_lint_and_sugg( + match detect_lint(cx, expr) { + Some(LintTrigger::SortByKey(trigger)) => utils::span_lint_and_sugg( cx, SORT_BY_KEY, expr.span, @@ -201,7 +222,21 @@ impl LateLintPass<'_, '_> for SortByKey { trigger.closure_body, ), Applicability::MachineApplicable, - ); + ), + Some(LintTrigger::Sort(trigger)) => utils::span_lint_and_sugg( + cx, + SORT_BY_KEY, + expr.span, + "use Vec::sort here instead", + "try", + format!( + "{}.sort{}()", + trigger.vec_name, + if trigger.unstable { "_unstable" } else { "" }, + ), + Applicability::MachineApplicable, + ), + None => {}, } } } diff --git a/tests/ui/sort_by_key.fixed b/tests/ui/sort_by_key.fixed index f6535c8d8f5..bb88df1a56c 100644 --- a/tests/ui/sort_by_key.fixed +++ b/tests/ui/sort_by_key.fixed @@ -10,7 +10,7 @@ fn id(x: isize) -> isize { fn main() { let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; // Forward examples - vec.sort_by_key(|&a| a); + vec.sort(); vec.sort_by_key(|&a| (a + 5).abs()); vec.sort_by_key(|&a| id(-a)); // Reverse examples diff --git a/tests/ui/sort_by_key.stderr b/tests/ui/sort_by_key.stderr index fa6a9a0fb10..291fd5500f7 100644 --- a/tests/ui/sort_by_key.stderr +++ b/tests/ui/sort_by_key.stderr @@ -1,8 +1,8 @@ -error: use Vec::sort_by_key here instead +error: use Vec::sort here instead --> $DIR/sort_by_key.rs:13:5 | LL | vec.sort_by(|a, b| a.cmp(b)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&a| a)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort()` | = note: `-D clippy::sort-by-key` implied by `-D warnings` From 015ab9f9259d58a48c171276f6e7190528f1a9ad Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 28 May 2020 18:18:25 -0700 Subject: [PATCH 151/526] Renamed to --- clippy_lints/src/lib.rs | 10 +++++----- .../{sort_by_key.rs => unnecessary_sort_by.rs} | 18 +++++++++--------- ..._by_key.fixed => unnecessary_sort_by.fixed} | 0 .../{sort_by_key.rs => unnecessary_sort_by.rs} | 0 ...y_key.stderr => unnecessary_sort_by.stderr} | 0 5 files changed, 14 insertions(+), 14 deletions(-) rename clippy_lints/src/{sort_by_key.rs => unnecessary_sort_by.rs} (95%) rename tests/ui/{sort_by_key.fixed => unnecessary_sort_by.fixed} (100%) rename tests/ui/{sort_by_key.rs => unnecessary_sort_by.rs} (100%) rename tests/ui/{sort_by_key.stderr => unnecessary_sort_by.stderr} (100%) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9e826316f21..46df743b5bf 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -304,7 +304,7 @@ mod serde_api; mod shadow; mod single_component_path_imports; mod slow_vector_initialization; -mod sort_by_key; +mod unnecessary_sort_by; mod strings; mod suspicious_trait_impl; mod swap; @@ -780,7 +780,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &shadow::SHADOW_UNRELATED, &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, - &sort_by_key::SORT_BY_KEY, + &unnecessary_sort_by::UNNECESSARY_SORT_BY, &strings::STRING_ADD, &strings::STRING_ADD_ASSIGN, &strings::STRING_LIT_AS_BYTES, @@ -998,7 +998,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast); store.register_late_pass(|| box redundant_clone::RedundantClone); store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit); - store.register_late_pass(|| box sort_by_key::SortByKey); + store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy); store.register_late_pass(|| box types::RefToMut); store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants); store.register_late_pass(|| box missing_const_for_fn::MissingConstForFn); @@ -1394,7 +1394,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), - LintId::of(&sort_by_key::SORT_BY_KEY), + LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), @@ -1596,7 +1596,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ranges::RANGE_ZIP_WITH_LEN), LintId::of(&reference::DEREF_ADDROF), LintId::of(&reference::REF_IN_DEREF), - LintId::of(&sort_by_key::SORT_BY_KEY), + LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), LintId::of(&swap::MANUAL_SWAP), LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT), LintId::of(&transmute::CROSSPOINTER_TRANSMUTE), diff --git a/clippy_lints/src/sort_by_key.rs b/clippy_lints/src/unnecessary_sort_by.rs similarity index 95% rename from clippy_lints/src/sort_by_key.rs rename to clippy_lints/src/unnecessary_sort_by.rs index f720d14473a..c0858ec4c88 100644 --- a/clippy_lints/src/sort_by_key.rs +++ b/clippy_lints/src/unnecessary_sort_by.rs @@ -14,9 +14,9 @@ declare_clippy_lint! { /// which compares the two arguments, either directly or indirectly. /// /// **Why is this bad?** - /// It is more clear to use `Vec::sort_by_key` (or - /// `Vec::sort_by_key` and `std::cmp::Reverse` if necessary) than - /// using + /// It is more clear to use `Vec::sort_by_key` (or `Vec::sort` if + /// possible) than to use `Vec::sort_by` and and a more complicated + /// closure. /// /// **Known problems:** None. /// @@ -29,12 +29,12 @@ declare_clippy_lint! { /// ```rust /// vec.sort_by_key(|a| a.foo()); /// ``` - pub SORT_BY_KEY, + pub UNNECESSARY_SORT_BY, complexity, - "Use of `Vec::sort_by` when `Vec::sort_by_key` would be clearer" + "Use of `Vec::sort_by` when `Vec::sort_by_key` or `Vec::sort` would be clearer" } -declare_lint_pass!(SortByKey => [SORT_BY_KEY]); +declare_lint_pass!(UnnecessarySortBy => [UNNECESSARY_SORT_BY]); enum LintTrigger { Sort(SortDetection), @@ -205,12 +205,12 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> } } -impl LateLintPass<'_, '_> for SortByKey { +impl LateLintPass<'_, '_> for UnnecessarySortBy { fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { match detect_lint(cx, expr) { Some(LintTrigger::SortByKey(trigger)) => utils::span_lint_and_sugg( cx, - SORT_BY_KEY, + UNNECESSARY_SORT_BY, expr.span, "use Vec::sort_by_key here instead", "try", @@ -225,7 +225,7 @@ impl LateLintPass<'_, '_> for SortByKey { ), Some(LintTrigger::Sort(trigger)) => utils::span_lint_and_sugg( cx, - SORT_BY_KEY, + UNNECESSARY_SORT_BY, expr.span, "use Vec::sort here instead", "try", diff --git a/tests/ui/sort_by_key.fixed b/tests/ui/unnecessary_sort_by.fixed similarity index 100% rename from tests/ui/sort_by_key.fixed rename to tests/ui/unnecessary_sort_by.fixed diff --git a/tests/ui/sort_by_key.rs b/tests/ui/unnecessary_sort_by.rs similarity index 100% rename from tests/ui/sort_by_key.rs rename to tests/ui/unnecessary_sort_by.rs diff --git a/tests/ui/sort_by_key.stderr b/tests/ui/unnecessary_sort_by.stderr similarity index 100% rename from tests/ui/sort_by_key.stderr rename to tests/ui/unnecessary_sort_by.stderr From 20cb512e81ad03a014b40c377a01fdebaea66963 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sun, 31 May 2020 12:06:32 -0700 Subject: [PATCH 152/526] Updated test cases and formatted --- clippy_lints/src/lib.rs | 2 +- tests/ui/unnecessary_sort_by.fixed | 1 - tests/ui/unnecessary_sort_by.rs | 1 - tests/ui/unnecessary_sort_by.stderr | 24 ++++++++---------------- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 46df743b5bf..fd832d11577 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -304,7 +304,6 @@ mod serde_api; mod shadow; mod single_component_path_imports; mod slow_vector_initialization; -mod unnecessary_sort_by; mod strings; mod suspicious_trait_impl; mod swap; @@ -319,6 +318,7 @@ mod try_err; mod types; mod unicode; mod unnamed_address; +mod unnecessary_sort_by; mod unsafe_removed_from_name; mod unused_io_amount; mod unused_self; diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index bb88df1a56c..4521ae38d49 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -1,5 +1,4 @@ // run-rustfix -#![warn(clippy::sort_by_key)] use std::cmp::Reverse; diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index 953c573d406..fdb5a823369 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -1,5 +1,4 @@ // run-rustfix -#![warn(clippy::sort_by_key_reverse)] use std::cmp::Reverse; diff --git a/tests/ui/unnecessary_sort_by.stderr b/tests/ui/unnecessary_sort_by.stderr index 291fd5500f7..b6365c1709d 100644 --- a/tests/ui/unnecessary_sort_by.stderr +++ b/tests/ui/unnecessary_sort_by.stderr @@ -1,48 +1,40 @@ error: use Vec::sort here instead - --> $DIR/sort_by_key.rs:13:5 + --> $DIR/unnecessary_sort_by.rs:12:5 | LL | vec.sort_by(|a, b| a.cmp(b)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort()` | - = note: `-D clippy::sort-by-key` implied by `-D warnings` + = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key.rs:14:5 + --> $DIR/unnecessary_sort_by.rs:13:5 | LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&a| (a + 5).abs())` error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key.rs:15:5 + --> $DIR/unnecessary_sort_by.rs:14:5 | LL | vec.sort_by(|a, b| id(-a).cmp(&id(-b))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&a| id(-a))` error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key.rs:17:5 + --> $DIR/unnecessary_sort_by.rs:16:5 | LL | vec.sort_by(|a, b| b.cmp(a)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(b))` error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key.rs:18:5 + --> $DIR/unnecessary_sort_by.rs:17:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse((b + 5).abs()))` error: use Vec::sort_by_key here instead - --> $DIR/sort_by_key.rs:19:5 + --> $DIR/unnecessary_sort_by.rs:18:5 | LL | vec.sort_by(|a, b| id(-b).cmp(&id(-a))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(id(-b)))` -error: unknown clippy lint: clippy::sort_by_key_reverse - --> $DIR/sort_by_key.rs:2:9 - | -LL | #![warn(clippy::sort_by_key_reverse)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::sort_by_key` - | - = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` - -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors From 32fde0b5116b3a1115d11c49a9bf2af2ebdd5773 Mon Sep 17 00:00:00 2001 From: Ericko Samudera <ericko.samudera@gmail.com> Date: Mon, 25 May 2020 23:22:01 +0700 Subject: [PATCH 153/526] New lint: iter_next_slice --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 3 + clippy_lints/src/loops.rs | 26 ++++----- clippy_lints/src/methods/mod.rs | 84 ++++++++++++++++++++++++++- clippy_lints/src/needless_continue.rs | 2 +- src/lintlist/mod.rs | 7 +++ tests/ui/into_iter_on_ref.fixed | 2 + tests/ui/into_iter_on_ref.rs | 2 + tests/ui/into_iter_on_ref.stderr | 8 ++- tests/ui/iter_next_slice.fixed | 24 ++++++++ tests/ui/iter_next_slice.rs | 24 ++++++++ tests/ui/iter_next_slice.stderr | 28 +++++++++ tests/ui/needless_collect.fixed | 2 +- tests/ui/needless_collect.stderr | 16 ++--- 14 files changed, 204 insertions(+), 25 deletions(-) create mode 100644 tests/ui/iter_next_slice.fixed create mode 100644 tests/ui/iter_next_slice.rs create mode 100644 tests/ui/iter_next_slice.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ac9057199f..714e25a32ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1401,6 +1401,7 @@ Released 2018-09-13 [`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements [`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect [`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop +[`iter_next_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_slice [`iter_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth [`iter_nth_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth_zero [`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 057d39d4c82..7c16dbd8f26 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -669,6 +669,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::INTO_ITER_ON_REF, &methods::ITERATOR_STEP_BY_ZERO, &methods::ITER_CLONED_COLLECT, + &methods::ITER_NEXT_SLICE, &methods::ITER_NTH, &methods::ITER_NTH_ZERO, &methods::ITER_SKIP_NEXT, @@ -1303,6 +1304,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::INTO_ITER_ON_REF), LintId::of(&methods::ITERATOR_STEP_BY_ZERO), LintId::of(&methods::ITER_CLONED_COLLECT), + LintId::of(&methods::ITER_NEXT_SLICE), LintId::of(&methods::ITER_NTH), LintId::of(&methods::ITER_NTH_ZERO), LintId::of(&methods::ITER_SKIP_NEXT), @@ -1483,6 +1485,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::CHARS_NEXT_CMP), LintId::of(&methods::INTO_ITER_ON_REF), LintId::of(&methods::ITER_CLONED_COLLECT), + LintId::of(&methods::ITER_NEXT_SLICE), LintId::of(&methods::ITER_NTH_ZERO), LintId::of(&methods::ITER_SKIP_NEXT), LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC), diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 38a5829b3f7..dbe41823a9c 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -27,7 +27,7 @@ use rustc_middle::middle::region; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::BytePos; +use rustc_span::symbol::Symbol; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; use std::iter::{once, Iterator}; use std::mem; @@ -2381,32 +2381,32 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, ' match_type(cx, ty, &paths::BTREEMAP) || is_type_diagnostic_item(cx, ty, sym!(hashmap_type)) { if method.ident.name == sym!(len) { - let span = shorten_needless_collect_span(expr); + let span = shorten_span(expr, sym!(collect)); span_lint_and_sugg( cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, "replace with", - ".count()".to_string(), + "count()".to_string(), Applicability::MachineApplicable, ); } if method.ident.name == sym!(is_empty) { - let span = shorten_needless_collect_span(expr); + let span = shorten_span(expr, sym!(iter)); span_lint_and_sugg( cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, "replace with", - ".next().is_none()".to_string(), + "get(0).is_none()".to_string(), Applicability::MachineApplicable, ); } if method.ident.name == sym!(contains) { let contains_arg = snippet(cx, args[1].span, "??"); - let span = shorten_needless_collect_span(expr); + let span = shorten_span(expr, sym!(collect)); span_lint_and_then( cx, NEEDLESS_COLLECT, @@ -2422,7 +2422,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, ' span, "replace with", format!( - ".any(|{}| x == {})", + "any(|{}| x == {})", arg, pred ), Applicability::MachineApplicable, @@ -2435,13 +2435,13 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, ' } } -fn shorten_needless_collect_span(expr: &Expr<'_>) -> Span { - if_chain! { - if let ExprKind::MethodCall(_, _, ref args) = expr.kind; - if let ExprKind::MethodCall(_, ref span, _) = args[0].kind; - then { - return expr.span.with_lo(span.lo() - BytePos(1)); +fn shorten_span(expr: &Expr<'_>, target_fn_name: Symbol) -> Span { + let mut current_expr = expr; + while let ExprKind::MethodCall(ref path, ref span, ref args) = current_expr.kind { + if path.ident.name == target_fn_name { + return expr.span.with_lo(span.lo()); } + current_expr = &args[0]; } unreachable!() } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 32b3b7f7947..7cb04d4d81c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -26,7 +26,7 @@ use rustc_span::symbol::{sym, SymbolStr}; use crate::consts::{constant, Constant}; use crate::utils::usage::mutated_variables; use crate::utils::{ - get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, implements_trait, in_macro, is_copy, + get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro, is_copy, is_ctor_or_promotable_const_function, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath, match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, remove_blocks, return_ty, same_tys, single_segment_path, snippet, snippet_with_applicability, @@ -1242,6 +1242,32 @@ declare_clippy_lint! { "using `as_ref().map(Deref::deref)`, which is more succinctly expressed as `as_deref()`" } +declare_clippy_lint! { + /// **What it does:** Checks for usage of `iter().next()` on a Slice or an Array + /// + /// **Why is this bad?** These can be shortened into `.get()` + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// # let a = [1, 2, 3]; + /// # let b = vec![1, 2, 3]; + /// a[2..].iter().next(); + /// b.iter().next(); + /// ``` + /// should be written as: + /// ```rust + /// # let a = [1, 2, 3]; + /// # let b = vec![1, 2, 3]; + /// a.get(2); + /// b.get(0); + /// ``` + pub ITER_NEXT_SLICE, + style, + "using `.iter().next()` on a sliced array, which can be shortened to just `.get()`" +} + declare_lint_pass!(Methods => [ UNWRAP_USED, EXPECT_USED, @@ -1273,6 +1299,7 @@ declare_lint_pass!(Methods => [ FIND_MAP, MAP_FLATTEN, ITERATOR_STEP_BY_ZERO, + ITER_NEXT_SLICE, ITER_NTH, ITER_NTH_ZERO, ITER_SKIP_NEXT, @@ -1320,6 +1347,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { }, ["next", "filter"] => lint_filter_next(cx, expr, arg_lists[1]), ["next", "skip_while"] => lint_skip_while_next(cx, expr, arg_lists[1]), + ["next", "iter"] => lint_iter_next(cx, expr, arg_lists[1]), ["map", "filter"] => lint_filter_map(cx, expr, arg_lists[1], arg_lists[0]), ["map", "filter_map"] => lint_filter_map_map(cx, expr, arg_lists[1], arg_lists[0]), ["next", "filter_map"] => lint_filter_map_next(cx, expr, arg_lists[1]), @@ -2184,6 +2212,60 @@ fn lint_step_by<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr<'_>, args } } +fn lint_iter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>, iter_args: &'tcx [hir::Expr<'_>]) { + let caller_expr = &iter_args[0]; + + // Skip lint if the `iter().next()` expression is a for loop argument, + // since it is already covered by `&loops::ITER_NEXT_LOOP` + let mut parent_expr_opt = get_parent_expr(cx, expr); + while let Some(parent_expr) = parent_expr_opt { + if higher::for_loop(parent_expr).is_some() { + return; + } + parent_expr_opt = get_parent_expr(cx, parent_expr); + } + + if derefs_to_slice(cx, caller_expr, cx.tables.expr_ty(caller_expr)).is_some() { + // caller is a Slice + if_chain! { + if let hir::ExprKind::Index(ref caller_var, ref index_expr) = &caller_expr.kind; + if let Some(higher::Range { start: Some(start_expr), end: None, limits: ast::RangeLimits::HalfOpen }) + = higher::range(cx, index_expr); + if let hir::ExprKind::Lit(ref start_lit) = &start_expr.kind; + if let ast::LitKind::Int(start_idx, _) = start_lit.node; + then { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + ITER_NEXT_SLICE, + expr.span, + "Using `.iter().next()` on a Slice without end index.", + "try calling", + format!("{}.get({})", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability), start_idx), + applicability, + ); + } + } + } else if is_type_diagnostic_item(cx, cx.tables.expr_ty(caller_expr), sym!(vec_type)) + || matches!(&walk_ptrs_ty(cx.tables.expr_ty(caller_expr)).kind, ty::Array(_, _)) + { + // caller is a Vec or an Array + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + ITER_NEXT_SLICE, + expr.span, + "Using `.iter().next()` on an array", + "try calling", + format!( + "{}.get(0)", + snippet_with_applicability(cx, caller_expr.span, "..", &mut applicability) + ), + applicability, + ); + } +} + fn lint_iter_nth<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, expr: &hir::Expr<'_>, diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 28183810df4..a971d041ca6 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -424,7 +424,7 @@ fn erode_from_back(s: &str) -> String { } fn span_of_first_expr_in_block(block: &ast::Block) -> Option<Span> { - block.stmts.iter().next().map(|stmt| stmt.span) + block.stmts.get(0).map(|stmt| stmt.span) } #[cfg(test)] diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 8211a57b564..79da1f3702e 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -934,6 +934,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "loops", }, + Lint { + name: "iter_next_slice", + group: "style", + desc: "using `.iter().next()` on a sliced array, which can be shortened to just `.get()`", + deprecation: None, + module: "methods", + }, Lint { name: "iter_nth", group: "perf", diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed index c30d23de3f8..7f92d0dbdc9 100644 --- a/tests/ui/into_iter_on_ref.fixed +++ b/tests/ui/into_iter_on_ref.fixed @@ -40,4 +40,6 @@ fn main() { let _ = (&HashSet::<i32>::new()).iter(); //~ WARN equivalent to .iter() let _ = std::path::Path::new("12/34").iter(); //~ WARN equivalent to .iter() let _ = std::path::PathBuf::from("12/34").iter(); //~ ERROR equivalent to .iter() + + let _ = (&[1, 2, 3]).iter().next(); //~ WARN equivalent to .iter() } diff --git a/tests/ui/into_iter_on_ref.rs b/tests/ui/into_iter_on_ref.rs index 94bc1689619..416056d3fdb 100644 --- a/tests/ui/into_iter_on_ref.rs +++ b/tests/ui/into_iter_on_ref.rs @@ -40,4 +40,6 @@ fn main() { let _ = (&HashSet::<i32>::new()).into_iter(); //~ WARN equivalent to .iter() let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter() let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() + + let _ = (&[1, 2, 3]).into_iter().next(); //~ WARN equivalent to .iter() } diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr index 80e2d104f82..1cd6400b019 100644 --- a/tests/ui/into_iter_on_ref.stderr +++ b/tests/ui/into_iter_on_ref.stderr @@ -156,5 +156,11 @@ error: this `.into_iter()` call is equivalent to `.iter()` and will not move the LL | let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` -error: aborting due to 26 previous errors +error: this `.into_iter()` call is equivalent to `.iter()` and will not move the `array` + --> $DIR/into_iter_on_ref.rs:44:26 + | +LL | let _ = (&[1, 2, 3]).into_iter().next(); //~ WARN equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` + +error: aborting due to 27 previous errors diff --git a/tests/ui/iter_next_slice.fixed b/tests/ui/iter_next_slice.fixed new file mode 100644 index 00000000000..79c1db87ac3 --- /dev/null +++ b/tests/ui/iter_next_slice.fixed @@ -0,0 +1,24 @@ +// run-rustfix +#![warn(clippy::iter_next_slice)] + +fn main() { + // test code goes here + let s = [1, 2, 3]; + let v = vec![1, 2, 3]; + + s.get(0); + // Should be replaced by s.get(0) + + s.get(2); + // Should be replaced by s.get(2) + + v.get(5); + // Should be replaced by v.get(5) + + v.get(0); + // Should be replaced by v.get(0) + + let o = Some(5); + o.iter().next(); + // Shouldn't be linted since this is not a Slice or an Array +} diff --git a/tests/ui/iter_next_slice.rs b/tests/ui/iter_next_slice.rs new file mode 100644 index 00000000000..ef9a55f3d99 --- /dev/null +++ b/tests/ui/iter_next_slice.rs @@ -0,0 +1,24 @@ +// run-rustfix +#![warn(clippy::iter_next_slice)] + +fn main() { + // test code goes here + let s = [1, 2, 3]; + let v = vec![1, 2, 3]; + + s.iter().next(); + // Should be replaced by s.get(0) + + s[2..].iter().next(); + // Should be replaced by s.get(2) + + v[5..].iter().next(); + // Should be replaced by v.get(5) + + v.iter().next(); + // Should be replaced by v.get(0) + + let o = Some(5); + o.iter().next(); + // Shouldn't be linted since this is not a Slice or an Array +} diff --git a/tests/ui/iter_next_slice.stderr b/tests/ui/iter_next_slice.stderr new file mode 100644 index 00000000000..bbf61df0cda --- /dev/null +++ b/tests/ui/iter_next_slice.stderr @@ -0,0 +1,28 @@ +error: Using `.iter().next()` on an array + --> $DIR/iter_next_slice.rs:9:5 + | +LL | s.iter().next(); + | ^^^^^^^^^^^^^^^ help: try calling: `s.get(0)` + | + = note: `-D clippy::iter-next-slice` implied by `-D warnings` + +error: Using `.iter().next()` on a Slice without end index. + --> $DIR/iter_next_slice.rs:12:5 + | +LL | s[2..].iter().next(); + | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)` + +error: Using `.iter().next()` on a Slice without end index. + --> $DIR/iter_next_slice.rs:15:5 + | +LL | v[5..].iter().next(); + | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)` + +error: Using `.iter().next()` on an array + --> $DIR/iter_next_slice.rs:18:5 + | +LL | v.iter().next(); + | ^^^^^^^^^^^^^^^ help: try calling: `v.get(0)` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index b4227eaf2f8..be37dc16b9a 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -9,7 +9,7 @@ use std::collections::{BTreeSet, HashMap, HashSet}; fn main() { let sample = [1; 5]; let len = sample.iter().count(); - if sample.iter().next().is_none() { + if sample.get(0).is_none() { // Empty } sample.iter().cloned().any(|x| x == 1); diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index 8884c8e1612..9113aad90dd 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,28 +1,28 @@ error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:11:28 + --> $DIR/needless_collect.rs:11:29 | LL | let len = sample.iter().collect::<Vec<_>>().len(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` | = note: `-D clippy::needless-collect` implied by `-D warnings` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:12:21 + --> $DIR/needless_collect.rs:12:15 | LL | if sample.iter().collect::<Vec<_>>().is_empty() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.next().is_none()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get(0).is_none()` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:15:27 + --> $DIR/needless_collect.rs:15:28 | LL | sample.iter().cloned().collect::<Vec<_>>().contains(&1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.any(|x| x == 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == 1)` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:16:34 + --> $DIR/needless_collect.rs:16:35 | LL | sample.iter().map(|x| (x, x)).collect::<HashMap<_, _>>().len(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `.count()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` error: aborting due to 4 previous errors From 7727c4ac7f3d4c977866bd8e6659a3e27f0bb6aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 28 May 2020 21:42:01 +0200 Subject: [PATCH 154/526] CONTRIBUTING: explain how to use cargo dev ra-setup Fixes #5514 --- CONTRIBUTING.md | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0f47ac98fd2..9f7bdcb1be7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,14 +12,16 @@ anything, feel free to ask questions on issues or visit the `#clippy` on [Discor All contributors are expected to follow the [Rust Code of Conduct]. -* [Getting started](#getting-started) - * [Finding something to fix/improve](#finding-something-to-fiximprove) -* [Writing code](#writing-code) -* [How Clippy works](#how-clippy-works) -* [Fixing nightly build failures](#fixing-build-failures-caused-by-rust) -* [Issue and PR Triage](#issue-and-pr-triage) -* [Bors and Homu](#bors-and-homu) -* [Contributions](#contributions) +- [Contributing to Clippy](#contributing-to-clippy) + - [Getting started](#getting-started) + - [Finding something to fix/improve](#finding-something-to-fiximprove) + - [Writing code](#writing-code) + - [Getting code-completion for rustc internals to work](#getting-code-completion-for-rustc-internals-to-work) + - [How Clippy works](#how-clippy-works) + - [Fixing build failures caused by Rust](#fixing-build-failures-caused-by-rust) + - [Issue and PR triage](#issue-and-pr-triage) + - [Bors and Homu](#bors-and-homu) + - [Contributions](#contributions) [Discord]: https://discord.gg/rust-lang [Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct @@ -91,6 +93,24 @@ quick read. [rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees [rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories +## Getting code-completion for rustc internals to work + +Unfortunately, [`rust-analyzer`][ra_homepage] does not (yet?) understand how Clippy uses compiler-internals +using `extern crate` and it also needs to be able to read the source files of the rustc-compiler which are not +available via a `rustup` component at the time of writing. +To work around this, you need to have a copy of the [rustc-repo][rustc_repo] available which can be obtained via +`git clone https://github.com/rust-lang/rust/`. +Then you can run a `cargo dev` command to automatically make Clippy use the rustc-repo via path-dependencies +which rust-analyzer will be able to understand. +Run `cargo dev ra-setup --repo-path <repo-path>` where `<repo-path>` is an absolute path to the rustc repo +you just cloned. +The command will add path-dependencies pointing towards rustc-crates inside the rustc repo to +Clippys `Cargo.toml`s and should allow rust-analyzer to understand most of the types that Clippy uses. +Just make sure to remove the dependencies again before finally making a pull request! + +[ra_homepage]: https://rust-analyzer.github.io/ +[rustc_repo]: https://github.com/rust-lang/rust/ + ## How Clippy works [`clippy_lints/src/lib.rs`][lint_crate_entry] imports all the different lint modules and registers in the [`LintStore`]. From 9a5baed482b68e0d9806e19eb9e8676d7ff3e1c2 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sun, 31 May 2020 15:09:12 -0700 Subject: [PATCH 155/526] Implement suggestions from phansch --- clippy_lints/src/unnecessary_sort_by.rs | 41 ++++++++++++++++++++----- tests/ui/unnecessary_sort_by.fixed | 7 +++-- tests/ui/unnecessary_sort_by.rs | 7 +++-- tests/ui/unnecessary_sort_by.stderr | 26 ++++++++++------ 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/unnecessary_sort_by.rs b/clippy_lints/src/unnecessary_sort_by.rs index c0858ec4c88..33d8331c292 100644 --- a/clippy_lints/src/unnecessary_sort_by.rs +++ b/clippy_lints/src/unnecessary_sort_by.rs @@ -18,15 +18,25 @@ declare_clippy_lint! { /// possible) than to use `Vec::sort_by` and and a more complicated /// closure. /// - /// **Known problems:** None. + /// **Known problems:** + /// If the suggested `Vec::sort_by_key` uses Reverse and it isn't + /// imported by a use statement in the current frame, then a `use` + /// statement that imports it will need to be added (which this lint + /// can't do). /// /// **Example:** /// /// ```rust - /// vec.sort_by(|a, b| a.foo().cmp(b.foo())); + /// # struct A; + /// # impl A { fn foo(&self) {} } + /// # let mut vec: Vec<A> = Vec::new(); + /// vec.sort_by(|a, b| a.foo().cmp(&b.foo())); /// ``` /// Use instead: /// ```rust + /// # struct A; + /// # impl A { fn foo(&self) {} } + /// # let mut vec: Vec<A> = Vec::new(); /// vec.sort_by_key(|a| a.foo()); /// ``` pub UNNECESSARY_SORT_BY, @@ -50,6 +60,7 @@ struct SortByKeyDetection { vec_name: String, closure_arg: String, closure_body: String, + reverse: bool, unstable: bool, } @@ -172,16 +183,16 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> if let ExprKind::MethodCall(method_path, _, [ref left_expr, ref right_expr]) = &closure_body.value.kind; if method_path.ident.name.to_ident_string() == "cmp"; then { - let (closure_body, closure_arg) = if mirrored_exprs( + let (closure_body, closure_arg, reverse) = if mirrored_exprs( &cx, &left_expr, &left_ident, &right_expr, &right_ident ) { - (Sugg::hir(cx, &left_expr, "..").to_string(), left_ident.name.to_string()) + (Sugg::hir(cx, &left_expr, "..").to_string(), left_ident.name.to_string(), false) } else if mirrored_exprs(&cx, &left_expr, &right_ident, &right_expr, &left_ident) { - (format!("Reverse({})", Sugg::hir(cx, &left_expr, "..").to_string()), right_ident.name.to_string()) + (Sugg::hir(cx, &left_expr, "..").to_string(), right_ident.name.to_string(), true) } else { return None; }; @@ -196,7 +207,13 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> Some(LintTrigger::Sort(SortDetection { vec_name, unstable })) } else { - Some(LintTrigger::SortByKey(SortByKeyDetection { vec_name, unstable, closure_arg, closure_body })) + Some(LintTrigger::SortByKey(SortByKeyDetection { + vec_name, + unstable, + closure_arg, + closure_body, + reverse + })) } } } else { @@ -219,9 +236,17 @@ impl LateLintPass<'_, '_> for UnnecessarySortBy { trigger.vec_name, if trigger.unstable { "_unstable" } else { "" }, trigger.closure_arg, - trigger.closure_body, + if trigger.reverse { + format!("Reverse({})", trigger.closure_body) + } else { + trigger.closure_body.to_string() + }, ), - Applicability::MachineApplicable, + if trigger.reverse { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + }, ), Some(LintTrigger::Sort(trigger)) => utils::span_lint_and_sugg( cx, diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index 4521ae38d49..779fd57707a 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -10,16 +10,17 @@ fn main() { let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; // Forward examples vec.sort(); + vec.sort_unstable(); vec.sort_by_key(|&a| (a + 5).abs()); - vec.sort_by_key(|&a| id(-a)); + vec.sort_unstable_by_key(|&a| id(-a)); // Reverse examples vec.sort_by_key(|&b| Reverse(b)); vec.sort_by_key(|&b| Reverse((b + 5).abs())); - vec.sort_by_key(|&b| Reverse(id(-b))); + vec.sort_unstable_by_key(|&b| Reverse(id(-b))); // Negative examples (shouldn't be changed) let c = &7; vec.sort_by(|a, b| (b - a).cmp(&(a - b))); vec.sort_by(|_, b| b.cmp(&5)); vec.sort_by(|_, b| b.cmp(c)); - vec.sort_by(|a, _| a.cmp(c)); + vec.sort_unstable_by(|a, _| a.cmp(c)); } diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index fdb5a823369..0485a5630af 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -10,16 +10,17 @@ fn main() { let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; // Forward examples vec.sort_by(|a, b| a.cmp(b)); + vec.sort_unstable_by(|a, b| a.cmp(b)); vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); - vec.sort_by(|a, b| id(-a).cmp(&id(-b))); + vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); // Reverse examples vec.sort_by(|a, b| b.cmp(a)); vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); - vec.sort_by(|a, b| id(-b).cmp(&id(-a))); + vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); // Negative examples (shouldn't be changed) let c = &7; vec.sort_by(|a, b| (b - a).cmp(&(a - b))); vec.sort_by(|_, b| b.cmp(&5)); vec.sort_by(|_, b| b.cmp(c)); - vec.sort_by(|a, _| a.cmp(c)); + vec.sort_unstable_by(|a, _| a.cmp(c)); } diff --git a/tests/ui/unnecessary_sort_by.stderr b/tests/ui/unnecessary_sort_by.stderr index b6365c1709d..903b6e5099c 100644 --- a/tests/ui/unnecessary_sort_by.stderr +++ b/tests/ui/unnecessary_sort_by.stderr @@ -6,35 +6,41 @@ LL | vec.sort_by(|a, b| a.cmp(b)); | = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` -error: use Vec::sort_by_key here instead +error: use Vec::sort here instead --> $DIR/unnecessary_sort_by.rs:13:5 | +LL | vec.sort_unstable_by(|a, b| a.cmp(b)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable()` + +error: use Vec::sort_by_key here instead + --> $DIR/unnecessary_sort_by.rs:14:5 + | LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&a| (a + 5).abs())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:14:5 + --> $DIR/unnecessary_sort_by.rs:15:5 | -LL | vec.sort_by(|a, b| id(-a).cmp(&id(-b))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&a| id(-a))` +LL | vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|&a| id(-a))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:16:5 + --> $DIR/unnecessary_sort_by.rs:17:5 | LL | vec.sort_by(|a, b| b.cmp(a)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(b))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:17:5 + --> $DIR/unnecessary_sort_by.rs:18:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse((b + 5).abs()))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:18:5 + --> $DIR/unnecessary_sort_by.rs:19:5 | -LL | vec.sort_by(|a, b| id(-b).cmp(&id(-a))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(id(-b)))` +LL | vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|&b| Reverse(id(-b)))` -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors From b89880a30ce4dd7887614f305a565b6779dc4825 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sun, 31 May 2020 15:19:31 -0700 Subject: [PATCH 156/526] Ran update_lints --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 6 +++--- src/lintlist/mod.rs | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c00f84bdb85..086a1141be5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1555,7 +1555,6 @@ Released 2018-09-13 [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next [`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization -[`sort_by_key_reverse`]: https://rust-lang.github.io/rust-clippy/master/index.html#sort_by_key_reverse [`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string [`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add [`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign @@ -1602,6 +1601,7 @@ Released 2018-09-13 [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation +[`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by [`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap [`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern [`unneeded_wildcard_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_wildcard_pattern diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index fd832d11577..03addf1f4a4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -780,7 +780,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &shadow::SHADOW_UNRELATED, &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, - &unnecessary_sort_by::UNNECESSARY_SORT_BY, &strings::STRING_ADD, &strings::STRING_ADD_ASSIGN, &strings::STRING_LIT_AS_BYTES, @@ -835,6 +834,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &unicode::ZERO_WIDTH_SPACE, &unnamed_address::FN_ADDRESS_COMPARISONS, &unnamed_address::VTABLE_ADDRESS_COMPARISONS, + &unnecessary_sort_by::UNNECESSARY_SORT_BY, &unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, &unused_io_amount::UNUSED_IO_AMOUNT, &unused_self::UNUSED_SELF, @@ -1394,7 +1394,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), - LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), @@ -1431,6 +1430,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&unicode::ZERO_WIDTH_SPACE), LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS), LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS), + LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), LintId::of(&unwrap::PANICKING_UNWRAP), @@ -1596,7 +1596,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ranges::RANGE_ZIP_WITH_LEN), LintId::of(&reference::DEREF_ADDROF), LintId::of(&reference::REF_IN_DEREF), - LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), LintId::of(&swap::MANUAL_SWAP), LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT), LintId::of(&transmute::CROSSPOINTER_TRANSMUTE), @@ -1613,6 +1612,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::UNIT_ARG), LintId::of(&types::UNNECESSARY_CAST), LintId::of(&types::VEC_BOX), + LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), LintId::of(&unwrap::UNNECESSARY_UNWRAP), LintId::of(&useless_conversion::USELESS_CONVERSION), LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index b5d9ef0110e..ab9542a7b9c 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1984,13 +1984,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "slow_vector_initialization", }, - Lint { - name: "sort_by_key_reverse", - group: "complexity", - desc: "Use of `Vec::sort_by` when `Vec::sort_by_key` would be clearer", - deprecation: None, - module: "sort_by_key_reverse", - }, Lint { name: "string_add", group: "restriction", @@ -2299,6 +2292,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "no_effect", }, + Lint { + name: "unnecessary_sort_by", + group: "complexity", + desc: "Use of `Vec::sort_by` when `Vec::sort_by_key` or `Vec::sort` would be clearer", + deprecation: None, + module: "unnecessary_sort_by", + }, Lint { name: "unnecessary_unwrap", group: "complexity", From 6955420ace822ec888cc999a623c67c51ced839f Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 1 Jun 2020 00:28:58 +0200 Subject: [PATCH 157/526] Update changelog for stable:1.44 beta:1.45 --- CHANGELOG.md | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7dae3dcfff..fcc9895dd90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,87 @@ document. ## Unreleased / In Rust Nightly -[891e1a8...master](https://github.com/rust-lang/rust-clippy/compare/891e1a8...master) +[7ea7cd1...master](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...master) + +## Rust 1.45 + +Current beta, release 2020-07-16 + +[891e1a8...7ea7cd1](https://github.com/rust-lang/rust-clippy/compare/891e1a8...7ea7cd1) + +### New lints + +* [`match_wildcard_for_single_variants`] [#5582](https://github.com/rust-lang/rust-clippy/pull/5582) +* [`unsafe_derive_deserialize`] [#5493](https://github.com/rust-lang/rust-clippy/pull/5493) +* [`if_let_mutex`] [#5332](https://github.com/rust-lang/rust-clippy/pull/5332) +* [`mismatched_target_os`] [#5506](https://github.com/rust-lang/rust-clippy/pull/5506) +* [`await_holding_lock`] [#5439](https://github.com/rust-lang/rust-clippy/pull/5439) +* [`match_on_vec_items`] [#5522](https://github.com/rust-lang/rust-clippy/pull/5522) +* [`manual_async_fn`] [#5576](https://github.com/rust-lang/rust-clippy/pull/5576) +* [`reversed_empty_ranges`] [#5583](https://github.com/rust-lang/rust-clippy/pull/5583) +* [`manual_non_exhaustive`] [#5550](https://github.com/rust-lang/rust-clippy/pull/5550) + +### Moves and Deprecations + +* Downgrade [`match_bool`] to pedantic [#5408](https://github.com/rust-lang/rust-clippy/pull/5408) +* Downgrade [`match_wild_err_arm`] to pedantic and update help messages. [#5622](https://github.com/rust-lang/rust-clippy/pull/5622) +* Downgrade [`useless_let_if_seq`] to nursery. [#5599](https://github.com/rust-lang/rust-clippy/pull/5599) +* Generalize [`option_and_then_some`] and rename to [`bind_instead_of_map`]. [#5529](https://github.com/rust-lang/rust-clippy/pull/5529) +* Rename [`identity_conversion`] to [`useless_conversion`]. [#5568](https://github.com/rust-lang/rust-clippy/pull/5568) +* Merge [`block_in_if_condition_expr`] and [`block_in_if_condition_stmt`] into [`blocks_in_if_conditions`]. +[#5563](https://github.com/rust-lang/rust-clippy/pull/5563) +* Merge [`option_map_unwrap_or`], [`option_map_unwrap_or_else`] and [`result_map_unwrap_or_else`] into [`map_unwrap_or`]. +[#5563](https://github.com/rust-lang/rust-clippy/pull/5563) +* Merge [`option_unwrap_used`] and [`result_unwrap_used`] into [`unwrap_used`]. +[#5563](https://github.com/rust-lang/rust-clippy/pull/5563) +* Merge [`option_expect_used`] and [`result_expect_used`] into [`expect_used`]. +[#5563](https://github.com/rust-lang/rust-clippy/pull/5563) +* Merge [`for_loop_over_option`] and [`for_loop_over_result`] into [`for_loops_over_fallibles`]. +[#5563](https://github.com/rust-lang/rust-clippy/pull/5563) + +### Enhancements + +* Avoid running cargo/internal lints when not enabled. [#5505](https://github.com/rust-lang/rust-clippy/pull/5505) +* Extend [`useless_conversion`] with `TryFrom` and `TryInto`. [#5631](https://github.com/rust-lang/rust-clippy/pull/5631) +* Lint also in type parameters and where clauses in [`unused_unit`]. [#5592](https://github.com/rust-lang/rust-clippy/pull/5592) +* Do not suggest deriving `Default` in [`new_without_default`]. [#5616](https://github.com/rust-lang/rust-clippy/pull/5616) + +### False Positive Fixes + +* [`while_let_on_iterator`] [#5525](https://github.com/rust-lang/rust-clippy/pull/5525) +* [`empty_line_after_outer_attr`] [#5609](https://github.com/rust-lang/rust-clippy/pull/5609) +* [`unnecessary_unwrap`] [#5558](https://github.com/rust-lang/rust-clippy/pull/5558) +* [`comparison_chain`] [#5596](https://github.com/rust-lang/rust-clippy/pull/5596) +* Don't trigger [`used_underscore_binding`] in await desugaring. [#5535](https://github.com/rust-lang/rust-clippy/pull/5535) +* Don't trigger [`borrowed_box`] on mutable references. [#5491](https://github.com/rust-lang/rust-clippy/pull/5491) +* Allow `1 << 0` in [`identity_op`]. [#5602](https://github.com/rust-lang/rust-clippy/pull/5602) +* Allow `use super::*;` glob imports in [`wildcard_imports`]. [#5564](https://github.com/rust-lang/rust-clippy/pull/5564) +* Add ignores to the list of words of [`clippy::doc_markdown`]. [#5611](https://github.com/rust-lang/rust-clippy/pull/5611) +* Skip dev and build deps in [`multiple_crate_versions`]. [#5636](https://github.com/rust-lang/rust-clippy/pull/5636) +* Honor `allow` attribute on arguments in [`ptr_arg`]. [#5647](https://github.com/rust-lang/rust-clippy/pull/5647) +* Honor lint level attributes for [`redundant_field_names`] and [`non_expressive_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/5651) +* Ignore calls to `len` in [`or_fun_call`]. [#4429](https://github.com/rust-lang/rust-clippy/pull/4429) + +### Suggestion Improvements + +* Simplify suggestions in [`manual_memcpy`]. [#5536](https://github.com/rust-lang/rust-clippy/pull/5536) +* Fix suggestion in [`redundant_pattern_matching`] for macros. [#5511](https://github.com/rust-lang/rust-clippy/pull/5511) +* Avoid suggesting `copied()` for mutable references in [`map_clone`]. [#5530](https://github.com/rust-lang/rust-clippy/pull/5530) +* Improve help message for [`clone_double_ref`]. [#5547](https://github.com/rust-lang/rust-clippy/pull/5547) + +### ICE Fixes + +* Fix ICE caused in unwrap module. [#5590](https://github.com/rust-lang/rust-clippy/pull/5590) +* Fix crash on rustc test issue-69020-assoc-const-arith-overflow.rs [#5499](https://github.com/rust-lang/rust-clippy/pull/5499) + +### Documentation + +* Clarify the documentation of [`unnecessary_mut_passed`]. [#5639](https://github.com/rust-lang/rust-clippy/pull/5639) +* Extend example for [`unneeded_field_pattern`]. [#5541](https://github.com/rust-lang/rust-clippy/pull/5541) ## Rust 1.44 -Current beta, release 2020-06-04 +Current stable, released 2020-06-04 [204bb9b...891e1a8](https://github.com/rust-lang/rust-clippy/compare/204bb9b...891e1a8) @@ -93,7 +169,7 @@ Current beta, release 2020-06-04 ## Rust 1.43 -Current stable, released 2020-04-23 +Released 2020-04-23 [4ee1206...204bb9b](https://github.com/rust-lang/rust-clippy/compare/4ee1206...204bb9b) From ae0ce2255aea7e896cbfc0330c9d4f17ed66b55f Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Mon, 1 Jun 2020 09:58:42 +0200 Subject: [PATCH 158/526] Add regression test for string_lit_as_bytes issue --- tests/ui/string_lit_as_bytes.fixed | 2 ++ tests/ui/string_lit_as_bytes.rs | 2 ++ tests/ui/string_lit_as_bytes.stderr | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/ui/string_lit_as_bytes.fixed b/tests/ui/string_lit_as_bytes.fixed index 7ad272ade5f..ccf8f61c4a9 100644 --- a/tests/ui/string_lit_as_bytes.fixed +++ b/tests/ui/string_lit_as_bytes.fixed @@ -14,6 +14,8 @@ fn str_lit_as_bytes() { let strify = stringify!(foobar).as_bytes(); + let current_version = env!("CARGO_PKG_VERSION").as_bytes(); + let includestr = include_bytes!("entry_unfixable.rs"); let _ = b"string with newline\t\n"; diff --git a/tests/ui/string_lit_as_bytes.rs b/tests/ui/string_lit_as_bytes.rs index 1bf4538b7c9..178df08e249 100644 --- a/tests/ui/string_lit_as_bytes.rs +++ b/tests/ui/string_lit_as_bytes.rs @@ -14,6 +14,8 @@ fn str_lit_as_bytes() { let strify = stringify!(foobar).as_bytes(); + let current_version = env!("CARGO_PKG_VERSION").as_bytes(); + let includestr = include_str!("entry_unfixable.rs").as_bytes(); let _ = "string with newline\t\n".as_bytes(); diff --git a/tests/ui/string_lit_as_bytes.stderr b/tests/ui/string_lit_as_bytes.stderr index ff6e3346dfc..99c512354d5 100644 --- a/tests/ui/string_lit_as_bytes.stderr +++ b/tests/ui/string_lit_as_bytes.stderr @@ -13,13 +13,13 @@ LL | let bs = r###"raw string with 3# plus " ""###.as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with 3# plus " ""###` error: calling `as_bytes()` on `include_str!(..)` - --> $DIR/string_lit_as_bytes.rs:17:22 + --> $DIR/string_lit_as_bytes.rs:19:22 | LL | let includestr = include_str!("entry_unfixable.rs").as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("entry_unfixable.rs")` error: calling `as_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:19:13 + --> $DIR/string_lit_as_bytes.rs:21:13 | LL | let _ = "string with newline/t/n".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"string with newline/t/n"` From 861b897c54200becd6767ad6e091abef61f15344 Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Mon, 1 Jun 2020 10:20:17 +0200 Subject: [PATCH 159/526] Add regression test for endless loop This was fixed in pulldown_cmark 0.7.1, specifically https://github.com/raphlinus/pulldown-cmark/pull/438 --- clippy_lints/Cargo.toml | 2 +- tests/ui/crashes/regressions.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 98391732d18..e959c1a6511 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -21,7 +21,7 @@ cargo_metadata = "0.9.1" if_chain = "1.0.0" itertools = "0.9" lazy_static = "1.0.2" -pulldown-cmark = { version = "0.7", default-features = false } +pulldown-cmark = { version = "0.7.1", default-features = false } quine-mc_cluskey = "0.2.2" regex-syntax = "0.6" serde = { version = "1.0", features = ["derive"] } diff --git a/tests/ui/crashes/regressions.rs b/tests/ui/crashes/regressions.rs index 623ae51f9f0..3d5063d1a3a 100644 --- a/tests/ui/crashes/regressions.rs +++ b/tests/ui/crashes/regressions.rs @@ -6,4 +6,8 @@ pub fn foo(bar: *const u8) { println!("{:#p}", bar); } +// Regression test for https://github.com/rust-lang/rust-clippy/issues/4917 +/// <foo +struct A {} + fn main() {} From 61587c9a294a423fb9eb9d57c5856c9e83e22d42 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Wed, 27 May 2020 16:24:53 +0200 Subject: [PATCH 160/526] Fix some code examples in doc --- clippy_lints/src/assign_ops.rs | 4 +++ clippy_lints/src/double_parens.rs | 18 +++++++++++-- clippy_lints/src/drop_bounds.rs | 4 +++ clippy_lints/src/duration_subsec.rs | 6 +++++ clippy_lints/src/enum_variants.rs | 32 +++++++++++++++++++---- clippy_lints/src/eq_op.rs | 4 +++ clippy_lints/src/escape.rs | 7 +++++ clippy_lints/src/eta_reduction.rs | 4 +++ clippy_lints/src/eval_order_dependence.rs | 6 +++++ 9 files changed, 78 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 05e2650d0b7..13e61fe98ba 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -24,7 +24,11 @@ declare_clippy_lint! { /// let mut a = 5; /// let b = 0; /// // ... + /// // Bad /// a = a + b; + /// + /// // Good + /// a += b; /// ``` pub ASSIGN_OP_PATTERN, style, diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 7f2ff8b9b26..05517f6f9f0 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -13,10 +13,24 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad + /// fn simple_double_parens() -> i32 { + /// ((0)) + /// } + /// + /// // Good + /// fn simple_no_parens() -> i32 { + /// 0 + /// } + /// + /// // or + /// /// # fn foo(bar: usize) {} - /// ((0)); + /// // Bad /// foo((0)); - /// ((1, 2)); + /// + /// // Good + /// foo(0); /// ``` pub DOUBLE_PARENS, complexity, diff --git a/clippy_lints/src/drop_bounds.rs b/clippy_lints/src/drop_bounds.rs index f4966808279..4ef963ac314 100644 --- a/clippy_lints/src/drop_bounds.rs +++ b/clippy_lints/src/drop_bounds.rs @@ -27,6 +27,10 @@ declare_clippy_lint! { /// ```rust /// fn foo<T: Drop>() {} /// ``` + /// Could be written as: + /// ```rust + /// fn foo() {} + /// ``` pub DROP_BOUNDS, correctness, "Bounds of the form `T: Drop` are useless" diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index b35a8facf8b..afefa250638 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -22,8 +22,14 @@ declare_clippy_lint! { /// ```rust /// # use std::time::Duration; /// let dur = Duration::new(5, 0); + /// + /// // Bad /// let _micros = dur.subsec_nanos() / 1_000; /// let _millis = dur.subsec_nanos() / 1_000_000; + /// + /// // Good + /// let _micros = dur.subsec_micros(); + /// let _millis = dur.subsec_millis(); /// ``` pub DURATION_SUBSEC, complexity, diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index a5871cf0cd4..cb0fd59a2d4 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -25,31 +25,47 @@ declare_clippy_lint! { /// BattenbergCake, /// } /// ``` + /// Could be written as: + /// ```rust + /// enum Cake { + /// BlackForest, + /// Hummingbird, + /// Battenberg, + /// } + /// ``` pub ENUM_VARIANT_NAMES, style, "enums where all variants share a prefix/postfix" } declare_clippy_lint! { - /// **What it does:** Detects enumeration variants that are prefixed or suffixed - /// by the same characters. + /// **What it does:** Detects public enumeration variants that are + /// prefixed or suffixed by the same characters. /// - /// **Why is this bad?** Enumeration variant names should specify their variant, + /// **Why is this bad?** Public enumeration variant names should specify their variant, /// not repeat the enumeration name. /// /// **Known problems:** None. /// /// **Example:** /// ```rust - /// enum Cake { + /// pub enum Cake { /// BlackForestCake, /// HummingbirdCake, /// BattenbergCake, /// } /// ``` + /// Could be written as: + /// ```rust + /// pub enum Cake { + /// BlackForest, + /// Hummingbird, + /// Battenberg, + /// } + /// ``` pub PUB_ENUM_VARIANT_NAMES, pedantic, - "enums where all variants share a prefix/postfix" + "public enums where all variants share a prefix/postfix" } declare_clippy_lint! { @@ -66,6 +82,12 @@ declare_clippy_lint! { /// struct BlackForestCake; /// } /// ``` + /// Could be written as: + /// ```rust + /// mod cake { + /// struct BlackForest; + /// } + /// ``` pub MODULE_NAME_REPETITIONS, pedantic, "type names prefixed/postfixed with their containing module's name" diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 4e1c1f13140..d7819d737ea 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -39,7 +39,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```ignore + /// // Bad /// &x == y + /// + /// // Good + /// x == *y /// ``` pub OP_REF, style, diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 1ec60a0e6e6..7227683aa5a 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -28,9 +28,16 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// # fn foo(bar: usize) {} + /// + /// // Bad /// let x = Box::new(1); /// foo(*x); /// println!("{}", *x); + /// + /// // Good + /// let x = 1; + /// foo(x); + /// println!("{}", x); /// ``` pub BOXED_LOCAL, perf, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index e3e1136b676..5f0cd1ec72c 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -26,7 +26,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust,ignore + /// // Bad /// xs.map(|x| foo(x)) + /// + /// // Good + /// foo(xs) /// ``` /// where `foo(_)` is a plain function that takes the exact argument type of /// `x`. diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 5206266ccf2..37e24ff34f7 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -21,11 +21,17 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let mut x = 0; + /// + /// // Bad /// let a = { /// x = 1; /// 1 /// } + x; /// // Unclear whether a is 1 or 2. + /// + /// // Good + /// x = 1; + /// let a = 1 + x; /// ``` pub EVAL_ORDER_DEPENDENCE, complexity, From 262c9dc025042646610df879dd9708eea625534d Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Fri, 29 May 2020 18:15:42 +0200 Subject: [PATCH 161/526] Fix more code examples --- clippy_lints/src/fallible_impl_from.rs | 15 +++++++++++++-- clippy_lints/src/floating_point_arithmetic.rs | 2 -- clippy_lints/src/format.rs | 6 +++++- clippy_lints/src/functions.rs | 14 ++++++++++---- clippy_lints/src/implicit_saturating_sub.rs | 7 ------- clippy_lints/src/int_plus_one.rs | 1 - clippy_lints/src/integer_division.rs | 11 +++++++---- clippy_lints/src/items_after_statements.rs | 16 ++++++++++++++++ 8 files changed, 51 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 17639cc2a06..575462f25e6 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -18,13 +18,24 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// struct Foo(i32); + /// + /// // Bad /// impl From<String> for Foo { /// fn from(s: String) -> Self { /// Foo(s.parse().unwrap()) /// } /// } + /// + /// // Good + /// use std::convert::TryFrom; + /// impl TryFrom<String> for Foo { + /// type Error = (); + /// fn try_from(s: String) -> Result<Self, Self::Error> { + /// s.parse() + /// } + /// } /// ``` pub FALLIBLE_IMPL_FROM, nursery, @@ -120,7 +131,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it move |diag| { diag.help( "`From` is intended for infallible conversions only. \ - Use `TryFrom` if there's a possibility for the conversion to fail."); + Use `TryFrom` if there's a possibility for the conversion to fail."); diag.span_note(fpu.result, "potential failure(s)"); }); } diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 86317fb8bd5..3a912d92837 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -28,7 +28,6 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust - /// /// let a = 3f32; /// let _ = a.powf(1.0 / 3.0); /// let _ = (1.0 + a).ln(); @@ -38,7 +37,6 @@ declare_clippy_lint! { /// is better expressed as /// /// ```rust - /// /// let a = 3f32; /// let _ = a.cbrt(); /// let _ = a.ln_1p(); diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 5b092526ce4..1530538aa7d 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -25,9 +25,13 @@ declare_clippy_lint! { /// /// **Examples:** /// ```rust + /// + /// // Bad /// # let foo = "foo"; - /// format!("foo"); /// format!("{}", foo); + /// + /// // Good + /// format!("foo"); /// ``` pub USELESS_FORMAT, complexity, diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index c24a24733d7..9b5f1dee7f4 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -49,11 +49,11 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ``` rust + /// ```rust /// fn im_too_long() { - /// println!(""); + /// println!(""); /// // ... 100 more LoC - /// println!(""); + /// println!(""); /// } /// ``` pub TOO_MANY_LINES, @@ -79,10 +79,16 @@ declare_clippy_lint! { /// `some_argument.get_raw_ptr()`). /// /// **Example:** - /// ```rust + /// ```rust,ignore + /// // Bad /// pub fn foo(x: *const u8) { /// println!("{}", unsafe { *x }); /// } + /// + /// // Good + /// pub unsafe fn foo(x: *const u8) { + /// println!("{}", unsafe { *x }); + /// } /// ``` pub NOT_UNSAFE_PTR_ARG_DEREF, correctness, diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 155a93de4fa..fdaf37e5e08 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -25,13 +25,6 @@ declare_clippy_lint! { /// if i != 0 { /// i -= 1; /// } - /// ``` - /// Use instead: - /// ```rust - /// let end: u32 = 10; - /// let start: u32 = 5; - /// - /// let mut i: u32 = end - start; /// /// // Good /// i = i.saturating_sub(1); diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index d5dbd495680..e91fb0c2f27 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -10,7 +10,6 @@ use crate::utils::{snippet_opt, span_lint_and_sugg}; declare_clippy_lint! { /// **What it does:** Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block /// - /// /// **Why is this bad?** Readability -- better to use `> y` instead of `>= y + 1`. /// /// **Known problems:** None. diff --git a/clippy_lints/src/integer_division.rs b/clippy_lints/src/integer_division.rs index fe34d33fe65..d537ef3f323 100644 --- a/clippy_lints/src/integer_division.rs +++ b/clippy_lints/src/integer_division.rs @@ -15,10 +15,13 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// fn main() { - /// let x = 3 / 2; - /// println!("{}", x); - /// } + /// // Bad + /// let x = 3 / 2; + /// println!("{}", x); + /// + /// // Good + /// let x = 3f32 / 2f32; + /// println!("{}", x); /// ``` pub INTEGER_DIVISION, restriction, diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index e7062b7c16b..c8576bcfcb4 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -16,6 +16,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad /// fn foo() { /// println!("cake"); /// } @@ -28,6 +29,21 @@ declare_clippy_lint! { /// foo(); // prints "foo" /// } /// ``` + /// + /// ```rust + /// // Good + /// fn foo() { + /// println!("cake"); + /// } + /// + /// fn main() { + /// fn foo() { + /// println!("foo"); + /// } + /// foo(); // prints "foo" + /// foo(); // prints "foo" + /// } + /// ``` pub ITEMS_AFTER_STATEMENTS, pedantic, "blocks where an item comes after a statement" From 19339334cb4e9c6db5a1f7dced38edcb16707bc7 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sun, 31 May 2020 11:38:48 +0200 Subject: [PATCH 162/526] Give more corrected code examples in doc --- clippy_lints/src/literal_representation.rs | 12 +++++ clippy_lints/src/matches.rs | 44 ++++++++++++++++--- clippy_lints/src/misc.rs | 31 ++++++++++++- clippy_lints/src/misc_early.rs | 34 +++++++++++--- clippy_lints/src/mut_reference.rs | 4 ++ clippy_lints/src/mutex_atomic.rs | 12 ++++- clippy_lints/src/needless_bool.rs | 3 +- clippy_lints/src/needless_borrow.rs | 8 +++- clippy_lints/src/needless_pass_by_value.rs | 3 +- clippy_lints/src/needless_update.rs | 10 +++++ clippy_lints/src/ptr.rs | 23 ++++++---- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/reference.rs | 5 +++ clippy_lints/src/regex.rs | 12 ++--- clippy_lints/src/shadow.rs | 10 +++++ .../src/single_component_path_imports.rs | 4 +- .../src/slow_vector_initialization.rs | 8 +++- clippy_lints/src/strings.rs | 8 ++++ 18 files changed, 195 insertions(+), 38 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index ec7c4531ed7..7ba43562d7d 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -24,7 +24,11 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust + /// // Bad /// let x: u64 = 61864918973511; + /// + /// // Good + /// let x: u64 = 61_864_918_973_511; /// ``` pub UNREADABLE_LITERAL, pedantic, @@ -44,7 +48,11 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust + /// // Probably mistyped /// 2_32; + /// + /// // Good + /// 2_i32; /// ``` pub MISTYPED_LITERAL_SUFFIXES, correctness, @@ -63,7 +71,11 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust + /// // Bad /// let x: u64 = 618_64_9189_73_511; + /// + /// // Good + /// let x: u64 = 61_864_918_973_511; /// ``` pub INCONSISTENT_DIGIT_GROUPING, style, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 94380acfcfd..146212cb2c7 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -36,10 +36,17 @@ declare_clippy_lint! { /// ```rust /// # fn bar(stool: &str) {} /// # let x = Some("abc"); + /// + /// // Bad /// match x { /// Some(ref foo) => bar(foo), /// _ => (), /// } + /// + /// // Good + /// if let Some(ref foo) = x { + /// bar(foo); + /// } /// ``` pub SINGLE_MATCH, style, @@ -97,11 +104,19 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust,ignore + /// // Bad /// match x { /// &A(ref y) => foo(y), /// &B => bar(), /// _ => frob(&x), /// } + /// + /// // Good + /// match *x { + /// A(ref y) => foo(y), + /// B => bar(), + /// _ => frob(x), + /// } /// ``` pub MATCH_REF_PATS, style, @@ -197,10 +212,15 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let x: Option<()> = None; + /// + /// // Bad /// let r: Option<&()> = match x { /// None => None, /// Some(ref v) => Some(v), /// }; + /// + /// // Good + /// let r: Option<&()> = x.as_ref(); /// ``` pub MATCH_AS_REF, complexity, @@ -219,10 +239,18 @@ declare_clippy_lint! { /// ```rust /// # enum Foo { A(usize), B(usize) } /// # let x = Foo::B(1); + /// + /// // Bad /// match x { /// Foo::A(_) => {}, /// _ => {}, /// } + /// + /// // Good + /// match x { + /// Foo::A(_) => {}, + /// Foo::B(_) => {}, + /// } /// ``` pub WILDCARD_ENUM_MATCH_ARM, restriction, @@ -242,16 +270,15 @@ declare_clippy_lint! { /// ```rust /// # enum Foo { A, B, C } /// # let x = Foo::B; + /// + /// // Bad /// match x { /// Foo::A => {}, /// Foo::B => {}, /// _ => {}, /// } - /// ``` - /// Use instead: - /// ```rust - /// # enum Foo { A, B, C } - /// # let x = Foo::B; + /// + /// // Good /// match x { /// Foo::A => {}, /// Foo::B => {}, @@ -273,10 +300,17 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad /// match "foo" { /// "a" => {}, /// "bar" | _ => {}, /// } + /// + /// // Good + /// match "foo" { + /// "a" => {}, + /// _ => {}, + /// } /// ``` pub WILDCARD_IN_OR_PATTERNS, complexity, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index e1d524c2231..a3b7134a376 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -38,10 +38,16 @@ declare_clippy_lint! { /// dereferences, e.g., changing `*x` to `x` within the function. /// /// **Example:** - /// ```rust + /// ```rust,ignore + /// // Bad /// fn foo(ref x: u8) -> bool { /// true /// } + /// + /// // Good + /// fn foo(x: &u8) -> bool { + /// true + /// } /// ``` pub TOPLEVEL_REF_ARG, style, @@ -60,7 +66,11 @@ declare_clippy_lint! { /// ```rust /// # let x = 1.0; /// + /// // Bad /// if x == f32::NAN { } + /// + /// // Good + /// if x.is_nan() { } /// ``` pub CMP_NAN, correctness, @@ -83,8 +93,15 @@ declare_clippy_lint! { /// ```rust /// let x = 1.2331f64; /// let y = 1.2332f64; + /// + /// // Bad /// if y == 1.23f64 { } /// if y != x {} // where both are floats + /// + /// // Good + /// let error = 0.01f64; // Use an epsilon for comparison + /// if (y - 1.23f64).abs() < error { } + /// if (y - x).abs() > error { } /// ``` pub FLOAT_CMP, correctness, @@ -191,7 +208,11 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust + /// // Bad /// let a = 0 as *const u32; + /// + /// // Good + /// let a = std::ptr::null::<u32>(); /// ``` pub ZERO_PTR, style, @@ -214,7 +235,13 @@ declare_clippy_lint! { /// ```rust /// let x: f64 = 1.0; /// const ONE: f64 = 1.00; - /// x == ONE; // where both are floats + /// + /// // Bad + /// if x == ONE { } // where both are floats + /// + /// // Good + /// let error = 0.1f64; // Use an epsilon for comparison + /// if (x - ONE).abs() < error { } /// ``` pub FLOAT_CMP_CONST, restriction, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 552222eba2e..ad39e59d067 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -59,7 +59,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad /// fn foo(a: i32, _a: i32) {} + /// + /// // Good + /// fn bar(a: i32, _b: i32) {} /// ``` pub DUPLICATE_UNDERSCORE_ARGUMENT, style, @@ -77,7 +81,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust,ignore - /// (|| 42)() + /// // Bad + /// let a = (|| 42)() + /// + /// // Good + /// let a = 42 /// ``` pub REDUNDANT_CLOSURE_CALL, complexity, @@ -112,7 +120,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad /// let y = 0x1a9BAcD; + /// + /// // Good + /// let y = 0x1A9BACD; /// ``` pub MIXED_CASE_HEX_LITERALS, style, @@ -129,7 +141,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad /// let y = 123832i32; + /// + /// // Good + /// let y = 123832_i32; /// ``` pub UNSEPARATED_LITERAL_SUFFIX, pedantic, @@ -207,9 +223,16 @@ declare_clippy_lint! { /// ```rust /// # let v = Some("abc"); /// + /// // Bad /// match v { /// Some(x) => (), - /// y @ _ => (), // easier written as `y`, + /// y @ _ => (), + /// } + /// + /// // Good + /// match v { + /// Some(x) => (), + /// y => (), /// } /// ``` pub REDUNDANT_PATTERN, @@ -235,16 +258,13 @@ declare_clippy_lint! { /// # struct TupleStruct(u32, u32, u32); /// # let t = TupleStruct(1, 2, 3); /// + /// // Bad /// match t { /// TupleStruct(0, .., _) => (), /// _ => (), /// } - /// ``` - /// can be written as - /// ```rust - /// # struct TupleStruct(u32, u32, u32); - /// # let t = TupleStruct(1, 2, 3); /// + /// // Good /// match t { /// TupleStruct(0, ..) => (), /// _ => (), diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 67a1ac78a67..58a8e1a1064 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -16,7 +16,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```ignore + /// // Bad /// my_vec.push(&mut value) + /// + /// // Good + /// my_vec.push(&value) /// ``` pub UNNECESSARY_MUT_PASSED, style, diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 4e1a8be4892..78b15afc5a7 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -22,9 +22,15 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # let y = true; + /// + /// // Bad /// # use std::sync::Mutex; - /// # let y = 1; /// let x = Mutex::new(&y); + /// + /// // Good + /// # use std::sync::atomic::AtomicBool; + /// let x = AtomicBool::new(y); /// ``` pub MUTEX_ATOMIC, perf, @@ -46,6 +52,10 @@ declare_clippy_lint! { /// ```rust /// # use std::sync::Mutex; /// let x = Mutex::new(0usize); + /// + /// // Good + /// # use std::sync::atomic::AtomicUsize; + /// let x = AtomicUsize::new(0usize); /// ``` pub MUTEX_INTEGER, nursery, diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index efa77db822d..15b129fa098 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -15,8 +15,7 @@ use rustc_span::Span; declare_clippy_lint! { /// **What it does:** Checks for expressions of the form `if c { true } else { - /// false }` - /// (or vice versa) and suggest using the condition directly. + /// false }` (or vice versa) and suggests using the condition directly. /// /// **Why is this bad?** Redundant code. /// diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 9ee875d7516..5880d1d6102 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -18,12 +18,16 @@ declare_clippy_lint! { /// **Why is this bad?** Suggests that the receiver of the expression borrows /// the expression. /// + /// **Known problems:** None. + /// /// **Example:** /// ```rust + /// // Bad /// let x: &i32 = &&&&&&5; - /// ``` /// - /// **Known problems:** None. + /// // Good + /// let x: &i32 = &5; + /// ``` pub NEEDLESS_BORROW, nursery, "taking a reference that is going to be automatically dereferenced" diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 9c508fc0e4a..fbdf927b824 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -40,9 +40,8 @@ declare_clippy_lint! { /// assert_eq!(v.len(), 42); /// } /// ``` - /// + /// should be /// ```rust - /// // should be /// fn foo(v: &[i32]) { /// assert_eq!(v.len(), 42); /// } diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 4b2586877e5..d866bab2f64 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -21,6 +21,16 @@ declare_clippy_lint! { /// # z: i32, /// # } /// # let zero_point = Point { x: 0, y: 0, z: 0 }; + /// + /// // Bad + /// Point { + /// x: 1, + /// y: 1, + /// z: 1, + /// ..zero_point + /// }; + /// + /// // Ok /// Point { /// x: 1, /// y: 1, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 4eac571f966..c77b44e0c99 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -47,7 +47,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```ignore + /// // Bad /// fn foo(&Vec<u32>) { .. } + /// + /// // Good + /// fn foo(&[u32]) { .. } /// ``` pub PTR_ARG, style, @@ -65,9 +69,15 @@ declare_clippy_lint! { /// /// **Example:** /// ```ignore + /// // Bad /// if x == ptr::null { /// .. /// } + /// + /// // Good + /// if x.is_null() { + /// .. + /// } /// ``` pub CMP_NULL, style, @@ -76,19 +86,16 @@ declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** This lint checks for functions that take immutable - /// references and return - /// mutable ones. + /// references and return mutable ones. /// /// **Why is this bad?** This is trivially unsound, as one can create two - /// mutable references - /// from the same (immutable!) source. This - /// [error](https://github.com/rust-lang/rust/issues/39465) + /// mutable references from the same (immutable!) source. + /// This [error](https://github.com/rust-lang/rust/issues/39465) /// actually lead to an interim Rust release 1.15.1. /// /// **Known problems:** To be on the conservative side, if there's at least one - /// mutable reference - /// with the output lifetime, this lint will not trigger. In practice, this - /// case is unlikely anyway. + /// mutable reference with the output lifetime, this lint will not trigger. + /// In practice, this case is unlikely anyway. /// /// **Example:** /// ```ignore diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index ea654467b86..e4361b00fb4 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -88,7 +88,7 @@ impl QuestionMark { replacement_str, applicability, ) - } + } } } } diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index d5797468e9d..fe457aad50e 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -16,8 +16,13 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust,ignore + /// // Bad /// let a = f(*&mut b); /// let c = *&d; + /// + /// // Good + /// let a = f(b); + /// let c = d; /// ``` pub DEREF_ADDROF, complexity, diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 30084e3e1ff..a2c35c42673 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -86,11 +86,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Regex { if let Some(span) = is_expn_of(expr.span, "regex"); then { if !self.spans.contains(&span) { - span_lint(cx, - REGEX_MACRO, - span, - "`regex!(_)` found. \ - Please use `Regex::new(_)`, which is faster for now."); + span_lint( + cx, + REGEX_MACRO, + span, + "`regex!(_)` found. \ + Please use `Regex::new(_)`, which is faster for now." + ); self.spans.insert(span); } self.last = Some(block.hir_id); diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 11360b0ef84..68c36f91891 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -25,7 +25,12 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// # let x = 1; + /// + /// // Bad /// let x = &x; + /// + /// // Good + /// let y = &x; // use different variable name /// ``` pub SHADOW_SAME, restriction, @@ -77,7 +82,12 @@ declare_clippy_lint! { /// # let y = 1; /// # let z = 2; /// let x = y; + /// + /// // Bad /// let x = z; // shadows the earlier binding + /// + /// // Good + /// let w = z; // use different variable name /// ``` pub SHADOW_UNRELATED, pedantic, diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs index 8d767a7fec8..2e853e8301d 100644 --- a/clippy_lints/src/single_component_path_imports.rs +++ b/clippy_lints/src/single_component_path_imports.rs @@ -16,7 +16,7 @@ declare_clippy_lint! { /// /// **Example:** /// - /// ```rust, ignore + /// ```rust,ignore /// use regex; /// /// fn main() { @@ -24,7 +24,7 @@ declare_clippy_lint! { /// } /// ``` /// Better as - /// ```rust, ignore + /// ```rust,ignore /// fn main() { /// regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap(); /// } diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index fb3706be1c2..a7c4f2c2291 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -22,11 +22,17 @@ declare_clippy_lint! { /// ```rust /// # use core::iter::repeat; /// # let len = 4; + /// + /// // Bad /// let mut vec1 = Vec::with_capacity(len); /// vec1.resize(len, 0); /// /// let mut vec2 = Vec::with_capacity(len); - /// vec2.extend(repeat(0).take(len)) + /// vec2.extend(repeat(0).take(len)); + /// + /// // Good + /// let mut vec1 = vec![0; len]; + /// let mut vec2 = vec![0; len]; /// ``` pub SLOW_VECTOR_INITIALIZATION, perf, diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 2c51271e312..f84566ef707 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -24,6 +24,10 @@ declare_clippy_lint! { /// ```rust /// let mut x = "Hello".to_owned(); /// x = x + ", World"; + /// + /// // More readable + /// x += ", World"; + /// x.push_str(", World"); /// ``` pub STRING_ADD_ASSIGN, pedantic, @@ -69,7 +73,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad /// let bs = "a byte string".as_bytes(); + /// + /// // Good + /// let bs = b"a byte string"; /// ``` pub STRING_LIT_AS_BYTES, style, From 9893254dff38c2644612c8465ae9abfa553f4ea3 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sun, 31 May 2020 12:08:41 +0200 Subject: [PATCH 163/526] Add more corrected code for doc --- clippy_lints/src/methods/mod.rs | 65 ++++++++++++++++++++------ clippy_lints/src/misc.rs | 2 +- clippy_lints/src/vec.rs | 10 +++- clippy_lints/src/verbose_file_reads.rs | 1 + clippy_lints/src/wildcard_imports.rs | 12 +++-- clippy_lints/src/write.rs | 22 ++++++++- clippy_lints/src/zero_div_zero.rs | 6 ++- src/lintlist/mod.rs | 2 +- 8 files changed, 95 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 52ca962e7ef..fbc29efdeb2 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -218,7 +218,12 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// # let x = Ok::<_, ()>(()); - /// x.ok().expect("why did I do this again?") + /// + /// // Bad + /// x.ok().expect("why did I do this again?"); + /// + /// // Good + /// x.expect("why did I do this again?"); /// ``` pub OK_EXPECT, style, @@ -273,8 +278,12 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// # let opt = Some(1); - /// opt.map_or(None, |a| Some(a + 1)) - /// # ; + /// + /// // Bad + /// opt.map_or(None, |a| Some(a + 1)); + /// + /// // Good + /// opt.and_then(|a| Some(a + 1)); /// ``` pub OPTION_MAP_OR_NONE, style, @@ -390,14 +399,19 @@ declare_clippy_lint! { /// **What it does:** Checks for usage of `_.map(_).flatten(_)`, /// /// **Why is this bad?** Readability, this can be written more concisely as a - /// single method call. + /// single method call using `_.flat_map(_)` /// /// **Known problems:** /// /// **Example:** /// ```rust /// let vec = vec![vec![1]]; + /// + /// // Bad /// vec.iter().map(|x| x.iter()).flatten(); + /// + /// // Good + /// vec.iter().flat_map(|x| x.iter()); /// ``` pub MAP_FLATTEN, pedantic, @@ -417,7 +431,12 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let vec = vec![1]; + /// + /// // Bad /// vec.iter().filter(|x| **x == 0).map(|x| *x * 2); + /// + /// // Good + /// vec.iter().filter_map(|x| Some(*x * 2)); /// ``` pub FILTER_MAP, pedantic, @@ -634,7 +653,12 @@ declare_clippy_lint! { /// ```rust /// # use std::rc::Rc; /// let x = Rc::new(1); + /// + /// // Bad /// x.clone(); + /// + /// // Good + /// Rc::clone(&x); /// ``` pub CLONE_ON_REF_PTR, restriction, @@ -741,7 +765,12 @@ declare_clippy_lint! { /// **Known problems:** Does not catch multi-byte unicode characters. /// /// **Example:** - /// `_.split("x")` could be `_.split('x')` + /// ```rust,ignore + /// // Bad + /// _.split("x"); + /// + /// // Good + /// _.split('x'); pub SINGLE_CHAR_PATTERN, perf, "using a single-character str where a char could be used, e.g., `_.split(\"x\")`" @@ -964,8 +993,8 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Checks for usage of `.chars().last()` or - /// `.chars().next_back()` on a `str` to check if it ends with a given char. + /// **What it does:** Checks for usage of `_.chars().last()` or + /// `_.chars().next_back()` on a `str` to check if it ends with a given char. /// /// **Why is this bad?** Readability, this can be written more concisely as /// `_.ends_with(_)`. @@ -975,8 +1004,12 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// # let name = "_"; - /// name.chars().last() == Some('_') || name.chars().next_back() == Some('-') - /// # ; + /// + /// // Bad + /// name.chars().last() == Some('_') || name.chars().next_back() == Some('-'); + /// + /// // Good + /// name.ends_with('_') || name.ends_with('-'); /// ``` pub CHARS_LAST_CMP, style, @@ -1044,17 +1077,15 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let _ = (0..3).filter_map(|x| if x > 2 { Some(x) } else { None }); - /// ``` - /// As there is no transformation of the argument this could be written as: - /// ```rust + /// + /// // As there is no transformation of the argument this could be written as: /// let _ = (0..3).filter(|&x| x > 2); /// ``` /// /// ```rust /// let _ = (0..4).filter_map(|x| Some(x + 1)); - /// ``` - /// As there is no conditional check on the argument this could be written as: - /// ```rust + /// + /// // As there is no conditional check on the argument this could be written as: /// let _ = (0..4).map(|x| x + 1); /// ``` pub UNNECESSARY_FILTER_MAP, @@ -1075,7 +1106,11 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust + /// // Bad /// let _ = (&vec![3, 4, 5]).into_iter(); + /// + /// // Good + /// let _ = (&vec![3, 4, 5]).iter(); /// ``` pub INTO_ITER_ON_REF, style, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index a3b7134a376..51282ab93ef 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -93,7 +93,7 @@ declare_clippy_lint! { /// ```rust /// let x = 1.2331f64; /// let y = 1.2332f64; - /// + /// /// // Bad /// if y == 1.23f64 { } /// if y != x {} // where both are floats diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 1174f421577..a8d4c7620b1 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -17,8 +17,14 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust,ignore - /// foo(&vec![1, 2]) + /// ```rust + /// # fn foo(my_vec: &[u8]) {} + /// + /// // Bad + /// foo(&vec![1, 2]); + /// + /// // Good + /// foo(&[1, 2]); /// ``` pub USELESS_VEC, perf, diff --git a/clippy_lints/src/verbose_file_reads.rs b/clippy_lints/src/verbose_file_reads.rs index 4d8d4438d88..7247518e19b 100644 --- a/clippy_lints/src/verbose_file_reads.rs +++ b/clippy_lints/src/verbose_file_reads.rs @@ -9,6 +9,7 @@ declare_clippy_lint! { /// /// **Why is this bad?** `fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values. /// See also: [fs::read docs](https://doc.rust-lang.org/std/fs/fn.read.html), [fs::read_to_string docs](https://doc.rust-lang.org/std/fs/fn.read_to_string.html) + /// /// **Known problems:** None. /// /// **Example:** diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 32d9a45c37d..b637253bd02 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -19,8 +19,14 @@ declare_clippy_lint! { /// still around. /// /// **Example:** - /// ```rust + /// ```rust,ignore + /// // Bad /// use std::cmp::Ordering::*; + /// foo(Less); + /// + /// // Good + /// use std::cmp::Ordering; + /// foo(Ordering::Less) /// ``` pub ENUM_GLOB_USE, pedantic, @@ -60,15 +66,15 @@ declare_clippy_lint! { /// /// **Example:** /// - /// Bad: /// ```rust,ignore + /// // Bad /// use crate1::*; /// /// foo(); /// ``` /// - /// Good: /// ```rust,ignore + /// // Good /// use crate1::foo; /// /// foo(); diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 5f794598052..22ce484b24e 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -23,7 +23,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad /// println!(""); + /// + /// // Good + /// println!(); /// ``` pub PRINTLN_EMPTY_STRING, style, @@ -32,8 +36,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** This lint warns when you use `print!()` with a format - /// string that - /// ends in a newline. + /// string that ends in a newline. /// /// **Why is this bad?** You should use `println!()` instead, which appends the /// newline. @@ -125,7 +128,12 @@ declare_clippy_lint! { /// ```rust /// # use std::fmt::Write; /// # let mut buf = String::new(); + /// + /// // Bad /// writeln!(buf, ""); + /// + /// // Good + /// writeln!(buf); /// ``` pub WRITELN_EMPTY_STRING, style, @@ -147,7 +155,12 @@ declare_clippy_lint! { /// # use std::fmt::Write; /// # let mut buf = String::new(); /// # let name = "World"; + /// + /// // Bad /// write!(buf, "Hello {}!\n", name); + /// + /// // Good + /// writeln!(buf, "Hello {}!", name); /// ``` pub WRITE_WITH_NEWLINE, style, @@ -168,7 +181,12 @@ declare_clippy_lint! { /// ```rust /// # use std::fmt::Write; /// # let mut buf = String::new(); + /// + /// // Bad /// writeln!(buf, "{}", "foo"); + /// + /// // Good + /// writeln!(buf, "foo"); /// ``` pub WRITE_LITERAL, style, diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index fb4700d8743..0820385e01b 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -14,7 +14,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// 0.0f32 / 0.0; + /// // Bad + /// let nan = 0.0f32 / 0.0; + /// + /// // Good + /// let nan = f32::NAN; /// ``` pub ZERO_DIVIDED_BY_ZERO, complexity, diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index ab9542a7b9c..6b6e2c7324c 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1735,7 +1735,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ Lint { name: "pub_enum_variant_names", group: "pedantic", - desc: "enums where all variants share a prefix/postfix", + desc: "public enums where all variants share a prefix/postfix", deprecation: None, module: "enum_variants", }, From 137a3b4d3242cfe331f8f9b87c51ac0c431fe160 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Mon, 1 Jun 2020 10:16:01 +0200 Subject: [PATCH 164/526] Corrected doc PR fixes --- clippy_lints/src/drop_bounds.rs | 2 +- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 7 +++++-- clippy_lints/src/fallible_impl_from.rs | 12 ++++++++++-- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/methods/mod.rs | 6 +++++- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/drop_bounds.rs b/clippy_lints/src/drop_bounds.rs index 4ef963ac314..5a7f759486e 100644 --- a/clippy_lints/src/drop_bounds.rs +++ b/clippy_lints/src/drop_bounds.rs @@ -29,7 +29,7 @@ declare_clippy_lint! { /// ``` /// Could be written as: /// ```rust - /// fn foo() {} + /// fn foo<T>() {} /// ``` pub DROP_BOUNDS, correctness, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 5f0cd1ec72c..d093025fd3d 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -30,7 +30,7 @@ declare_clippy_lint! { /// xs.map(|x| foo(x)) /// /// // Good - /// foo(xs) + /// xs.map(foo) /// ``` /// where `foo(_)` is a plain function that takes the exact argument type of /// `x`. diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 37e24ff34f7..74144fb299d 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -30,8 +30,11 @@ declare_clippy_lint! { /// // Unclear whether a is 1 or 2. /// /// // Good - /// x = 1; - /// let a = 1 + x; + /// let tmp = { + /// x = 1; + /// 1 + /// }; + /// let a = tmp + x; /// ``` pub EVAL_ORDER_DEPENDENCE, complexity, diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 575462f25e6..92812816461 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -18,7 +18,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust,ignore + /// ```rust /// struct Foo(i32); /// /// // Bad @@ -27,13 +27,21 @@ declare_clippy_lint! { /// Foo(s.parse().unwrap()) /// } /// } + /// ``` /// + /// ```rust /// // Good + /// struct Foo(i32); + /// /// use std::convert::TryFrom; /// impl TryFrom<String> for Foo { /// type Error = (); /// fn try_from(s: String) -> Result<Self, Self::Error> { - /// s.parse() + /// if let Ok(parsed) = s.parse() { + /// Ok(Foo(parsed)) + /// } else { + /// Err(()) + /// } /// } /// } /// ``` diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 9b5f1dee7f4..325b6cf32a3 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -52,7 +52,7 @@ declare_clippy_lint! { /// ```rust /// fn im_too_long() { /// println!(""); - /// // ... 100 more LoC + /// // ... 100 more LoC /// println!(""); /// } /// ``` diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index fbc29efdeb2..a8d5c10d5da 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -436,7 +436,11 @@ declare_clippy_lint! { /// vec.iter().filter(|x| **x == 0).map(|x| *x * 2); /// /// // Good - /// vec.iter().filter_map(|x| Some(*x * 2)); + /// vec.iter().filter_map(|x| if *x == 0 { + /// Some(*x * 2) + /// } else { + /// None + /// }); /// ``` pub FILTER_MAP, pedantic, From 9e89ba93fda29b4dc707cd14bd518b73e676d895 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sun, 31 May 2020 15:09:58 +0200 Subject: [PATCH 165/526] Add doc for checking if type defines certain method --- doc/common_tools_writing_lints.md | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/doc/common_tools_writing_lints.md b/doc/common_tools_writing_lints.md index ed33b37c6bd..dbc43450594 100644 --- a/doc/common_tools_writing_lints.md +++ b/doc/common_tools_writing_lints.md @@ -4,7 +4,9 @@ You may need following tooltips to catch up with common operations. - [Common tools for writing lints](#common-tools-for-writing-lints) - [Retrieving the type of an expression](#retrieving-the-type-of-an-expression) + - [Checking if an expression is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method) - [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait) + - [Checking if a type defines a method](#checking-if-a-type-defines-a-method) - [Dealing with macros](#dealing-with-macros) Useful Rustc dev guide links: @@ -49,6 +51,26 @@ Two noticeable items here: - `tables` is [`TypeckTables`][TypeckTables] and is created by type checking step, it includes useful information such as types of expressions, ways to resolve methods and so on. +# Checking if an expr is calling a specific method + +Starting with an `expr`, you can check whether it is calling a specific method `some_method`: + +```rust +impl LateLintPass<'_, '_> for MyStructLint { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { + if_chain! { + // Check our expr is calling a method + if let hir::ExprKind::MethodCall(path, _, _args) = &expr.kind; + // Check the name of this method is `some_method` + if path.ident.name == sym!(some_method); + then { + // ... + } + } + } +} +``` + # Checking if a type implements a specific trait There are two ways to do this, depending if the target trait is part of lang items. @@ -83,6 +105,32 @@ A list of defined paths for Clippy can be found in [paths.rs][paths] We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate. +# Checking if a type defines a specific method + +To check if our type defines a method called `some_method`: + +```rust +use crate::utils::{is_type_diagnostic_item, return_ty}; + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MyTypeImpl { + fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx ImplItem<'_>) { + if_chain! { + // Check if item is a method/function + if let ImplItemKind::Fn(ref signature, _) = impl_item.kind; + // Check the method is named `some_method` + if impl_item.ident.name == sym!(some_method); + // We can also check it has a parameter `self` + if signature.decl.implicit_self.has_implicit_self(); + // We can go further and even check if its return type is `String` + if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(string_type)); + then { + // ... + } + } + } +} +``` + # Dealing with macros There are several helpers in Clippy's utils to deal with macros: From a44fa387efff44414c7baac249dcd148b93e2eb1 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 1 Jun 2020 09:26:40 +0200 Subject: [PATCH 166/526] Update documentation on changelog updates --- CHANGELOG.md | 19 ++++++++++--------- doc/changelog_update.md | 9 +++++---- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcc9895dd90..dd0905e9f39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,17 +31,17 @@ Current beta, release 2020-07-16 * Downgrade [`match_bool`] to pedantic [#5408](https://github.com/rust-lang/rust-clippy/pull/5408) * Downgrade [`match_wild_err_arm`] to pedantic and update help messages. [#5622](https://github.com/rust-lang/rust-clippy/pull/5622) * Downgrade [`useless_let_if_seq`] to nursery. [#5599](https://github.com/rust-lang/rust-clippy/pull/5599) -* Generalize [`option_and_then_some`] and rename to [`bind_instead_of_map`]. [#5529](https://github.com/rust-lang/rust-clippy/pull/5529) -* Rename [`identity_conversion`] to [`useless_conversion`]. [#5568](https://github.com/rust-lang/rust-clippy/pull/5568) -* Merge [`block_in_if_condition_expr`] and [`block_in_if_condition_stmt`] into [`blocks_in_if_conditions`]. +* Generalize `option_and_then_some` and rename to [`bind_instead_of_map`]. [#5529](https://github.com/rust-lang/rust-clippy/pull/5529) +* Rename `identity_conversion` to [`useless_conversion`]. [#5568](https://github.com/rust-lang/rust-clippy/pull/5568) +* Merge `block_in_if_condition_expr` and `block_in_if_condition_stmt` into [`blocks_in_if_conditions`]. [#5563](https://github.com/rust-lang/rust-clippy/pull/5563) -* Merge [`option_map_unwrap_or`], [`option_map_unwrap_or_else`] and [`result_map_unwrap_or_else`] into [`map_unwrap_or`]. +* Merge `option_map_unwrap_or`, `option_map_unwrap_or_else` and `result_map_unwrap_or_else` into [`map_unwrap_or`]. [#5563](https://github.com/rust-lang/rust-clippy/pull/5563) -* Merge [`option_unwrap_used`] and [`result_unwrap_used`] into [`unwrap_used`]. +* Merge `option_unwrap_used` and `result_unwrap_used` into [`unwrap_used`]. [#5563](https://github.com/rust-lang/rust-clippy/pull/5563) -* Merge [`option_expect_used`] and [`result_expect_used`] into [`expect_used`]. +* Merge `option_expect_used` and `result_expect_used` into [`expect_used`]. [#5563](https://github.com/rust-lang/rust-clippy/pull/5563) -* Merge [`for_loop_over_option`] and [`for_loop_over_result`] into [`for_loops_over_fallibles`]. +* Merge `for_loop_over_option` and `for_loop_over_result` into [`for_loops_over_fallibles`]. [#5563](https://github.com/rust-lang/rust-clippy/pull/5563) ### Enhancements @@ -61,10 +61,11 @@ Current beta, release 2020-07-16 * Don't trigger [`borrowed_box`] on mutable references. [#5491](https://github.com/rust-lang/rust-clippy/pull/5491) * Allow `1 << 0` in [`identity_op`]. [#5602](https://github.com/rust-lang/rust-clippy/pull/5602) * Allow `use super::*;` glob imports in [`wildcard_imports`]. [#5564](https://github.com/rust-lang/rust-clippy/pull/5564) -* Add ignores to the list of words of [`clippy::doc_markdown`]. [#5611](https://github.com/rust-lang/rust-clippy/pull/5611) +* Add ignores to the list of words of [`doc_markdown`]. [#5611](https://github.com/rust-lang/rust-clippy/pull/5611) * Skip dev and build deps in [`multiple_crate_versions`]. [#5636](https://github.com/rust-lang/rust-clippy/pull/5636) * Honor `allow` attribute on arguments in [`ptr_arg`]. [#5647](https://github.com/rust-lang/rust-clippy/pull/5647) -* Honor lint level attributes for [`redundant_field_names`] and [`non_expressive_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/5651) +* Honor lint level attributes for [`redundant_field_names`], [`just_underscores_and_digits`], [`many_single_char_names`] +and [`similar_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/5651) * Ignore calls to `len` in [`or_fun_call`]. [#4429](https://github.com/rust-lang/rust-clippy/pull/4429) ### Suggestion Improvements diff --git a/doc/changelog_update.md b/doc/changelog_update.md index 0b80cce6d23..edba3b4741c 100644 --- a/doc/changelog_update.md +++ b/doc/changelog_update.md @@ -32,8 +32,9 @@ bullet points might be helpful: need to select the Rust release tag from the dropdown and then check the commit of the Clippy directory: -  - +To find the commit hash, click on "History" of the relevant branch in github +and search for the latest "Merge commit '<hash>' into <branch>" commit. +The <hash> part is then the most recent commit in the clippy repo. ### 2. Fetching the PRs between those commits @@ -74,5 +75,5 @@ relevant commit ranges. [changelog]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md [forge]: https://forge.rust-lang.org/ -[rust_master_tools]: https://github.com/rust-lang/rust/tree/master/src/tools -[rust_beta_tools]: https://github.com/rust-lang/rust/tree/beta/src/tools +[rust_master_tools]: https://github.com/rust-lang/rust/tree/master/src/tools/clippy +[rust_beta_tools]: https://github.com/rust-lang/rust/tree/beta/src/tools/clippy From fbf0b84b32aab798258838d5e932dbc56c4a1813 Mon Sep 17 00:00:00 2001 From: Lzu Tao <taolzu@gmail.com> Date: Tue, 2 Jun 2020 21:42:33 +0700 Subject: [PATCH 167/526] Make use of slice pattern --- clippy_lints/src/utils/mod.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6c1488664bf..7e07e7751e3 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -165,8 +165,8 @@ pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr<'_>, path: &[&st /// Checks if an expression references a variable of the given name. pub fn match_var(expr: &Expr<'_>, var: Name) -> bool { if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind { - if path.segments.len() == 1 && path.segments[0].ident.name == var { - return true; + if let [p] = path.segments { + return p.ident.name == var; } } false @@ -181,8 +181,7 @@ pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> { pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> { match *path { - QPath::Resolved(_, ref path) if path.segments.len() == 1 => Some(&path.segments[0]), - QPath::Resolved(..) => None, + QPath::Resolved(_, ref path) => path.segments.get(0), QPath::TypeRelative(_, ref seg) => Some(seg), } } @@ -201,9 +200,12 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool { QPath::Resolved(_, ref path) => match_path(path, segments), QPath::TypeRelative(ref ty, ref segment) => match ty.kind { TyKind::Path(ref inner_path) => { - !segments.is_empty() - && match_qpath(inner_path, &segments[..(segments.len() - 1)]) - && segment.ident.name.as_str() == segments[segments.len() - 1] + if let [prefix @ .., end] = segments { + if match_qpath(inner_path, prefix) { + return segment.ident.name.as_str() == *end; + } + } + false }, _ => false, }, From dcd480678236d3829f3af3ae9c3339e3e10aebad Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Tue, 2 Jun 2020 20:45:57 +0200 Subject: [PATCH 168/526] Apply suggestions from PR review --- CHANGELOG.md | 6 +++--- doc/changelog_update.md | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd0905e9f39..a8ec5fa67b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,7 +46,7 @@ Current beta, release 2020-07-16 ### Enhancements -* Avoid running cargo/internal lints when not enabled. [#5505](https://github.com/rust-lang/rust-clippy/pull/5505) +* Avoid running cargo lints when not enabled to improve performance. [#5505](https://github.com/rust-lang/rust-clippy/pull/5505) * Extend [`useless_conversion`] with `TryFrom` and `TryInto`. [#5631](https://github.com/rust-lang/rust-clippy/pull/5631) * Lint also in type parameters and where clauses in [`unused_unit`]. [#5592](https://github.com/rust-lang/rust-clippy/pull/5592) * Do not suggest deriving `Default` in [`new_without_default`]. [#5616](https://github.com/rust-lang/rust-clippy/pull/5616) @@ -61,7 +61,7 @@ Current beta, release 2020-07-16 * Don't trigger [`borrowed_box`] on mutable references. [#5491](https://github.com/rust-lang/rust-clippy/pull/5491) * Allow `1 << 0` in [`identity_op`]. [#5602](https://github.com/rust-lang/rust-clippy/pull/5602) * Allow `use super::*;` glob imports in [`wildcard_imports`]. [#5564](https://github.com/rust-lang/rust-clippy/pull/5564) -* Add ignores to the list of words of [`doc_markdown`]. [#5611](https://github.com/rust-lang/rust-clippy/pull/5611) +* Whitelist more words in [`doc_markdown`]. [#5611](https://github.com/rust-lang/rust-clippy/pull/5611) * Skip dev and build deps in [`multiple_crate_versions`]. [#5636](https://github.com/rust-lang/rust-clippy/pull/5636) * Honor `allow` attribute on arguments in [`ptr_arg`]. [#5647](https://github.com/rust-lang/rust-clippy/pull/5647) * Honor lint level attributes for [`redundant_field_names`], [`just_underscores_and_digits`], [`many_single_char_names`] @@ -78,7 +78,7 @@ and [`similar_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/565 ### ICE Fixes * Fix ICE caused in unwrap module. [#5590](https://github.com/rust-lang/rust-clippy/pull/5590) -* Fix crash on rustc test issue-69020-assoc-const-arith-overflow.rs [#5499](https://github.com/rust-lang/rust-clippy/pull/5499) +* Fix ICE on rustc test issue-69020-assoc-const-arith-overflow.rs [#5499](https://github.com/rust-lang/rust-clippy/pull/5499) ### Documentation diff --git a/doc/changelog_update.md b/doc/changelog_update.md index edba3b4741c..1ec07b9dbbe 100644 --- a/doc/changelog_update.md +++ b/doc/changelog_update.md @@ -32,9 +32,10 @@ bullet points might be helpful: need to select the Rust release tag from the dropdown and then check the commit of the Clippy directory: -To find the commit hash, click on "History" of the relevant branch in github -and search for the latest "Merge commit '<hash>' into <branch>" commit. -The <hash> part is then the most recent commit in the clippy repo. +To find the commit hash, issue the following command when in a `rust-lang/rust` checkout: +``` +git log --oneline -- src/tools/clippy/ | grep -o "Merge commit '[a-f0-9]*' into .*" | head -1 | sed -e "s/Merge commit '\([a-f0-9]*\)' into .*/\1/g" +``` ### 2. Fetching the PRs between those commits From b39fd5f62f80cb9bb47ac44d7100f694e0c7301c Mon Sep 17 00:00:00 2001 From: Lzu Tao <taolzu@gmail.com> Date: Wed, 3 Jun 2020 09:04:24 +0700 Subject: [PATCH 169/526] Fix false negative of checked_conversion lint --- clippy_lints/src/checked_conversions.rs | 78 ++++++++--------- tests/ui/checked_conversions.fixed | 106 +++++++++--------------- tests/ui/checked_conversions.rs | 106 +++++++++--------------- tests/ui/checked_conversions.stderr | 98 ++++++++++++++++------ tests/ui/checked_conversions.stdout | 0 5 files changed, 188 insertions(+), 200 deletions(-) delete mode 100644 tests/ui/checked_conversions.stdout diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index d9776dd50a8..e845ef99c7c 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -58,24 +58,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CheckedConversions { } }; - if_chain! { - if let Some(cv) = result; - if let Some(to_type) = cv.to_type; - - then { + if let Some(cv) = result { + if let Some(to_type) = cv.to_type { let mut applicability = Applicability::MachineApplicable; - let snippet = snippet_with_applicability(cx, cv.expr_to_cast.span, "_", &mut - applicability); + let snippet = snippet_with_applicability(cx, cv.expr_to_cast.span, "_", &mut applicability); span_lint_and_sugg( cx, CHECKED_CONVERSIONS, item.span, "Checked cast can be simplified.", "try", - format!("{}::try_from({}).is_ok()", - to_type, - snippet), - applicability + format!("{}::try_from({}).is_ok()", to_type, snippet), + applicability, ); } } @@ -184,7 +178,7 @@ fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> { if_chain! { if let ExprKind::Binary(ref op, ref left, ref right) = &expr.kind; if let Some((candidate, check)) = normalize_le_ge(op, left, right); - if let Some((from, to)) = get_types_from_cast(check, MAX_VALUE, INTS); + if let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX"); then { Conversion::try_new(candidate, from, to) @@ -224,7 +218,7 @@ fn check_lower_bound_zero<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> O /// Check for `expr >= (to_type::MIN as from_type)` fn check_lower_bound_min<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> Option<Conversion<'a>> { - if let Some((from, to)) = get_types_from_cast(check, MIN_VALUE, SINTS) { + if let Some((from, to)) = get_types_from_cast(check, SINTS, "min_value", "MIN") { Conversion::try_new(candidate, from, to) } else { None @@ -232,10 +226,16 @@ fn check_lower_bound_min<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> Op } /// Tries to extract the from- and to-type from a cast expression -fn get_types_from_cast<'a>(expr: &'a Expr<'_>, func: &'a str, types: &'a [&str]) -> Option<(&'a str, &'a str)> { - // `to_type::maxmin_value() as from_type` +fn get_types_from_cast<'a>( + expr: &'a Expr<'_>, + types: &'a [&str], + func: &'a str, + assoc_const: &'a str, +) -> Option<(&'a str, &'a str)> { + // `to_type::max_value() as from_type` + // or `to_type::MAX as from_type` let call_from_cast: Option<(&Expr<'_>, &str)> = if_chain! { - // to_type::maxmin_value(), from_type + // to_type::max_value(), from_type if let ExprKind::Cast(ref limit, ref from_type) = &expr.kind; if let TyKind::Path(ref from_type_path) = &from_type.kind; if let Some(from_sym) = int_ty_to_sym(from_type_path); @@ -247,17 +247,17 @@ fn get_types_from_cast<'a>(expr: &'a Expr<'_>, func: &'a str, types: &'a [&str]) } }; - // `from_type::from(to_type::maxmin_value())` + // `from_type::from(to_type::max_value())` let limit_from: Option<(&Expr<'_>, &str)> = call_from_cast.or_else(|| { if_chain! { - // `from_type::from, to_type::maxmin_value()` + // `from_type::from, to_type::max_value()` if let ExprKind::Call(ref from_func, ref args) = &expr.kind; - // `to_type::maxmin_value()` + // `to_type::max_value()` if args.len() == 1; if let limit = &args[0]; // `from_type::from` if let ExprKind::Path(ref path) = &from_func.kind; - if let Some(from_sym) = get_implementing_type(path, INTS, FROM); + if let Some(from_sym) = get_implementing_type(path, INTS, "from"); then { Some((limit, from_sym)) @@ -268,22 +268,26 @@ fn get_types_from_cast<'a>(expr: &'a Expr<'_>, func: &'a str, types: &'a [&str]) }); if let Some((limit, from_type)) = limit_from { - if_chain! { - if let ExprKind::Call(ref fun_name, _) = &limit.kind; - // `to_type, maxmin_value` - if let ExprKind::Path(ref path) = &fun_name.kind; - // `to_type` - if let Some(to_type) = get_implementing_type(path, types, func); - - then { - Some((from_type, to_type)) - } else { - None - } + match limit.kind { + // `from_type::from(_)` + ExprKind::Call(path, _) => { + if let ExprKind::Path(ref path) = path.kind { + // `to_type` + if let Some(to_type) = get_implementing_type(path, types, func) { + return Some((from_type, to_type)); + } + } + }, + // `to_type::MAX` + ExprKind::Path(ref path) => { + if let Some(to_type) = get_implementing_type(path, types, assoc_const) { + return Some((from_type, to_type)); + } + }, + _ => {}, } - } else { - None - } + }; + None } /// Gets the type which implements the called function @@ -336,10 +340,6 @@ fn normalize_le_ge<'a>(op: &BinOp, left: &'a Expr<'a>, right: &'a Expr<'a>) -> O } // Constants -const FROM: &str = "from"; -const MAX_VALUE: &str = "max_value"; -const MIN_VALUE: &str = "min_value"; - const UINTS: &[&str] = &["u8", "u16", "u32", "u64", "usize"]; const SINTS: &[&str] = &["i8", "i16", "i32", "i64", "isize"]; const INTS: &[&str] = &["u8", "u16", "u32", "u64", "usize", "i8", "i16", "i32", "i64", "isize"]; diff --git a/tests/ui/checked_conversions.fixed b/tests/ui/checked_conversions.fixed index 7febd6f3761..12290db3dcf 100644 --- a/tests/ui/checked_conversions.fixed +++ b/tests/ui/checked_conversions.fixed @@ -1,106 +1,76 @@ // run-rustfix +#![allow( + clippy::cast_lossless, + // Int::max_value will be deprecated in the future + deprecated, +)] #![warn(clippy::checked_conversions)] -#![allow(clippy::cast_lossless)] -#![allow(dead_code)] + use std::convert::TryFrom; // Positive tests // Signed to unsigned -fn i64_to_u32(value: i64) -> Option<u32> { - if u32::try_from(value).is_ok() { - Some(value as u32) - } else { - None - } +pub fn i64_to_u32(value: i64) { + let _ = u32::try_from(value).is_ok(); + let _ = u32::try_from(value).is_ok(); } -fn i64_to_u16(value: i64) -> Option<u16> { - if u16::try_from(value).is_ok() { - Some(value as u16) - } else { - None - } +pub fn i64_to_u16(value: i64) { + let _ = u16::try_from(value).is_ok(); + let _ = u16::try_from(value).is_ok(); } -fn isize_to_u8(value: isize) -> Option<u8> { - if u8::try_from(value).is_ok() { - Some(value as u8) - } else { - None - } +pub fn isize_to_u8(value: isize) { + let _ = u8::try_from(value).is_ok(); + let _ = u8::try_from(value).is_ok(); } // Signed to signed -fn i64_to_i32(value: i64) -> Option<i32> { - if i32::try_from(value).is_ok() { - Some(value as i32) - } else { - None - } +pub fn i64_to_i32(value: i64) { + let _ = i32::try_from(value).is_ok(); + let _ = i32::try_from(value).is_ok(); } -fn i64_to_i16(value: i64) -> Option<i16> { - if i16::try_from(value).is_ok() { - Some(value as i16) - } else { - None - } +pub fn i64_to_i16(value: i64) { + let _ = i16::try_from(value).is_ok(); + let _ = i16::try_from(value).is_ok(); } // Unsigned to X -fn u32_to_i32(value: u32) -> Option<i32> { - if i32::try_from(value).is_ok() { - Some(value as i32) - } else { - None - } +pub fn u32_to_i32(value: u32) { + let _ = i32::try_from(value).is_ok(); + let _ = i32::try_from(value).is_ok(); } -fn usize_to_isize(value: usize) -> isize { - if isize::try_from(value).is_ok() && value as i32 == 5 { - 5 - } else { - 1 - } +pub fn usize_to_isize(value: usize) { + let _ = isize::try_from(value).is_ok() && value as i32 == 5; + let _ = isize::try_from(value).is_ok() && value as i32 == 5; } -fn u32_to_u16(value: u32) -> isize { - if u16::try_from(value).is_ok() && value as i32 == 5 { - 5 - } else { - 1 - } +pub fn u32_to_u16(value: u32) { + let _ = u16::try_from(value).is_ok() && value as i32 == 5; + let _ = u16::try_from(value).is_ok() && value as i32 == 5; } // Negative tests -fn no_i64_to_i32(value: i64) -> Option<i32> { - if value <= (i32::max_value() as i64) && value >= 0 { - Some(value as i32) - } else { - None - } +pub fn no_i64_to_i32(value: i64) { + let _ = value <= (i32::max_value() as i64) && value >= 0; + let _ = value <= (i32::MAX as i64) && value >= 0; } -fn no_isize_to_u8(value: isize) -> Option<u8> { - if value <= (u8::max_value() as isize) && value >= (u8::min_value() as isize) { - Some(value as u8) - } else { - None - } +pub fn no_isize_to_u8(value: isize) { + let _ = value <= (u8::max_value() as isize) && value >= (u8::min_value() as isize); + let _ = value <= (u8::MAX as isize) && value >= (u8::MIN as isize); } -fn i8_to_u8(value: i8) -> Option<u8> { - if value >= 0 { - Some(value as u8) - } else { - None - } +pub fn i8_to_u8(value: i8) { + let _ = value >= 0; } fn main() {} diff --git a/tests/ui/checked_conversions.rs b/tests/ui/checked_conversions.rs index a643354e243..895a301e821 100644 --- a/tests/ui/checked_conversions.rs +++ b/tests/ui/checked_conversions.rs @@ -1,106 +1,76 @@ // run-rustfix +#![allow( + clippy::cast_lossless, + // Int::max_value will be deprecated in the future + deprecated, +)] #![warn(clippy::checked_conversions)] -#![allow(clippy::cast_lossless)] -#![allow(dead_code)] + use std::convert::TryFrom; // Positive tests // Signed to unsigned -fn i64_to_u32(value: i64) -> Option<u32> { - if value <= (u32::max_value() as i64) && value >= 0 { - Some(value as u32) - } else { - None - } +pub fn i64_to_u32(value: i64) { + let _ = value <= (u32::max_value() as i64) && value >= 0; + let _ = value <= (u32::MAX as i64) && value >= 0; } -fn i64_to_u16(value: i64) -> Option<u16> { - if value <= i64::from(u16::max_value()) && value >= 0 { - Some(value as u16) - } else { - None - } +pub fn i64_to_u16(value: i64) { + let _ = value <= i64::from(u16::max_value()) && value >= 0; + let _ = value <= i64::from(u16::MAX) && value >= 0; } -fn isize_to_u8(value: isize) -> Option<u8> { - if value <= (u8::max_value() as isize) && value >= 0 { - Some(value as u8) - } else { - None - } +pub fn isize_to_u8(value: isize) { + let _ = value <= (u8::max_value() as isize) && value >= 0; + let _ = value <= (u8::MAX as isize) && value >= 0; } // Signed to signed -fn i64_to_i32(value: i64) -> Option<i32> { - if value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64) { - Some(value as i32) - } else { - None - } +pub fn i64_to_i32(value: i64) { + let _ = value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64); + let _ = value <= (i32::MAX as i64) && value >= (i32::MIN as i64); } -fn i64_to_i16(value: i64) -> Option<i16> { - if value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value()) { - Some(value as i16) - } else { - None - } +pub fn i64_to_i16(value: i64) { + let _ = value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value()); + let _ = value <= i64::from(i16::MAX) && value >= i64::from(i16::MIN); } // Unsigned to X -fn u32_to_i32(value: u32) -> Option<i32> { - if value <= i32::max_value() as u32 { - Some(value as i32) - } else { - None - } +pub fn u32_to_i32(value: u32) { + let _ = value <= i32::max_value() as u32; + let _ = value <= i32::MAX as u32; } -fn usize_to_isize(value: usize) -> isize { - if value <= isize::max_value() as usize && value as i32 == 5 { - 5 - } else { - 1 - } +pub fn usize_to_isize(value: usize) { + let _ = value <= isize::max_value() as usize && value as i32 == 5; + let _ = value <= isize::MAX as usize && value as i32 == 5; } -fn u32_to_u16(value: u32) -> isize { - if value <= u16::max_value() as u32 && value as i32 == 5 { - 5 - } else { - 1 - } +pub fn u32_to_u16(value: u32) { + let _ = value <= u16::max_value() as u32 && value as i32 == 5; + let _ = value <= u16::MAX as u32 && value as i32 == 5; } // Negative tests -fn no_i64_to_i32(value: i64) -> Option<i32> { - if value <= (i32::max_value() as i64) && value >= 0 { - Some(value as i32) - } else { - None - } +pub fn no_i64_to_i32(value: i64) { + let _ = value <= (i32::max_value() as i64) && value >= 0; + let _ = value <= (i32::MAX as i64) && value >= 0; } -fn no_isize_to_u8(value: isize) -> Option<u8> { - if value <= (u8::max_value() as isize) && value >= (u8::min_value() as isize) { - Some(value as u8) - } else { - None - } +pub fn no_isize_to_u8(value: isize) { + let _ = value <= (u8::max_value() as isize) && value >= (u8::min_value() as isize); + let _ = value <= (u8::MAX as isize) && value >= (u8::MIN as isize); } -fn i8_to_u8(value: i8) -> Option<u8> { - if value >= 0 { - Some(value as u8) - } else { - None - } +pub fn i8_to_u8(value: i8) { + let _ = value >= 0; } fn main() {} diff --git a/tests/ui/checked_conversions.stderr b/tests/ui/checked_conversions.stderr index f678f009621..648ba3ccd01 100644 --- a/tests/ui/checked_conversions.stderr +++ b/tests/ui/checked_conversions.stderr @@ -1,52 +1,100 @@ error: Checked cast can be simplified. - --> $DIR/checked_conversions.rs:13:8 + --> $DIR/checked_conversions.rs:17:13 | -LL | if value <= (u32::max_value() as i64) && value >= 0 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` +LL | let _ = value <= (u32::max_value() as i64) && value >= 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` | = note: `-D clippy::checked-conversions` implied by `-D warnings` error: Checked cast can be simplified. - --> $DIR/checked_conversions.rs:21:8 + --> $DIR/checked_conversions.rs:18:13 | -LL | if value <= i64::from(u16::max_value()) && value >= 0 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` +LL | let _ = value <= (u32::MAX as i64) && value >= 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` error: Checked cast can be simplified. - --> $DIR/checked_conversions.rs:29:8 + --> $DIR/checked_conversions.rs:22:13 | -LL | if value <= (u8::max_value() as isize) && value >= 0 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` +LL | let _ = value <= i64::from(u16::max_value()) && value >= 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: Checked cast can be simplified. - --> $DIR/checked_conversions.rs:39:8 + --> $DIR/checked_conversions.rs:23:13 | -LL | if value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` +LL | let _ = value <= i64::from(u16::MAX) && value >= 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: Checked cast can be simplified. - --> $DIR/checked_conversions.rs:47:8 + --> $DIR/checked_conversions.rs:27:13 | -LL | if value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` +LL | let _ = value <= (u8::max_value() as isize) && value >= 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` error: Checked cast can be simplified. - --> $DIR/checked_conversions.rs:57:8 + --> $DIR/checked_conversions.rs:28:13 | -LL | if value <= i32::max_value() as u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` +LL | let _ = value <= (u8::MAX as isize) && value >= 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` error: Checked cast can be simplified. - --> $DIR/checked_conversions.rs:65:8 + --> $DIR/checked_conversions.rs:34:13 | -LL | if value <= isize::max_value() as usize && value as i32 == 5 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` +LL | let _ = value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: Checked cast can be simplified. - --> $DIR/checked_conversions.rs:73:8 + --> $DIR/checked_conversions.rs:35:13 | -LL | if value <= u16::max_value() as u32 && value as i32 == 5 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` +LL | let _ = value <= (i32::MAX as i64) && value >= (i32::MIN as i64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` -error: aborting due to 8 previous errors +error: Checked cast can be simplified. + --> $DIR/checked_conversions.rs:39:13 + | +LL | let _ = value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` + +error: Checked cast can be simplified. + --> $DIR/checked_conversions.rs:40:13 + | +LL | let _ = value <= i64::from(i16::MAX) && value >= i64::from(i16::MIN); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` + +error: Checked cast can be simplified. + --> $DIR/checked_conversions.rs:46:13 + | +LL | let _ = value <= i32::max_value() as u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` + +error: Checked cast can be simplified. + --> $DIR/checked_conversions.rs:47:13 + | +LL | let _ = value <= i32::MAX as u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` + +error: Checked cast can be simplified. + --> $DIR/checked_conversions.rs:51:13 + | +LL | let _ = value <= isize::max_value() as usize && value as i32 == 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` + +error: Checked cast can be simplified. + --> $DIR/checked_conversions.rs:52:13 + | +LL | let _ = value <= isize::MAX as usize && value as i32 == 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` + +error: Checked cast can be simplified. + --> $DIR/checked_conversions.rs:56:13 + | +LL | let _ = value <= u16::max_value() as u32 && value as i32 == 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` + +error: Checked cast can be simplified. + --> $DIR/checked_conversions.rs:57:13 + | +LL | let _ = value <= u16::MAX as u32 && value as i32 == 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` + +error: aborting due to 16 previous errors diff --git a/tests/ui/checked_conversions.stdout b/tests/ui/checked_conversions.stdout deleted file mode 100644 index e69de29bb2d..00000000000 From 7654125d27d95d5c329e554115b510efc1ab1e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 4 Jun 2020 03:34:22 +0200 Subject: [PATCH 170/526] match_wildcard_for_single_variants: remove empty line at start of lint example. See https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants changelog: none --- clippy_lints/src/matches.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 146212cb2c7..6d7af45a472 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -270,7 +270,6 @@ declare_clippy_lint! { /// ```rust /// # enum Foo { A, B, C } /// # let x = Foo::B; - /// /// // Bad /// match x { /// Foo::A => {}, From 9ef15ae7c86a08c96a368f6728b25e1c55f6e10b Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Fri, 5 Jun 2020 13:56:07 +0200 Subject: [PATCH 171/526] Reorder sections of release documentation Before tagging a commit the beta branch has to be remerged --- doc/release.md | 120 ++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/doc/release.md b/doc/release.md index 9d69fa8a7f6..f0a7fe52149 100644 --- a/doc/release.md +++ b/doc/release.md @@ -7,11 +7,11 @@ Clippy is released together with stable Rust releases. The dates for these releases can be found at the [Rust Forge]. This document explains the necessary steps to create a Clippy release. -1. [Find the Clippy commit](#find-the-clippy-commit) -2. [Tag the stable commit](#tag-the-stable-commit) -3. [Update `CHANGELOG.md`](#update-changelogmd) -4. [Remerge the `beta` branch](#remerge-the-beta-branch) -5. [Update the `beta` branch](#update-the-beta-branch) +1. [Remerge the `beta` branch](#remerge-the-beta-branch) +2. [Update the `beta` branch](#update-the-beta-branch) +3. [Find the Clippy commit](#find-the-clippy-commit) +4. [Tag the stable commit](#tag-the-stable-commit) +5. [Update `CHANGELOG.md`](#update-changelogmd) _NOTE: This document is for stable Rust releases, not for point releases. For point releases, step 1. and 2. should be enough._ @@ -19,6 +19,61 @@ point releases, step 1. and 2. should be enough._ [Rust Forge]: https://forge.rust-lang.org/ +## Remerge the `beta` branch + +This step is only necessary, if since the last release something was backported +to the beta Rust release. The remerge is then necessary, to make sure that the +Clippy commit, that was used by the now stable Rust release, persists in the +tree of the Clippy repository. + +To find out if this step is necessary run + +```bash +# Assumes that the local master branch is up-to-date +$ git fetch upstream +$ git branch master --contains upstream/beta +``` + +If this command outputs `master`, this step is **not** necessary. + +```bash +# Assuming `HEAD` is the current `master` branch of rust-lang/rust-clippy +$ git checkout -b backport_remerge +$ git merge upstream/beta +$ git diff # This diff has to be empty, otherwise something with the remerge failed +$ git push origin backport_remerge # This can be pushed to your fork +``` + +After this, open a PR to the master branch. In this PR, the commit hash of the +`HEAD` of the `beta` branch must exists. In addition to that, no files should +be changed by this PR. + + +## Update the `beta` branch + +This step must be done **after** the PR of the previous step was merged. + +First, the Clippy commit of the `beta` branch of the Rust repository has to be +determined. + +```bash +# Assuming the current directory corresponds to the Rust repository +$ git checkout beta +$ git submodule update +$ BETA_SHA=$(git submodule status src/tools/clippy | awk '{print $1}') +``` + +After finding the Clippy commit, the `beta` branch in the Clippy repository can +be updated. + +```bash +# Assuming the current directory corresponds to the Clippy repository +$ git checkout beta +$ git rebase $BETA_SHA +$ git push upstream beta +``` + + ## Find the Clippy commit The first step is to tag the Clippy commit, that is included in the stable Rust @@ -54,58 +109,3 @@ After this, the release should be available on the Clippy [release page]. For this see the document on [how to update the changelog]. [how to update the changelog]: https://github.com/rust-lang/rust-clippy/blob/master/doc/changelog_update.md - - -## Remerge the `beta` branch - -This step is only necessary, if since the last release something was backported -to the beta Rust release. The remerge is then necessary, to make sure that the -Clippy commit, that was used by the now stable Rust release, persists in the -tree of the Clippy repository. - -To find out if this step is necessary run - -```bash -# Assumes that the local master branch is up-to-date -$ git fetch upstream -$ git branch master --contains upstream/beta -``` - -If this command outputs `master`, this step is **not** necessary. - -```bash -# Assuming `HEAD` is the current `master` branch of rust-lang/rust-clippy -$ git checkout -b backport_remerge -$ git merge beta -$ git diff # This diff has to be empty, otherwise something with the remerge failed -$ git push origin backport_remerge # This can be pushed to your fork -``` - -After this, open a PR to the master branch. In this PR, the commit hash of the -`HEAD` of the `beta` branch must exists. In addition to that, no files should -be changed by this PR. - - -## Update the `beta` branch - -This step must be done **after** the PR of the previous step was merged. - -First, the Clippy commit of the `beta` branch of the Rust repository has to be -determined. - -```bash -# Assuming the current directory corresponds to the Rust repository -$ git checkout beta -$ git submodule update -$ BETA_SHA=$(git submodule status src/tools/clippy | awk '{print $1}') -``` - -After finding the Clippy commit, the `beta` branch in the Clippy repository can -be updated. - -```bash -# Assuming the current directory corresponds to the Clippy repository -$ git checkout beta -$ git rebase $BETA_SHA -$ git push upstream beta -``` From 6b9e2e90bf7688bfbcf357fda6e0ef74e11ba1ff Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Fri, 5 Jun 2020 14:47:12 +0200 Subject: [PATCH 172/526] Replace all remaining occurrences of submodule with subtree --- doc/changelog_update.md | 2 +- doc/release.md | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/changelog_update.md b/doc/changelog_update.md index 0b80cce6d23..6657ab4187b 100644 --- a/doc/changelog_update.md +++ b/doc/changelog_update.md @@ -18,7 +18,7 @@ been very rare that Clippy changes were included in a patch release. ### 1. Finding the relevant Clippy commits -Each Rust release ships with its own version of Clippy. The Clippy submodule can +Each Rust release ships with its own version of Clippy. The Clippy subtree can be found in the `tools` directory of the Rust repository. Depending on the current time and what exactly you want to update, the following diff --git a/doc/release.md b/doc/release.md index f0a7fe52149..391952ea6b1 100644 --- a/doc/release.md +++ b/doc/release.md @@ -59,8 +59,7 @@ determined. ```bash # Assuming the current directory corresponds to the Rust repository $ git checkout beta -$ git submodule update -$ BETA_SHA=$(git submodule status src/tools/clippy | awk '{print $1}') +$ BETA_SHA=$(git log --oneline -- src/tools/clippy/ | grep -o "Merge commit '[a-f0-9]*' into .*" | head -1 | sed -e "s/Merge commit '\([a-f0-9]*\)' into .*/\1/g") ``` After finding the Clippy commit, the `beta` branch in the Clippy repository can @@ -83,8 +82,7 @@ release. This commit can be found in the Rust repository. # Assuming the current directory corresponds to the Rust repository $ git fetch upstream # `upstream` is the `rust-lang/rust` remote $ git checkout 1.XX.0 # XX should be exchanged with the corresponding version -$ git submodule update -$ SHA=$(git submodule status src/tools/clippy | awk '{print $1}') +$ SHA=$(git log --oneline -- src/tools/clippy/ | grep -o "Merge commit '[a-f0-9]*' into .*" | head -1 | sed -e "s/Merge commit '\([a-f0-9]*\)' into .*/\1/g") ``` From 413713c8848ec94d5f1709a41537c300da398806 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Fri, 5 Jun 2020 22:28:58 +0200 Subject: [PATCH 173/526] Add error info when cargo metadata fails to run --- clippy_lints/src/cargo_common_metadata.rs | 13 ++----------- clippy_lints/src/multiple_crate_versions.rs | 10 ++-------- clippy_lints/src/utils/mod.rs | 18 ++++++++++++++++++ clippy_lints/src/wildcard_dependencies.rs | 7 +------ 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index 16b46423c8f..c40a387d297 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -36,13 +36,9 @@ declare_clippy_lint! { "common metadata is defined in `Cargo.toml`" } -fn warning(cx: &LateContext<'_, '_>, message: &str) { - span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, message); -} - fn missing_warning(cx: &LateContext<'_, '_>, package: &cargo_metadata::Package, field: &str) { let message = format!("package `{}` is missing `{}` metadata", package.name, field); - warning(cx, &message); + span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message); } fn is_empty_str(value: &Option<String>) -> bool { @@ -66,12 +62,7 @@ impl LateLintPass<'_, '_> for CargoCommonMetadata { return; } - let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().no_deps().exec() { - metadata - } else { - warning(cx, "could not read cargo metadata"); - return; - }; + let metadata = unwrap_cargo_metadata!(cx, CARGO_COMMON_METADATA, false); for package in metadata.packages { if is_empty_vec(&package.authors) { diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index b6770804e18..6c42014b4c8 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -7,7 +7,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; -use cargo_metadata::{DependencyKind, MetadataCommand, Node, Package, PackageId}; +use cargo_metadata::{DependencyKind, Node, Package, PackageId}; use if_chain::if_chain; use itertools::Itertools; @@ -42,13 +42,7 @@ impl LateLintPass<'_, '_> for MultipleCrateVersions { return; } - let metadata = if let Ok(metadata) = MetadataCommand::new().exec() { - metadata - } else { - span_lint(cx, MULTIPLE_CRATE_VERSIONS, DUMMY_SP, "could not read cargo metadata"); - return; - }; - + let metadata = unwrap_cargo_metadata!(cx, MULTIPLE_CRATE_VERSIONS, true); let local_name = cx.tcx.crate_name(LOCAL_CRATE).as_str(); let mut packages = metadata.packages; packages.sort_by(|a, b| a.name.cmp(&b.name)); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 7e07e7751e3..2cdb6486fcb 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1405,6 +1405,24 @@ pub fn run_lints(cx: &LateContext<'_, '_>, lints: &[&'static Lint], id: HirId) - }) } +#[macro_export] +macro_rules! unwrap_cargo_metadata { + ($cx: ident, $lint: ident, $deps: expr) => {{ + let mut command = cargo_metadata::MetadataCommand::new(); + if !$deps { + command.no_deps(); + } + + match command.exec() { + Ok(metadata) => metadata, + Err(err) => { + span_lint($cx, $lint, DUMMY_SP, &format!("could not read cargo metadata: {}", err)); + return; + }, + } + }}; +} + #[cfg(test)] mod test { use super::{trim_multiline, without_block_comments}; diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index d8d48eb1535..511518082be 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -34,12 +34,7 @@ impl LateLintPass<'_, '_> for WildcardDependencies { return; } - let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().no_deps().exec() { - metadata - } else { - span_lint(cx, WILDCARD_DEPENDENCIES, DUMMY_SP, "could not read cargo metadata"); - return; - }; + let metadata = unwrap_cargo_metadata!(cx, WILDCARD_DEPENDENCIES, false); for dep in &metadata.packages[0].dependencies { // VersionReq::any() does not work From c325c120c21657acb1b131ded41261889e51a62b Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Fri, 5 Jun 2020 22:30:14 +0200 Subject: [PATCH 174/526] Fix cargo ui tests when running inside rust repo --- clippy_dev/src/new_lint.rs | 2 ++ tests/compile-test.rs | 4 ---- tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml | 2 ++ tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml | 2 ++ .../multiple_crate_versions/5041_allow_dev_build/Cargo.toml | 2 ++ tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml | 2 ++ tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml | 2 ++ tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml | 2 ++ tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml | 2 ++ 9 files changed, 16 insertions(+), 4 deletions(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index c0b2dac2f60..1e032a7bc20 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -147,6 +147,8 @@ fn get_manifest_contents(lint_name: &str, hint: &str) -> String { name = "{}" version = "0.1.0" publish = false + +[workspace] "#, hint, lint_name ) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 194354b291f..11b3f69a828 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -220,10 +220,6 @@ fn run_ui_cargo(config: &mut compiletest::Config) { Ok(result) } - if cargo::is_rustc_test_suite() { - return; - } - config.mode = TestMode::Ui; config.src_base = Path::new("tests").join("ui-cargo").canonicalize().unwrap(); diff --git a/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml index c64adcf7c01..ae0a6032996 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml +++ b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml @@ -2,3 +2,5 @@ name = "cargo_common_metadata" version = "0.1.0" publish = false + +[workspace] diff --git a/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml index c8233f328bb..737e84e963c 100644 --- a/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml +++ b/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml @@ -9,3 +9,5 @@ readme = "README.md" license = "MIT OR Apache-2.0" keywords = ["metadata", "lint", "clippy"] categories = ["development-tools::testing"] + +[workspace] diff --git a/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml index 72731fbc75d..278bebbbd9e 100644 --- a/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml @@ -5,6 +5,8 @@ name = "multiple_crate_versions" version = "0.1.0" publish = false +[workspace] + # One of the versions of winapi is only a dev dependency: allowed [dependencies] ctrlc = "=3.1.0" diff --git a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml index 3a94b723f3f..4f97b011334 100644 --- a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml @@ -3,6 +3,8 @@ name = "multiple_crate_versions" version = "0.1.0" publish = false +[workspace] + [dependencies] ctrlc = "=3.1.0" ansi_term = "=0.11.0" diff --git a/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml index a9b06420b33..b4b49bb369a 100644 --- a/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml @@ -3,6 +3,8 @@ name = "cargo_common_metadata" version = "0.1.0" publish = false +[workspace] + [dependencies] regex = "1.3.7" serde = "1.0.110" diff --git a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml index fd2a3414856..3e1a02cbb3c 100644 --- a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml +++ b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml @@ -3,5 +3,7 @@ name = "wildcard_dependencies" version = "0.1.0" publish = false +[workspace] + [dependencies] regex = "*" diff --git a/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml b/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml index 38cb139146e..f844cab09ba 100644 --- a/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml +++ b/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml @@ -3,5 +3,7 @@ name = "wildcard_dependencies" version = "0.1.0" publish = false +[workspace] + [dependencies] regex = "1" From 623faac84ec56fa545163ab81d7e3b759a392353 Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Sat, 6 Jun 2020 11:50:59 +0200 Subject: [PATCH 175/526] Cleanup: Use rustc's `same_types` instead of our `same_tys` --- clippy_lints/src/copies.rs | 14 +++++--------- clippy_lints/src/loops.rs | 8 ++++---- clippy_lints/src/methods/mod.rs | 12 ++++++------ clippy_lints/src/new_without_default.rs | 6 +++--- clippy_lints/src/types.rs | 6 +++--- clippy_lints/src/useless_conversion.rs | 14 +++++++------- clippy_lints/src/utils/mod.rs | 16 +--------------- 7 files changed, 29 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 66722786eab..b6d50bdfa14 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,9 +1,9 @@ -use crate::utils::{get_parent_expr, higher, if_sequence, same_tys, snippet, span_lint_and_note, span_lint_and_then}; +use crate::utils::{get_parent_expr, higher, if_sequence, snippet, span_lint_and_note, span_lint_and_then}; use crate::utils::{SpanlessEq, SpanlessHash}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Arm, Block, Expr, ExprKind, MatchSource, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{Ty, TyS}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; use std::collections::hash_map::Entry; @@ -242,15 +242,11 @@ fn lint_same_fns_in_if_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) { /// Implementation of `MATCH_SAME_ARMS`. fn lint_match_arms<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr<'_>) { - fn same_bindings<'tcx>( - cx: &LateContext<'_, 'tcx>, - lhs: &FxHashMap<Symbol, Ty<'tcx>>, - rhs: &FxHashMap<Symbol, Ty<'tcx>>, - ) -> bool { + fn same_bindings<'tcx>(lhs: &FxHashMap<Symbol, Ty<'tcx>>, rhs: &FxHashMap<Symbol, Ty<'tcx>>) -> bool { lhs.len() == rhs.len() && lhs .iter() - .all(|(name, l_ty)| rhs.get(name).map_or(false, |r_ty| same_tys(cx, l_ty, r_ty))) + .all(|(name, l_ty)| rhs.get(name).map_or(false, |r_ty| TyS::same_type(l_ty, r_ty))) } if let ExprKind::Match(_, ref arms, MatchSource::Normal) = expr.kind { @@ -269,7 +265,7 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr<'_>) { (min_index..=max_index).all(|index| arms[index].guard.is_none()) && SpanlessEq::new(cx).eq_expr(&lhs.body, &rhs.body) && // all patterns should have the same bindings - same_bindings(cx, &bindings(cx, &lhs.pat), &bindings(cx, &rhs.pat)) + same_bindings(&bindings(cx, &lhs.pat), &bindings(cx, &rhs.pat)) }; let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect(); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index dbe41823a9c..57c62d73964 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -8,7 +8,7 @@ use crate::utils::{ multispan_sugg, snippet, snippet_opt, snippet_with_applicability, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, SpanlessEq, }; -use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sugg}; +use crate::utils::{is_type_diagnostic_item, qpath_res, sugg}; use if_chain::if_chain; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -24,7 +24,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; use rustc_middle::middle::region; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TyS}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; @@ -1256,7 +1256,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, e } else if method_name == "into_iter" && match_trait_method(cx, arg, &paths::INTO_ITERATOR) { let receiver_ty = cx.tables.expr_ty(&args[0]); let receiver_ty_adjusted = cx.tables.expr_ty_adjusted(&args[0]); - if same_tys(cx, receiver_ty, receiver_ty_adjusted) { + if TyS::same_type(receiver_ty, receiver_ty_adjusted) { let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); span_lint_and_sugg( @@ -1277,7 +1277,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, e mutbl: Mutability::Not, }, ); - if same_tys(cx, receiver_ty_adjusted, ref_receiver_ty) { + if TyS::same_type(receiver_ty_adjusted, ref_receiver_ty) { lint_iter_method(cx, args, arg, method_name) } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index a9c0ff24fa6..78d69690c2d 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -18,7 +18,7 @@ use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TyS}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::{sym, SymbolStr}; @@ -29,9 +29,9 @@ use crate::utils::{ get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro, is_copy, is_ctor_or_promotable_const_function, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath, match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, - remove_blocks, return_ty, same_tys, single_segment_path, snippet, snippet_with_applicability, - snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, - span_lint_and_then, sugg, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, + remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, + span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty, + walk_ptrs_ty_depth, SpanlessEq, }; declare_clippy_lint! { @@ -1548,7 +1548,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { let contains_self_ty = |ty: Ty<'tcx>| { ty.walk().any(|inner| match inner.unpack() { - GenericArgKind::Type(inner_ty) => same_tys(cx, self_ty, inner_ty), + GenericArgKind::Type(inner_ty) => TyS::same_type(self_ty, inner_ty), GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, }) @@ -1575,7 +1575,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { } } - if name == "new" && !same_tys(cx, ret_ty, self_ty) { + if name == "new" && !TyS::same_type(ret_ty, self_ty) { span_lint( cx, NEW_RET_NO_SELF, diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index e556e5d59c1..dd236535c18 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -1,13 +1,13 @@ use crate::utils::paths; use crate::utils::sugg::DiagnosticBuilderExt; -use crate::utils::{get_trait_def_id, return_ty, same_tys, span_lint_hir_and_then}; +use crate::utils::{get_trait_def_id, return_ty, span_lint_hir_and_then}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::HirIdSet; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{Ty, TyS}; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { @@ -93,7 +93,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { let self_def_id = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent_item(id)); let self_ty = cx.tcx.type_of(self_def_id); if_chain! { - if same_tys(cx, self_ty, return_ty(cx, id)); + if TyS::same_type(self_ty, return_ty(cx, id)); if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); then { if self.impling_types.is_none() { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 5ca30d598eb..bc5fe44b30f 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -17,7 +17,7 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, InferTy, Ty, TyCtxt, TypeckTables}; +use rustc_middle::ty::{self, InferTy, Ty, TyCtxt, TyS, TypeckTables}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::Span; @@ -31,7 +31,7 @@ use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_type_diagnostic_item, last_path_segment, match_def_path, match_path, method_chain_args, multispan_sugg, numeric_literal::NumericLiteral, - qpath_res, same_tys, sext, snippet, snippet_block_with_applicability, snippet_opt, snippet_with_applicability, + qpath_res, sext, snippet, snippet_block_with_applicability, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext, }; @@ -2556,7 +2556,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't if let ExprKind::Path(QPath::TypeRelative(ref ty, ref method)) = fun.kind; if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind; then { - if !same_tys(self.cx, self.target.ty(), self.body.expr_ty(e)) { + if !TyS::same_type(self.target.ty(), self.body.expr_ty(e)) { return; } diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 7fa97b24699..141035a980a 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -1,12 +1,12 @@ use crate::utils::{ - is_type_diagnostic_item, match_def_path, match_trait_method, paths, same_tys, snippet, snippet_with_macro_callsite, + is_type_diagnostic_item, match_def_path, match_trait_method, paths, snippet, snippet_with_macro_callsite, span_lint_and_help, span_lint_and_sugg, }; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, HirId, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; +use rustc_middle::ty::{self, TyS}; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { @@ -65,7 +65,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { if match_trait_method(cx, e, &paths::INTO) && &*name.ident.as_str() == "into" { let a = cx.tables.expr_ty(e); let b = cx.tables.expr_ty(&args[0]); - if same_tys(cx, a, b) { + if TyS::same_type(a, b) { let sugg = snippet_with_macro_callsite(cx, args[0].span, "<expr>").to_string(); span_lint_and_sugg( cx, @@ -81,7 +81,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { if match_trait_method(cx, e, &paths::INTO_ITERATOR) && &*name.ident.as_str() == "into_iter" { let a = cx.tables.expr_ty(e); let b = cx.tables.expr_ty(&args[0]); - if same_tys(cx, a, b) { + if TyS::same_type(a, b) { let sugg = snippet(cx, args[0].span, "<expr>").into_owned(); span_lint_and_sugg( cx, @@ -101,7 +101,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { if is_type_diagnostic_item(cx, a, sym!(result_type)); if let ty::Adt(_, substs) = a.kind; if let Some(a_type) = substs.types().next(); - if same_tys(cx, a_type, b); + if TyS::same_type(a_type, b); then { span_lint_and_help( @@ -131,7 +131,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { if is_type_diagnostic_item(cx, a, sym!(result_type)); if let ty::Adt(_, substs) = a.kind; if let Some(a_type) = substs.types().next(); - if same_tys(cx, a_type, b); + if TyS::same_type(a_type, b); then { let hint = format!("consider removing `{}()`", snippet(cx, path.span, "TryFrom::try_from")); @@ -148,7 +148,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { if_chain! { if match_def_path(cx, def_id, &paths::FROM_FROM); - if same_tys(cx, a, b); + if TyS::same_type(a, b); then { let sugg = snippet(cx, args[0].span.source_callsite(), "<expr>").into_owned(); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 2cdb6486fcb..9a6750c51ab 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -40,7 +40,7 @@ use rustc_hir::{ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::map::Map; -use rustc_middle::ty::{self, layout::IntegerExt, subst::GenericArg, Binder, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, layout::IntegerExt, subst::GenericArg, Ty, TyCtxt, TypeFoldable}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::original_sp; use rustc_span::symbol::{self, kw, Symbol}; @@ -879,20 +879,6 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: hir::HirId) -> T cx.tcx.erase_late_bound_regions(&ret_ty) } -/// Checks if two types are the same. -/// -/// This discards any lifetime annotations, too. -// -// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == -// `for <'b> Foo<'b>`, but not for type parameters). -pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - let a = cx.tcx.erase_late_bound_regions(&Binder::bind(a)); - let b = cx.tcx.erase_late_bound_regions(&Binder::bind(b)); - cx.tcx - .infer_ctxt() - .enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok()) -} - /// Returns `true` if the given type is an `unsafe` function. pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind { From 5bdbc45ae579e7b8f4187bc791abd67924cb626b Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sun, 7 Jun 2020 03:07:48 +0200 Subject: [PATCH 176/526] Rustup to rust-lang/rust#71796 --- tests/ui/or_fun_call.fixed | 4 ++-- tests/ui/or_fun_call.stderr | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index 7bb08797ef3..2045ffdb5f0 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -29,7 +29,7 @@ fn or_fun_call() { with_enum.unwrap_or(Enum::A(5)); let with_const_fn = Some(Duration::from_secs(1)); - with_const_fn.unwrap_or(Duration::from_secs(5)); + with_const_fn.unwrap_or_else(|| Duration::from_secs(5)); let with_constructor = Some(vec![1]); with_constructor.unwrap_or_else(make); @@ -94,7 +94,7 @@ fn test_or_with_ctors() { let b = "b".to_string(); let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) - .or(Some(Bar(b, Duration::from_secs(2)))); + .or_else(|| Some(Bar(b, Duration::from_secs(2)))); let vec = vec!["foo"]; let _ = opt.ok_or(vec.len()); diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index 96d55771e6c..bc5978b538f 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -1,10 +1,16 @@ +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:32:19 + | +LL | with_const_fn.unwrap_or(Duration::from_secs(5)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Duration::from_secs(5))` + | + = note: `-D clippy::or-fun-call` implied by `-D warnings` + error: use of `unwrap_or` followed by a function call --> $DIR/or_fun_call.rs:35:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` - | - = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` --> $DIR/or_fun_call.rs:38:5 @@ -78,5 +84,11 @@ error: use of `or` followed by a function call LL | let _ = Some("a".to_string()).or(Some("b".to_string())); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))` -error: aborting due to 13 previous errors +error: use of `or` followed by a function call + --> $DIR/or_fun_call.rs:97:10 + | +LL | .or(Some(Bar(b, Duration::from_secs(2)))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some(Bar(b, Duration::from_secs(2))))` + +error: aborting due to 15 previous errors From d9aa26a14dca32e0c4f2718ad1d3322f0de1674d Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sun, 7 Jun 2020 14:54:21 +0200 Subject: [PATCH 177/526] Temporarily disable RLS integration test --- .github/workflows/clippy_bors.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 3958ba01246..0c80394f03e 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -232,7 +232,8 @@ jobs: matrix: integration: - 'rust-lang/cargo' - - 'rust-lang/rls' + # FIXME: re-enable once fmt_macros is renamed in RLS + # - 'rust-lang/rls' - 'rust-lang/chalk' - 'rust-lang/rustfmt' - 'Marwes/combine' From dc13016ac2df1ce2663660389409b15eb2cf7e40 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Wed, 3 Jun 2020 01:13:57 +0200 Subject: [PATCH 178/526] Make let_and_return a late lint pass --- clippy_lints/src/let_and_return.rs | 82 ++++++++++++++++++++++++++++++ clippy_lints/src/lib.rs | 8 +-- clippy_lints/src/returns.rs | 82 ++---------------------------- src/lintlist/mod.rs | 2 +- 4 files changed, 91 insertions(+), 83 deletions(-) create mode 100644 clippy_lints/src/let_and_return.rs diff --git a/clippy_lints/src/let_and_return.rs b/clippy_lints/src/let_and_return.rs new file mode 100644 index 00000000000..8b877f696af --- /dev/null +++ b/clippy_lints/src/let_and_return.rs @@ -0,0 +1,82 @@ +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Block, ExprKind, PatKind, StmtKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +use crate::utils::{in_macro, match_qpath, snippet_opt, span_lint_and_then}; + +declare_clippy_lint! { + /// **What it does:** Checks for `let`-bindings, which are subsequently + /// returned. + /// + /// **Why is this bad?** It is just extraneous code. Remove it to make your code + /// more rusty. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// fn foo() -> String { + /// let x = String::new(); + /// x + /// } + /// ``` + /// instead, use + /// ``` + /// fn foo() -> String { + /// String::new() + /// } + /// ``` + pub LET_AND_RETURN, + style, + "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block" +} + +declare_lint_pass!(LetReturn => [LET_AND_RETURN]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetReturn { + fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block<'_>) { + // we need both a let-binding stmt and an expr + if_chain! { + if let Some(retexpr) = block.expr; + if let Some(stmt) = block.stmts.iter().last(); + if let StmtKind::Local(local) = &stmt.kind; + if local.ty.is_none(); + if local.attrs.is_empty(); + if let Some(initexpr) = &local.init; + if let PatKind::Binding(.., ident, _) = local.pat.kind; + if let ExprKind::Path(qpath) = &retexpr.kind; + if match_qpath(qpath, &[&*ident.name.as_str()]); + if !in_external_macro(cx.sess(), initexpr.span); + if !in_external_macro(cx.sess(), retexpr.span); + if !in_external_macro(cx.sess(), local.span); + if !in_macro(local.span); + then { + span_lint_and_then( + cx, + LET_AND_RETURN, + retexpr.span, + "returning the result of a `let` binding from a block", + |err| { + err.span_label(local.span, "unnecessary `let` binding"); + + if let Some(snippet) = snippet_opt(cx, initexpr.span) { + err.multipart_suggestion( + "return the expression directly", + vec![ + (local.span, String::new()), + (retexpr.span, snippet), + ], + Applicability::MachineApplicable, + ); + } else { + err.span_help(initexpr.span, "this expression can be directly returned"); + } + }, + ); + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6f8923b2660..6bc9e23bac5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -239,6 +239,7 @@ mod large_const_arrays; mod large_enum_variant; mod large_stack_arrays; mod len_zero; +mod let_and_return; mod let_if_seq; mod let_underscore; mod lifetimes; @@ -596,6 +597,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &large_stack_arrays::LARGE_STACK_ARRAYS, &len_zero::LEN_WITHOUT_IS_EMPTY, &len_zero::LEN_ZERO, + &let_and_return::LET_AND_RETURN, &let_if_seq::USELESS_LET_IF_SEQ, &let_underscore::LET_UNDERSCORE_LOCK, &let_underscore::LET_UNDERSCORE_MUST_USE, @@ -772,7 +774,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ®ex::INVALID_REGEX, ®ex::REGEX_MACRO, ®ex::TRIVIAL_REGEX, - &returns::LET_AND_RETURN, &returns::NEEDLESS_RETURN, &returns::UNUSED_UNIT, &serde_api::SERDE_API_MISUSE, @@ -1022,6 +1023,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box formatting::Formatting); store.register_early_pass(|| box misc_early::MiscEarlyLints); store.register_early_pass(|| box returns::Return); + store.register_late_pass(|| box let_and_return::LetReturn); store.register_early_pass(|| box collapsible_if::CollapsibleIf); store.register_early_pass(|| box items_after_statements::ItemsAfterStatements); store.register_early_pass(|| box precedence::Precedence); @@ -1265,6 +1267,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), + LintId::of(&let_and_return::LET_AND_RETURN), LintId::of(&let_underscore::LET_UNDERSCORE_LOCK), LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES), LintId::of(&lifetimes::NEEDLESS_LIFETIMES), @@ -1390,7 +1393,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(®ex::INVALID_REGEX), LintId::of(®ex::REGEX_MACRO), LintId::of(®ex::TRIVIAL_REGEX), - LintId::of(&returns::LET_AND_RETURN), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), LintId::of(&serde_api::SERDE_API_MISUSE), @@ -1474,6 +1476,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&inherent_to_string::INHERENT_TO_STRING), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), + LintId::of(&let_and_return::LET_AND_RETURN), LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING), LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::FOR_KV_MAP), @@ -1526,7 +1529,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), LintId::of(®ex::REGEX_MACRO), LintId::of(®ex::TRIVIAL_REGEX), - LintId::of(&returns::LET_AND_RETURN), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 35464f629c3..3c939744173 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -8,7 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::BytePos; -use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_sugg, span_lint_and_then}; +use crate::utils::{snippet_opt, span_lint_and_sugg, span_lint_and_then}; declare_clippy_lint! { /// **What it does:** Checks for return statements at the end of a block. @@ -36,33 +36,6 @@ declare_clippy_lint! { "using a return statement like `return expr;` where an expression would suffice" } -declare_clippy_lint! { - /// **What it does:** Checks for `let`-bindings, which are subsequently - /// returned. - /// - /// **Why is this bad?** It is just extraneous code. Remove it to make your code - /// more rusty. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// fn foo() -> String { - /// let x = String::new(); - /// x - /// } - /// ``` - /// instead, use - /// ``` - /// fn foo() -> String { - /// String::new() - /// } - /// ``` - pub LET_AND_RETURN, - style, - "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block" -} - declare_clippy_lint! { /// **What it does:** Checks for unit (`()`) expressions that can be removed. /// @@ -90,7 +63,7 @@ enum RetReplacement { Block, } -declare_lint_pass!(Return => [NEEDLESS_RETURN, LET_AND_RETURN, UNUSED_UNIT]); +declare_lint_pass!(Return => [NEEDLESS_RETURN, UNUSED_UNIT]); impl Return { // Check the final stmt or expr in a block for unnecessary return. @@ -105,7 +78,7 @@ impl Return { } } - // Check a the final expression in a block if it's a return. + // Check the final expression in a block if it's a return. fn check_final_expr( &mut self, cx: &EarlyContext<'_>, @@ -186,54 +159,6 @@ impl Return { }, } } - - // Check for "let x = EXPR; x" - fn check_let_return(cx: &EarlyContext<'_>, block: &ast::Block) { - let mut it = block.stmts.iter(); - - // we need both a let-binding stmt and an expr - if_chain! { - if let Some(retexpr) = it.next_back(); - if let ast::StmtKind::Expr(ref retexpr) = retexpr.kind; - if let Some(stmt) = it.next_back(); - if let ast::StmtKind::Local(ref local) = stmt.kind; - // don't lint in the presence of type inference - if local.ty.is_none(); - if local.attrs.is_empty(); - if let Some(ref initexpr) = local.init; - if let ast::PatKind::Ident(_, ident, _) = local.pat.kind; - if let ast::ExprKind::Path(_, ref path) = retexpr.kind; - if match_path_ast(path, &[&*ident.name.as_str()]); - if !in_external_macro(cx.sess(), initexpr.span); - if !in_external_macro(cx.sess(), retexpr.span); - if !in_external_macro(cx.sess(), local.span); - if !in_macro(local.span); - then { - span_lint_and_then( - cx, - LET_AND_RETURN, - retexpr.span, - "returning the result of a `let` binding from a block", - |err| { - err.span_label(local.span, "unnecessary `let` binding"); - - if let Some(snippet) = snippet_opt(cx, initexpr.span) { - err.multipart_suggestion( - "return the expression directly", - vec![ - (local.span, String::new()), - (retexpr.span, snippet), - ], - Applicability::MachineApplicable, - ); - } else { - err.span_help(initexpr.span, "this expression can be directly returned"); - } - }, - ); - } - } - } } impl EarlyLintPass for Return { @@ -254,7 +179,6 @@ impl EarlyLintPass for Return { } fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { - Self::check_let_return(cx, block); if_chain! { if let Some(ref stmt) = block.stmts.last(); if let ast::StmtKind::Expr(ref expr) = stmt.kind; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index d5d07ccb2eb..bb191f9be92 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1023,7 +1023,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ group: "style", desc: "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block", deprecation: None, - module: "returns", + module: "let_and_return", }, Lint { name: "let_underscore_lock", From 9c205d7b1baa982ae7063d57b18088ecf28df83b Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sat, 6 Jun 2020 21:51:41 +0200 Subject: [PATCH 179/526] Rename let_and_return test for consistency with the lint name --- tests/ui/{let_return.rs => let_and_return.rs} | 0 tests/ui/{let_return.stderr => let_and_return.stderr} | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/ui/{let_return.rs => let_and_return.rs} (100%) rename tests/ui/{let_return.stderr => let_and_return.stderr} (89%) diff --git a/tests/ui/let_return.rs b/tests/ui/let_and_return.rs similarity index 100% rename from tests/ui/let_return.rs rename to tests/ui/let_and_return.rs diff --git a/tests/ui/let_return.stderr b/tests/ui/let_and_return.stderr similarity index 89% rename from tests/ui/let_return.stderr rename to tests/ui/let_and_return.stderr index 128a22c86e3..eacf948b392 100644 --- a/tests/ui/let_return.stderr +++ b/tests/ui/let_and_return.stderr @@ -1,5 +1,5 @@ error: returning the result of a `let` binding from a block - --> $DIR/let_return.rs:7:5 + --> $DIR/let_and_return.rs:7:5 | LL | let x = 5; | ---------- unnecessary `let` binding @@ -14,7 +14,7 @@ LL | 5 | error: returning the result of a `let` binding from a block - --> $DIR/let_return.rs:13:9 + --> $DIR/let_and_return.rs:13:9 | LL | let x = 5; | ---------- unnecessary `let` binding From dac8a3c1ca19d2b5934ecbe2ed79ae6c156fd885 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sun, 7 Jun 2020 00:30:39 +0200 Subject: [PATCH 180/526] let_and_return: do not lint if last statement borrows --- clippy_lints/src/let_and_return.rs | 61 ++++++++++++++++++++++++++- clippy_lints/src/utils/mod.rs | 2 +- tests/ui/let_and_return.rs | 68 ++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/let_and_return.rs b/clippy_lints/src/let_and_return.rs index 8b877f696af..6d3fb317bcf 100644 --- a/clippy_lints/src/let_and_return.rs +++ b/clippy_lints/src/let_and_return.rs @@ -1,8 +1,12 @@ use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Block, ExprKind, PatKind, StmtKind}; +use rustc_hir::def_id::DefId; +use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc_hir::{Block, Expr, ExprKind, PatKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::subst::GenericArgKind; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::{in_macro, match_qpath, snippet_opt, span_lint_and_then}; @@ -49,6 +53,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetReturn { if let PatKind::Binding(.., ident, _) = local.pat.kind; if let ExprKind::Path(qpath) = &retexpr.kind; if match_qpath(qpath, &[&*ident.name.as_str()]); + if !last_statement_borrows(cx, initexpr); if !in_external_macro(cx.sess(), initexpr.span); if !in_external_macro(cx.sess(), retexpr.span); if !in_external_macro(cx.sess(), local.span); @@ -80,3 +85,57 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetReturn { } } } + +fn last_statement_borrows<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + let mut visitor = BorrowVisitor { cx, borrows: false }; + walk_expr(&mut visitor, expr); + visitor.borrows +} + +struct BorrowVisitor<'a, 'tcx> { + cx: &'a LateContext<'a, 'tcx>, + borrows: bool, +} + +impl BorrowVisitor<'_, '_> { + fn fn_def_id(&self, expr: &Expr<'_>) -> Option<DefId> { + match &expr.kind { + ExprKind::MethodCall(..) => self.cx.tables.type_dependent_def_id(expr.hir_id), + ExprKind::Call( + Expr { + kind: ExprKind::Path(qpath), + .. + }, + .., + ) => self.cx.tables.qpath_res(qpath, expr.hir_id).opt_def_id(), + _ => None, + } + } +} + +impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + if self.borrows { + return; + } + + if let Some(def_id) = self.fn_def_id(expr) { + self.borrows = self + .cx + .tcx + .fn_sig(def_id) + .output() + .skip_binder() + .walk() + .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))); + } + + walk_expr(self, expr); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 06638e7187b..39410acea4e 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -400,7 +400,7 @@ pub fn method_calls<'tcx>( /// Matches an `Expr` against a chain of methods, and return the matched `Expr`s. /// /// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`, -/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec` +/// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec` /// containing the `Expr`s for /// `.bar()` and `.baz()` pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<&'a [Expr<'a>]>> { diff --git a/tests/ui/let_and_return.rs b/tests/ui/let_and_return.rs index 23645d48fe7..09614b8c1ad 100644 --- a/tests/ui/let_and_return.rs +++ b/tests/ui/let_and_return.rs @@ -67,4 +67,72 @@ macro_rules! tuple_encode { tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); +mod no_lint_if_stmt_borrows { + mod issue_3792 { + use std::io::{self, BufRead, Stdin}; + + fn read_line() -> String { + let stdin = io::stdin(); + let line = stdin.lock().lines().next().unwrap().unwrap(); + line + } + } + + mod issue_3324 { + use std::cell::RefCell; + use std::rc::{Rc, Weak}; + + fn test(value: Weak<RefCell<Bar>>) -> u32 { + let value = value.upgrade().unwrap(); + let ret = value.borrow().baz(); + ret + } + + struct Bar {} + + impl Bar { + fn new() -> Self { + Bar {} + } + fn baz(&self) -> u32 { + 0 + } + } + + fn main() { + let a = Rc::new(RefCell::new(Bar::new())); + let b = Rc::downgrade(&a); + test(b); + } + } + + mod free_function { + struct Inner; + + struct Foo<'a> { + inner: &'a Inner, + } + + impl Drop for Foo<'_> { + fn drop(&mut self) {} + } + + impl Foo<'_> { + fn value(&self) -> i32 { + 42 + } + } + + fn some_foo(inner: &Inner) -> Foo<'_> { + Foo { inner } + } + + fn test() -> i32 { + let x = Inner {}; + let value = some_foo(&x).value(); + value + } + } +} + fn main() {} From ebfc1da07d2cd1cba87a3df79c5ffbfc0d25618c Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sun, 7 Jun 2020 20:38:28 +0200 Subject: [PATCH 181/526] reversed_empty_ranges: don't lint N..N except in for loop arg --- clippy_lints/src/ranges.rs | 62 +++++++++---------- tests/ui/reversed_empty_ranges_fixable.fixed | 8 +-- tests/ui/reversed_empty_ranges_fixable.rs | 8 +-- tests/ui/reversed_empty_ranges_fixable.stderr | 16 ++--- tests/ui/reversed_empty_ranges_unfixable.rs | 5 +- .../ui/reversed_empty_ranges_unfixable.stderr | 20 +++--- 6 files changed, 52 insertions(+), 67 deletions(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 1eb26d97ed4..45de4d29375 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -241,14 +241,26 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { - fn inside_indexing_expr<'a>(cx: &'a LateContext<'_, '_>, expr: &Expr<'_>) -> Option<&'a Expr<'a>> { - match get_parent_expr(cx, expr) { - parent_expr @ Some(Expr { + fn inside_indexing_expr<'a>(cx: &'a LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + matches!( + get_parent_expr(cx, expr), + Some(Expr { kind: ExprKind::Index(..), .. - }) => parent_expr, - _ => None, + }) + ) + } + + fn is_for_loop_arg(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + let mut cur_expr = expr; + while let Some(parent_expr) = get_parent_expr(cx, cur_expr) { + match higher::for_loop(parent_expr) { + Some((_, args, _)) if args.hir_id == expr.hir_id => return true, + _ => cur_expr = parent_expr, + } } + + false } fn is_empty_range(limits: RangeLimits, ordering: Ordering) -> bool { @@ -267,34 +279,18 @@ fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx); if is_empty_range(limits, ordering); then { - if let Some(parent_expr) = inside_indexing_expr(cx, expr) { - let (reason, outcome) = if ordering == Ordering::Equal { - ("empty", "always yield an empty slice") - } else { - ("reversed", "panic at run-time") - }; - - span_lint_and_then( - cx, - REVERSED_EMPTY_RANGES, - expr.span, - &format!("this range is {} and using it to index a slice will {}", reason, outcome), - |diag| { - if_chain! { - if ordering == Ordering::Equal; - if let ty::Slice(slice_ty) = cx.tables.expr_ty(parent_expr).kind; - then { - diag.span_suggestion( - parent_expr.span, - "if you want an empty slice, use", - format!("[] as &[{}]", slice_ty), - Applicability::MaybeIncorrect - ); - } - } - } - ); - } else { + if inside_indexing_expr(cx, expr) { + // Avoid linting `N..N` as it has proven to be useful, see #5689 and #5628 ... + if ordering != Ordering::Equal { + span_lint( + cx, + REVERSED_EMPTY_RANGES, + expr.span, + "this range is reversed and using it to index a slice will panic at run-time", + ); + } + // ... except in for loop arguments for backwards compatibility with `reverse_range_loop` + } else if ordering != Ordering::Equal || is_for_loop_arg(cx, expr) { span_lint_and_then( cx, REVERSED_EMPTY_RANGES, diff --git a/tests/ui/reversed_empty_ranges_fixable.fixed b/tests/ui/reversed_empty_ranges_fixable.fixed index 332c0427ef6..79e482eec30 100644 --- a/tests/ui/reversed_empty_ranges_fixable.fixed +++ b/tests/ui/reversed_empty_ranges_fixable.fixed @@ -4,8 +4,6 @@ const ANSWER: i32 = 42; fn main() { - let arr = [1, 2, 3, 4, 5]; - // These should be linted: (21..=42).rev().for_each(|x| println!("{}", x)); @@ -14,16 +12,18 @@ fn main() { for _ in (-42..=-21).rev() {} for _ in (21u32..42u32).rev() {} - let _ = &[] as &[i32]; - // These should be ignored as they are not empty ranges: (21..=42).for_each(|x| println!("{}", x)); (21..42).for_each(|x| println!("{}", x)); + let arr = [1, 2, 3, 4, 5]; let _ = &arr[1..=3]; let _ = &arr[1..3]; for _ in 21..=42 {} for _ in 21..42 {} + + // This range is empty but should be ignored, see issue #5689 + let _ = &arr[0..0]; } diff --git a/tests/ui/reversed_empty_ranges_fixable.rs b/tests/ui/reversed_empty_ranges_fixable.rs index 901ec8bcc09..b2e8bf33771 100644 --- a/tests/ui/reversed_empty_ranges_fixable.rs +++ b/tests/ui/reversed_empty_ranges_fixable.rs @@ -4,8 +4,6 @@ const ANSWER: i32 = 42; fn main() { - let arr = [1, 2, 3, 4, 5]; - // These should be linted: (42..=21).for_each(|x| println!("{}", x)); @@ -14,16 +12,18 @@ fn main() { for _ in -21..=-42 {} for _ in 42u32..21u32 {} - let _ = &arr[3..3]; - // These should be ignored as they are not empty ranges: (21..=42).for_each(|x| println!("{}", x)); (21..42).for_each(|x| println!("{}", x)); + let arr = [1, 2, 3, 4, 5]; let _ = &arr[1..=3]; let _ = &arr[1..3]; for _ in 21..=42 {} for _ in 21..42 {} + + // This range is empty but should be ignored, see issue #5689 + let _ = &arr[0..0]; } diff --git a/tests/ui/reversed_empty_ranges_fixable.stderr b/tests/ui/reversed_empty_ranges_fixable.stderr index 9a646fd9939..de83c4f3d63 100644 --- a/tests/ui/reversed_empty_ranges_fixable.stderr +++ b/tests/ui/reversed_empty_ranges_fixable.stderr @@ -1,5 +1,5 @@ error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_fixable.rs:11:5 + --> $DIR/reversed_empty_ranges_fixable.rs:9:5 | LL | (42..=21).for_each(|x| println!("{}", x)); | ^^^^^^^^^ @@ -11,7 +11,7 @@ LL | (21..=42).rev().for_each(|x| println!("{}", x)); | ^^^^^^^^^^^^^^^ error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_fixable.rs:12:13 + --> $DIR/reversed_empty_ranges_fixable.rs:10:13 | LL | let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>(); | ^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::<Ve | ^^^^^^^^^^^^^^^^^^ error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_fixable.rs:14:14 + --> $DIR/reversed_empty_ranges_fixable.rs:12:14 | LL | for _ in -21..=-42 {} | ^^^^^^^^^ @@ -33,7 +33,7 @@ LL | for _ in (-42..=-21).rev() {} | ^^^^^^^^^^^^^^^^^ error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_fixable.rs:15:14 + --> $DIR/reversed_empty_ranges_fixable.rs:13:14 | LL | for _ in 42u32..21u32 {} | ^^^^^^^^^^^^ @@ -43,11 +43,5 @@ help: consider using the following if you are attempting to iterate over this ra LL | for _ in (21u32..42u32).rev() {} | ^^^^^^^^^^^^^^^^^^^^ -error: this range is empty and using it to index a slice will always yield an empty slice - --> $DIR/reversed_empty_ranges_fixable.rs:17:18 - | -LL | let _ = &arr[3..3]; - | ----^^^^- help: if you want an empty slice, use: `[] as &[i32]` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/reversed_empty_ranges_unfixable.rs b/tests/ui/reversed_empty_ranges_unfixable.rs index 561a35625f0..264d3d1e95a 100644 --- a/tests/ui/reversed_empty_ranges_unfixable.rs +++ b/tests/ui/reversed_empty_ranges_unfixable.rs @@ -4,11 +4,12 @@ const ANSWER: i32 = 42; const SOME_NUM: usize = 3; fn main() { - let _ = (42 + 10..42 + 10).map(|x| x / 2).find(|&x| x == 21); - let arr = [1, 2, 3, 4, 5]; let _ = &arr[3usize..=1usize]; let _ = &arr[SOME_NUM..1]; for _ in ANSWER..ANSWER {} + + // Should not be linted, see issue #5689 + let _ = (42 + 10..42 + 10).map(|x| x / 2).find(|&x| x == 21); } diff --git a/tests/ui/reversed_empty_ranges_unfixable.stderr b/tests/ui/reversed_empty_ranges_unfixable.stderr index 240188cbb46..f23d4eb0f9c 100644 --- a/tests/ui/reversed_empty_ranges_unfixable.stderr +++ b/tests/ui/reversed_empty_ranges_unfixable.stderr @@ -1,28 +1,22 @@ -error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_unfixable.rs:7:13 +error: this range is reversed and using it to index a slice will panic at run-time + --> $DIR/reversed_empty_ranges_unfixable.rs:8:18 | -LL | let _ = (42 + 10..42 + 10).map(|x| x / 2).find(|&x| x == 21); - | ^^^^^^^^^^^^^^^^^^ +LL | let _ = &arr[3usize..=1usize]; + | ^^^^^^^^^^^^^^^ | = note: `-D clippy::reversed-empty-ranges` implied by `-D warnings` error: this range is reversed and using it to index a slice will panic at run-time - --> $DIR/reversed_empty_ranges_unfixable.rs:10:18 - | -LL | let _ = &arr[3usize..=1usize]; - | ^^^^^^^^^^^^^^^ - -error: this range is reversed and using it to index a slice will panic at run-time - --> $DIR/reversed_empty_ranges_unfixable.rs:11:18 + --> $DIR/reversed_empty_ranges_unfixable.rs:9:18 | LL | let _ = &arr[SOME_NUM..1]; | ^^^^^^^^^^^ error: this range is empty so it will yield no values - --> $DIR/reversed_empty_ranges_unfixable.rs:13:14 + --> $DIR/reversed_empty_ranges_unfixable.rs:11:14 | LL | for _ in ANSWER..ANSWER {} | ^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors From 7b6dc7b33dc437a59330ef3f5426102ca60fbf51 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad <twingoow@gmail.com> Date: Thu, 19 Mar 2020 14:14:52 +0100 Subject: [PATCH 182/526] add `unnested_or_patterns` lint --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 7 + clippy_lints/src/unnested_or_patterns.rs | 407 +++++++++++++++++ clippy_lints/src/utils/ast_utils.rs | 525 ++++++++++++++++++++++ clippy_lints/src/utils/hir_utils.rs | 10 +- clippy_lints/src/utils/mod.rs | 3 +- src/lintlist/mod.rs | 7 + tests/ui/neg_cmp_op_on_partial_ord.rs | 1 + tests/ui/neg_cmp_op_on_partial_ord.stderr | 8 +- tests/ui/unnested_or_patterns.fixed | 41 ++ tests/ui/unnested_or_patterns.rs | 41 ++ tests/ui/unnested_or_patterns.stderr | 267 +++++++++++ tests/ui/wildcard_enum_match_arm.fixed | 3 +- tests/ui/wildcard_enum_match_arm.rs | 3 +- tests/ui/wildcard_enum_match_arm.stderr | 10 +- 15 files changed, 1314 insertions(+), 20 deletions(-) create mode 100644 clippy_lints/src/unnested_or_patterns.rs create mode 100755 clippy_lints/src/utils/ast_utils.rs create mode 100644 tests/ui/unnested_or_patterns.fixed create mode 100644 tests/ui/unnested_or_patterns.rs create mode 100644 tests/ui/unnested_or_patterns.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index a4a184480fb..adc945a6944 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1683,6 +1683,7 @@ Released 2018-09-13 [`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap [`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern [`unneeded_wildcard_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_wildcard_pattern +[`unnested_or_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns [`unreachable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreachable [`unreadable_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal [`unsafe_derive_deserialize`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_derive_deserialize diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6f8923b2660..9809f953d67 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,5 +1,6 @@ // error-pattern:cargo-clippy +#![feature(bindings_after_at)] #![feature(box_syntax)] #![feature(box_patterns)] #![feature(or_patterns)] @@ -12,6 +13,7 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![feature(crate_visibility_modifier)] #![feature(concat_idents)] +#![feature(drain_filter)] // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) @@ -319,6 +321,7 @@ mod types; mod unicode; mod unnamed_address; mod unnecessary_sort_by; +mod unnested_or_patterns; mod unsafe_removed_from_name; mod unused_io_amount; mod unused_self; @@ -836,6 +839,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &unnamed_address::FN_ADDRESS_COMPARISONS, &unnamed_address::VTABLE_ADDRESS_COMPARISONS, &unnecessary_sort_by::UNNECESSARY_SORT_BY, + &unnested_or_patterns::UNNESTED_OR_PATTERNS, &unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, &unused_io_amount::UNUSED_IO_AMOUNT, &unused_self::UNUSED_SELF, @@ -1073,6 +1077,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(move || box non_expressive_names::NonExpressiveNames { single_char_binding_names_threshold, }); + store.register_early_pass(|| box unnested_or_patterns::UnnestedOrPatterns); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1433,6 +1438,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS), LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS), LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), + LintId::of(&unnested_or_patterns::UNNESTED_OR_PATTERNS), LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), LintId::of(&unwrap::PANICKING_UNWRAP), @@ -1616,6 +1622,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::UNNECESSARY_CAST), LintId::of(&types::VEC_BOX), LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), + LintId::of(&unnested_or_patterns::UNNESTED_OR_PATTERNS), LintId::of(&unwrap::UNNECESSARY_UNWRAP), LintId::of(&useless_conversion::USELESS_CONVERSION), LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO), diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs new file mode 100644 index 00000000000..2723af03c0b --- /dev/null +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -0,0 +1,407 @@ +#![allow(clippy::wildcard_imports, clippy::enum_glob_use)] + +use crate::utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path}; +use crate::utils::{over, span_lint_and_then}; +use rustc_ast::ast::{self, Pat, PatKind, PatKind::*, DUMMY_NODE_ID}; +use rustc_ast::mut_visit::*; +use rustc_ast::ptr::P; +use rustc_ast_pretty::pprust; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::DUMMY_SP; + +use std::cell::Cell; +use std::mem; + +declare_clippy_lint! { + /// **What it does:** + /// + /// Checks for unnested or-patterns, e.g., `Some(0) | Some(2)` and + /// suggests replacing the pattern with a nested one, `Some(0 | 2)`. + /// + /// Another way to think of this is that it rewrites patterns in + /// *disjunctive normal form (DNF)* into *conjunctive normal form (CNF)*. + /// + /// **Why is this bad?** + /// + /// In the example above, `Some` is repeated, which unncessarily complicates the pattern. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// fn main() { + /// if let Some(0) | Some(2) = Some(0) {} + /// } + /// ``` + /// Use instead: + /// ```rust + /// #![feature(or_patterns)] + /// + /// fn main() { + /// if let Some(0 | 2) = Some(0) {} + /// } + /// ``` + pub UNNESTED_OR_PATTERNS, + complexity, + "unnested or-patterns, e.g., `Foo(Bar) | Foo(Baz) instead of `Foo(Bar | Baz)`" +} + +declare_lint_pass!(UnnestedOrPatterns => [UNNESTED_OR_PATTERNS]); + +impl EarlyLintPass for UnnestedOrPatterns { + fn check_arm(&mut self, cx: &EarlyContext<'_>, a: &ast::Arm) { + lint_unnested_or_patterns(cx, &a.pat); + } + + fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { + if let ast::ExprKind::Let(pat, _) = &e.kind { + lint_unnested_or_patterns(cx, pat); + } + } + + fn check_param(&mut self, cx: &EarlyContext<'_>, p: &ast::Param) { + lint_unnested_or_patterns(cx, &p.pat); + } + + fn check_local(&mut self, cx: &EarlyContext<'_>, l: &ast::Local) { + lint_unnested_or_patterns(cx, &l.pat); + } +} + +fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) { + if !cx.sess.opts.unstable_features.is_nightly_build() { + // User cannot do `#![feature(or_patterns)]`, so bail. + return; + } + + if let Ident(.., None) | Lit(_) | Wild | Path(..) | Range(..) | Rest | MacCall(_) = pat.kind { + // This is a leaf pattern, so cloning is unprofitable. + return; + } + + let mut pat = P(pat.clone()); + + // Nix all the paren patterns everywhere so that they aren't in our way. + remove_all_parens(&mut pat); + + // Transform all unnested or-patterns into nested ones, and if there were none, quit. + if !unnest_or_patterns(&mut pat) { + return; + } + + span_lint_and_then(cx, UNNESTED_OR_PATTERNS, pat.span, "unnested or-patterns", |db| { + insert_necessary_parens(&mut pat); + db.span_suggestion_verbose( + pat.span, + "nest the patterns", + pprust::pat_to_string(&pat), + Applicability::MachineApplicable, + ); + }); +} + +/// Remove all `(p)` patterns in `pat`. +fn remove_all_parens(pat: &mut P<Pat>) { + struct Visitor; + impl MutVisitor for Visitor { + fn visit_pat(&mut self, pat: &mut P<Pat>) { + noop_visit_pat(pat, self); + let inner = match &mut pat.kind { + Paren(i) => mem::replace(&mut i.kind, Wild), + _ => return, + }; + pat.kind = inner; + } + } + Visitor.visit_pat(pat); +} + +/// Insert parens where necessary according to Rust's precedence rules for patterns. +fn insert_necessary_parens(pat: &mut P<Pat>) { + struct Visitor; + impl MutVisitor for Visitor { + fn visit_pat(&mut self, pat: &mut P<Pat>) { + use ast::{BindingMode::*, Mutability::*}; + noop_visit_pat(pat, self); + let target = match &mut pat.kind { + // `i @ a | b`, `box a | b`, and `& mut? a | b`. + Ident(.., Some(p)) | Box(p) | Ref(p, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p, + Ref(p, Not) if matches!(p.kind, Ident(ByValue(Mut), ..)) => p, // `&(mut x)` + _ => return, + }; + target.kind = Paren(P(take_pat(target))); + } + } + Visitor.visit_pat(pat); +} + +/// Unnest or-patterns `p0 | ... | p1` in the pattern `pat`. +/// For example, this would transform `Some(0) | FOO | Some(2)` into `Some(0 | 2) | FOO`. +fn unnest_or_patterns(pat: &mut P<Pat>) -> bool { + struct Visitor { + changed: bool, + } + impl MutVisitor for Visitor { + fn visit_pat(&mut self, p: &mut P<Pat>) { + // This is a bottom up transformation, so recurse first. + noop_visit_pat(p, self); + + // Don't have an or-pattern? Just quit early on. + let alternatives = match &mut p.kind { + Or(ps) => ps, + _ => return, + }; + + // Collapse or-patterns directly nested in or-patterns. + let mut idx = 0; + let mut this_level_changed = false; + while idx < alternatives.len() { + let inner = if let Or(ps) = &mut alternatives[idx].kind { + mem::take(ps) + } else { + idx += 1; + continue; + }; + this_level_changed = true; + alternatives.splice(idx..=idx, inner); + } + + // Focus on `p_n` and then try to transform all `p_i` where `i > n`. + let mut focus_idx = 0; + while focus_idx < alternatives.len() { + this_level_changed |= transform_with_focus_on_idx(alternatives, focus_idx); + focus_idx += 1; + } + self.changed |= this_level_changed; + + // Deal with `Some(Some(0)) | Some(Some(1))`. + if this_level_changed { + noop_visit_pat(p, self); + } + } + } + + let mut visitor = Visitor { changed: false }; + visitor.visit_pat(pat); + visitor.changed +} + +/// Match `$scrutinee` against `$pat` and extract `$then` from it. +/// Panics if there is no match. +macro_rules! always_pat { + ($scrutinee:expr, $pat:pat => $then:expr) => { + match $scrutinee { + $pat => $then, + _ => unreachable!(), + } + }; +} + +/// Focus on `focus_idx` in `alternatives`, +/// attempting to extend it with elements of the same constructor `C` +/// in `alternatives[focus_idx + 1..]`. +fn transform_with_focus_on_idx(alternatives: &mut Vec<P<Pat>>, focus_idx: usize) -> bool { + // Extract the kind; we'll need to make some changes in it. + let mut focus_kind = mem::replace(&mut alternatives[focus_idx].kind, PatKind::Wild); + // We'll focus on `alternatives[focus_idx]`, + // so we're draining from `alternatives[focus_idx + 1..]`. + let start = focus_idx + 1; + + // We're trying to find whatever kind (~"constructor") we found in `alternatives[start..]`. + let changed = match &mut focus_kind { + // These pattern forms are "leafs" and do not have sub-patterns. + // Therefore they are not some form of constructor `C`, + // with which a pattern `C(P0)` may be formed, + // which we would want to join with other `C(Pj)`s. + Ident(.., None) | Lit(_) | Wild | Path(..) | Range(..) | Rest | MacCall(_) + // Dealt with elsewhere. + | Or(_) | Paren(_) => false, + // Transform `box x | ... | box y` into `box (x | y)`. + // + // The cases below until `Slice(...)` deal *singleton* products. + // These patterns have the shape `C(p)`, and not e.g., `C(p0, ..., pn)`. + Box(target) => extend_with_matching( + target, start, alternatives, + |k| matches!(k, Box(_)), + |k| always_pat!(k, Box(p) => p), + ), + // Transform `&m x | ... | &m y` into `&m (x, y)`. + Ref(target, m1) => extend_with_matching( + target, start, alternatives, + |k| matches!(k, Ref(_, m2) if m1 == m2), // Mutabilities must match. + |k| always_pat!(k, Ref(p, _) => p), + ), + // Transform `b @ p0 | ... b @ p1` into `b @ (p0 | p1)`. + Ident(b1, i1, Some(target)) => extend_with_matching( + target, start, alternatives, + // Binding names must match. + |k| matches!(k, Ident(b2, i2, Some(_)) if b1 == b2 && eq_id(*i1, *i2)), + |k| always_pat!(k, Ident(_, _, Some(p)) => p), + ), + // Transform `[pre, x, post] | ... | [pre, y, post]` into `[pre, x | y, post]`. + Slice(ps1) => extend_with_matching_product( + ps1, start, alternatives, + |k, ps1, idx| matches!(k, Slice(ps2) if eq_pre_post(ps1, ps2, idx)), + |k| always_pat!(k, Slice(ps) => ps), + ), + // Transform `(pre, x, post) | ... | (pre, y, post)` into `(pre, x | y, post]`. + Tuple(ps1) => extend_with_matching_product( + ps1, start, alternatives, + |k, ps1, idx| matches!(k, Tuple(ps2) if eq_pre_post(ps1, ps2, idx)), + |k| always_pat!(k, Tuple(ps) => ps), + ), + // Transform `S(pre, x, post) | ... | S(pre, y, post)` into `S(pre, x | y, post]`. + TupleStruct(path1, ps1) => extend_with_matching_product( + ps1, start, alternatives, + |k, ps1, idx| matches!( + k, + TupleStruct(path2, ps2) if eq_path(path1, path2) && eq_pre_post(ps1, ps2, idx) + ), + |k| always_pat!(k, TupleStruct(_, ps) => ps), + ), + // Transform a record pattern `S { fp_0, ..., fp_n }`. + Struct(path1, fps1, rest1) => extend_with_struct_pat(path1, fps1, *rest1, start, alternatives), + }; + + alternatives[focus_idx].kind = focus_kind; + changed +} + +/// Here we focusing on a record pattern `S { fp_0, ..., fp_n }`. +/// In particular, for a record pattern, the order in which the field patterns is irrelevant. +/// So when we fixate on some `ident_k: pat_k`, we try to find `ident_k` in the other pattern +/// and check that all `fp_i` where `i ∈ ((0...n) \ k)` between two patterns are equal. +fn extend_with_struct_pat( + path1: &ast::Path, + fps1: &mut Vec<ast::FieldPat>, + rest1: bool, + start: usize, + alternatives: &mut Vec<P<Pat>>, +) -> bool { + (0..fps1.len()).any(|idx| { + let pos_in_2 = Cell::new(None); // The element `k`. + let tail_or = drain_matching( + start, + alternatives, + |k| { + matches!(k, Struct(path2, fps2, rest2) + if rest1 == *rest2 // If one struct pattern has `..` so must the other. + && eq_path(path1, path2) + && fps1.len() == fps2.len() + && fps1.iter().enumerate().all(|(idx_1, fp1)| { + if idx_1 == idx { + // In the case of `k`, we merely require identical field names + // so that we will transform into `ident_k: p1_k | p2_k`. + let pos = fps2.iter().position(|fp2| eq_id(fp1.ident, fp2.ident)); + pos_in_2.set(pos); + pos.is_some() + } else { + fps2.iter().any(|fp2| eq_field_pat(fp1, fp2)) + } + })) + }, + // Extract `p2_k`. + |k| always_pat!(k, Struct(_, mut fps, _) => fps.swap_remove(pos_in_2.take().unwrap()).pat), + ); + extend_with_tail_or(&mut fps1[idx].pat, tail_or) + }) +} + +/// Like `extend_with_matching` but for products with > 1 factor, e.g., `C(p_0, ..., p_n)`. +/// Here, the idea is that we fixate on some `p_k` in `C`, +/// allowing it to vary between two `targets` and `ps2` (returned by `extract`), +/// while also requiring `ps1[..n] ~ ps2[..n]` (pre) and `ps1[n + 1..] ~ ps2[n + 1..]` (post), +/// where `~` denotes semantic equality. +fn extend_with_matching_product( + targets: &mut Vec<P<Pat>>, + start: usize, + alternatives: &mut Vec<P<Pat>>, + predicate: impl Fn(&PatKind, &[P<Pat>], usize) -> bool, + extract: impl Fn(PatKind) -> Vec<P<Pat>>, +) -> bool { + (0..targets.len()).any(|idx| { + let tail_or = drain_matching( + start, + alternatives, + |k| predicate(k, targets, idx), + |k| extract(k).swap_remove(idx), + ); + extend_with_tail_or(&mut targets[idx], tail_or) + }) +} + +/// Extract the pattern from the given one and replace it with `Wild`. +/// This is meant for temporarily swapping out the pattern for manipulation. +fn take_pat(from: &mut Pat) -> Pat { + let dummy = Pat { + id: DUMMY_NODE_ID, + kind: Wild, + span: DUMMY_SP, + }; + mem::replace(from, dummy) +} + +/// Extend `target` as an or-pattern with the alternatives +/// in `tail_or` if there are any and return if there were. +fn extend_with_tail_or(target: &mut Pat, tail_or: Vec<P<Pat>>) -> bool { + fn extend(target: &mut Pat, mut tail_or: Vec<P<Pat>>) { + match target { + // On an existing or-pattern in the target, append to it. + Pat { kind: Or(ps), .. } => ps.append(&mut tail_or), + // Otherwise convert the target to an or-pattern. + target => { + let mut init_or = vec![P(take_pat(target))]; + init_or.append(&mut tail_or); + target.kind = Or(init_or); + }, + } + } + + let changed = !tail_or.is_empty(); + if changed { + // Extend the target. + extend(target, tail_or); + } + changed +} + +// Extract all inner patterns in `alternatives` matching our `predicate`. +// Only elements beginning with `start` are considered for extraction. +fn drain_matching( + start: usize, + alternatives: &mut Vec<P<Pat>>, + predicate: impl Fn(&PatKind) -> bool, + extract: impl Fn(PatKind) -> P<Pat>, +) -> Vec<P<Pat>> { + let mut tail_or = vec![]; + let mut idx = 0; + for pat in alternatives.drain_filter(|p| { + // Check if we should extract, but only if `idx >= start`. + idx += 1; + idx > start && predicate(&p.kind) + }) { + tail_or.push(extract(pat.into_inner().kind)); + } + tail_or +} + +fn extend_with_matching( + target: &mut Pat, + start: usize, + alternatives: &mut Vec<P<Pat>>, + predicate: impl Fn(&PatKind) -> bool, + extract: impl Fn(PatKind) -> P<Pat>, +) -> bool { + extend_with_tail_or(target, drain_matching(start, alternatives, predicate, extract)) +} + +/// Are the patterns in `ps1` and `ps2` equal save for `ps1[idx]` compared to `ps2[idx]`? +fn eq_pre_post(ps1: &[P<Pat>], ps2: &[P<Pat>], idx: usize) -> bool { + ps1[idx].is_rest() == ps2[idx].is_rest() // Avoid `[x, ..] | [x, 0]` => `[x, .. | 0]`. + && ps1.len() == ps2.len() + && over(&ps1[..idx], &ps2[..idx], |l, r| eq_pat(l, r)) + && over(&ps1[idx + 1..], &ps2[idx + 1..], |l, r| eq_pat(l, r)) +} diff --git a/clippy_lints/src/utils/ast_utils.rs b/clippy_lints/src/utils/ast_utils.rs new file mode 100755 index 00000000000..69a7b6c051e --- /dev/null +++ b/clippy_lints/src/utils/ast_utils.rs @@ -0,0 +1,525 @@ +//! Utilities for manipulating and extracting information from `rustc_ast::ast`. +//! +//! - The `eq_foobar` functions test for semantic equality but ignores `NodeId`s and `Span`s. + +#![allow(clippy::similar_names, clippy::wildcard_imports, clippy::enum_glob_use)] + +use crate::utils::{both, over}; +use rustc_ast::ast::{self, *}; +use rustc_ast::ptr::P; +use std::mem; + +/// Checks if each element in the first slice is contained within the latter as per `eq_fn`. +pub fn unordered_over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool { + left.len() == right.len() && left.iter().all(|l| right.iter().any(|r| eq_fn(l, r))) +} + +pub fn eq_id(l: Ident, r: Ident) -> bool { + l.name == r.name +} + +pub fn eq_pat(l: &Pat, r: &Pat) -> bool { + use PatKind::*; + match (&l.kind, &r.kind) { + (Paren(l), _) => eq_pat(l, r), + (_, Paren(r)) => eq_pat(l, r), + (Wild, Wild) | (Rest, Rest) => true, + (Lit(l), Lit(r)) => eq_expr(l, r), + (Ident(b1, i1, s1), Ident(b2, i2, s2)) => b1 == b2 && eq_id(*i1, *i2) && both(s1, s2, |l, r| eq_pat(l, r)), + (Range(lf, lt, le), Range(rf, rt, re)) => { + eq_expr_opt(lf, rf) && eq_expr_opt(lt, rt) && eq_range_end(&le.node, &re.node) + }, + (Box(l), Box(r)) + | (Ref(l, Mutability::Not), Ref(r, Mutability::Not)) + | (Ref(l, Mutability::Mut), Ref(r, Mutability::Mut)) => eq_pat(l, r), + (Tuple(l), Tuple(r)) | (Slice(l), Slice(r)) => over(l, r, |l, r| eq_pat(l, r)), + (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp), + (TupleStruct(lp, lfs), TupleStruct(rp, rfs)) => eq_path(lp, rp) && over(lfs, rfs, |l, r| eq_pat(l, r)), + (Struct(lp, lfs, lr), Struct(rp, rfs, rr)) => { + lr == rr && eq_path(lp, rp) && unordered_over(lfs, rfs, |lf, rf| eq_field_pat(lf, rf)) + }, + (Or(ls), Or(rs)) => unordered_over(ls, rs, |l, r| eq_pat(l, r)), + (MacCall(l), MacCall(r)) => eq_mac_call(l, r), + _ => false, + } +} + +pub fn eq_range_end(l: &RangeEnd, r: &RangeEnd) -> bool { + match (l, r) { + (RangeEnd::Excluded, RangeEnd::Excluded) => true, + (RangeEnd::Included(l), RangeEnd::Included(r)) => { + matches!(l, RangeSyntax::DotDotEq) == matches!(r, RangeSyntax::DotDotEq) + }, + _ => false, + } +} + +pub fn eq_field_pat(l: &FieldPat, r: &FieldPat) -> bool { + l.is_placeholder == r.is_placeholder + && eq_id(l.ident, r.ident) + && eq_pat(&l.pat, &r.pat) + && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) +} + +pub fn eq_qself(l: &QSelf, r: &QSelf) -> bool { + l.position == r.position && eq_ty(&l.ty, &r.ty) +} + +pub fn eq_path(l: &Path, r: &Path) -> bool { + over(&l.segments, &r.segments, |l, r| eq_path_seg(l, r)) +} + +pub fn eq_path_seg(l: &PathSegment, r: &PathSegment) -> bool { + eq_id(l.ident, r.ident) && both(&l.args, &r.args, |l, r| eq_generic_args(l, r)) +} + +pub fn eq_generic_args(l: &GenericArgs, r: &GenericArgs) -> bool { + match (l, r) { + (GenericArgs::AngleBracketed(l), GenericArgs::AngleBracketed(r)) => { + over(&l.args, &r.args, |l, r| eq_angle_arg(l, r)) + }, + (GenericArgs::Parenthesized(l), GenericArgs::Parenthesized(r)) => { + over(&l.inputs, &r.inputs, |l, r| eq_ty(l, r)) && eq_fn_ret_ty(&l.output, &r.output) + }, + _ => false, + } +} + +pub fn eq_angle_arg(l: &AngleBracketedArg, r: &AngleBracketedArg) -> bool { + match (l, r) { + (AngleBracketedArg::Arg(l), AngleBracketedArg::Arg(r)) => eq_generic_arg(l, r), + (AngleBracketedArg::Constraint(l), AngleBracketedArg::Constraint(r)) => eq_assoc_constraint(l, r), + _ => false, + } +} + +pub fn eq_generic_arg(l: &GenericArg, r: &GenericArg) -> bool { + match (l, r) { + (GenericArg::Lifetime(l), GenericArg::Lifetime(r)) => eq_id(l.ident, r.ident), + (GenericArg::Type(l), GenericArg::Type(r)) => eq_ty(l, r), + (GenericArg::Const(l), GenericArg::Const(r)) => eq_expr(&l.value, &r.value), + _ => false, + } +} + +pub fn eq_expr_opt(l: &Option<P<Expr>>, r: &Option<P<Expr>>) -> bool { + both(l, r, |l, r| eq_expr(l, r)) +} + +pub fn eq_expr(l: &Expr, r: &Expr) -> bool { + use ExprKind::*; + if !over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) { + return false; + } + match (&l.kind, &r.kind) { + (Paren(l), _) => eq_expr(l, r), + (_, Paren(r)) => eq_expr(l, r), + (Err, Err) => true, + (Box(l), Box(r)) | (Try(l), Try(r)) | (Await(l), Await(r)) => eq_expr(l, r), + (Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)), + (Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value), + (Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)), + (MethodCall(lc, la), MethodCall(rc, ra)) => eq_path_seg(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)), + (Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr), + (Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r), + (Lit(l), Lit(r)) => l.kind == r.kind, + (Cast(l, lt), Cast(r, rt)) | (Type(l, lt), Type(r, rt)) => eq_expr(l, r) && eq_ty(lt, rt), + (Let(lp, le), Let(rp, re)) => eq_pat(lp, rp) && eq_expr(le, re), + (If(lc, lt, le), If(rc, rt, re)) => eq_expr(lc, rc) && eq_block(lt, rt) && eq_expr_opt(le, re), + (While(lc, lt, ll), While(rc, rt, rl)) => eq_label(ll, rl) && eq_expr(lc, rc) && eq_block(lt, rt), + (ForLoop(lp, li, lt, ll), ForLoop(rp, ri, rt, rl)) => { + eq_label(ll, rl) && eq_pat(lp, rp) && eq_expr(li, ri) && eq_block(lt, rt) + }, + (Loop(lt, ll), Loop(rt, rl)) => eq_label(ll, rl) && eq_block(lt, rt), + (Block(lb, ll), Block(rb, rl)) => eq_label(ll, rl) && eq_block(lb, rb), + (TryBlock(l), TryBlock(r)) => eq_block(l, r), + (Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l, r), + (Break(ll, le), Break(rl, re)) => eq_label(ll, rl) && eq_expr_opt(le, re), + (Continue(ll), Continue(rl)) => eq_label(ll, rl), + (Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2), Index(r1, r2)) => eq_expr(l1, r1) && eq_expr(l2, r2), + (AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv), + (Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp), + (Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, |l, r| eq_arm(l, r)), + (Closure(lc, la, lm, lf, lb, _), Closure(rc, ra, rm, rf, rb, _)) => { + lc == rc && la.is_async() == ra.is_async() && lm == rm && eq_fn_decl(lf, rf) && eq_expr(lb, rb) + }, + (Async(lc, _, lb), Async(rc, _, rb)) => lc == rc && eq_block(lb, rb), + (Range(lf, lt, ll), Range(rf, rt, rl)) => ll == rl && eq_expr_opt(lf, rf) && eq_expr_opt(lt, rt), + (AddrOf(lbk, lm, le), AddrOf(rbk, rm, re)) => lbk == rbk && lm == rm && eq_expr(le, re), + (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp), + (MacCall(l), MacCall(r)) => eq_mac_call(l, r), + (Struct(lp, lfs, lb), Struct(rp, rfs, rb)) => { + eq_path(lp, rp) && eq_expr_opt(lb, rb) && unordered_over(lfs, rfs, |l, r| eq_field(l, r)) + }, + _ => false, + } +} + +pub fn eq_field(l: &Field, r: &Field) -> bool { + l.is_placeholder == r.is_placeholder + && eq_id(l.ident, r.ident) + && eq_expr(&l.expr, &r.expr) + && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) +} + +pub fn eq_arm(l: &Arm, r: &Arm) -> bool { + l.is_placeholder == r.is_placeholder + && eq_pat(&l.pat, &r.pat) + && eq_expr(&l.body, &r.body) + && eq_expr_opt(&l.guard, &r.guard) + && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) +} + +pub fn eq_label(l: &Option<Label>, r: &Option<Label>) -> bool { + both(l, r, |l, r| eq_id(l.ident, r.ident)) +} + +pub fn eq_block(l: &Block, r: &Block) -> bool { + l.rules == r.rules && over(&l.stmts, &r.stmts, |l, r| eq_stmt(l, r)) +} + +pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool { + use StmtKind::*; + match (&l.kind, &r.kind) { + (Local(l), Local(r)) => { + eq_pat(&l.pat, &r.pat) + && both(&l.ty, &r.ty, |l, r| eq_ty(l, r)) + && eq_expr_opt(&l.init, &r.init) + && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) + }, + (Item(l), Item(r)) => eq_item(l, r, eq_item_kind), + (Expr(l), Expr(r)) | (Semi(l), Semi(r)) => eq_expr(l, r), + (Empty, Empty) => true, + (MacCall(l), MacCall(r)) => l.1 == r.1 && eq_mac_call(&l.0, &r.0) && over(&l.2, &r.2, |l, r| eq_attr(l, r)), + _ => false, + } +} + +pub fn eq_item<K>(l: &Item<K>, r: &Item<K>, mut eq_kind: impl FnMut(&K, &K) -> bool) -> bool { + eq_id(l.ident, r.ident) + && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) + && eq_vis(&l.vis, &r.vis) + && eq_kind(&l.kind, &r.kind) +} + +pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { + use ItemKind::*; + match (l, r) { + (ExternCrate(l), ExternCrate(r)) => l == r, + (Use(l), Use(r)) => eq_use_tree(l, r), + (Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Fn(ld, lf, lg, lb), Fn(rd, rf, rg, rb)) => { + eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) + }, + (Mod(l), Mod(r)) => l.inline == r.inline && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_item_kind)), + (ForeignMod(l), ForeignMod(r)) => { + both(&l.abi, &r.abi, |l, r| eq_str_lit(l, r)) + && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind)) + }, + (TyAlias(ld, lg, lb, lt), TyAlias(rd, rg, rb, rt)) => { + eq_defaultness(*ld, *rd) + && eq_generics(lg, rg) + && over(lb, rb, |l, r| eq_generic_bound(l, r)) + && both(lt, rt, |l, r| eq_ty(l, r)) + }, + (Enum(le, lg), Enum(re, rg)) => { + over(&le.variants, &re.variants, |l, r| eq_variant(l, r)) && eq_generics(lg, rg) + }, + (Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => { + eq_variant_data(lv, rv) && eq_generics(lg, rg) + }, + (Trait(la, lu, lg, lb, li), Trait(ra, ru, rg, rb, ri)) => { + la == ra + && matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No) + && eq_generics(lg, rg) + && over(lb, rb, |l, r| eq_generic_bound(l, r)) + && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind)) + }, + (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, |l, r| eq_generic_bound(l, r)), + ( + Impl { + unsafety: lu, + polarity: lp, + defaultness: ld, + constness: lc, + generics: lg, + of_trait: lot, + self_ty: lst, + items: li, + }, + Impl { + unsafety: ru, + polarity: rp, + defaultness: rd, + constness: rc, + generics: rg, + of_trait: rot, + self_ty: rst, + items: ri, + }, + ) => { + matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No) + && matches!(lp, ImplPolarity::Positive) == matches!(rp, ImplPolarity::Positive) + && eq_defaultness(*ld, *rd) + && matches!(lc, ast::Const::No) == matches!(rc, ast::Const::No) + && eq_generics(lg, rg) + && both(lot, rot, |l, r| eq_path(&l.path, &r.path)) + && eq_ty(lst, rst) + && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind)) + }, + (MacCall(l), MacCall(r)) => eq_mac_call(l, r), + (MacroDef(l), MacroDef(r)) => l.macro_rules == r.macro_rules && eq_mac_args(&l.body, &r.body), + _ => false, + } +} + +pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { + use ForeignItemKind::*; + match (l, r) { + (Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Fn(ld, lf, lg, lb), Fn(rd, rf, rg, rb)) => { + eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) + }, + (TyAlias(ld, lg, lb, lt), TyAlias(rd, rg, rb, rt)) => { + eq_defaultness(*ld, *rd) + && eq_generics(lg, rg) + && over(lb, rb, |l, r| eq_generic_bound(l, r)) + && both(lt, rt, |l, r| eq_ty(l, r)) + }, + (MacCall(l), MacCall(r)) => eq_mac_call(l, r), + _ => false, + } +} + +pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { + use AssocItemKind::*; + match (l, r) { + (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Fn(ld, lf, lg, lb), Fn(rd, rf, rg, rb)) => { + eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) + }, + (TyAlias(ld, lg, lb, lt), TyAlias(rd, rg, rb, rt)) => { + eq_defaultness(*ld, *rd) + && eq_generics(lg, rg) + && over(lb, rb, |l, r| eq_generic_bound(l, r)) + && both(lt, rt, |l, r| eq_ty(l, r)) + }, + (MacCall(l), MacCall(r)) => eq_mac_call(l, r), + _ => false, + } +} + +pub fn eq_variant(l: &Variant, r: &Variant) -> bool { + l.is_placeholder == r.is_placeholder + && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) + && eq_vis(&l.vis, &r.vis) + && eq_id(l.ident, r.ident) + && eq_variant_data(&l.data, &r.data) + && both(&l.disr_expr, &r.disr_expr, |l, r| eq_expr(&l.value, &r.value)) +} + +pub fn eq_variant_data(l: &VariantData, r: &VariantData) -> bool { + use VariantData::*; + match (l, r) { + (Unit(_), Unit(_)) => true, + (Struct(l, _), Struct(r, _)) | (Tuple(l, _), Tuple(r, _)) => over(l, r, |l, r| eq_struct_field(l, r)), + _ => false, + } +} + +pub fn eq_struct_field(l: &StructField, r: &StructField) -> bool { + l.is_placeholder == r.is_placeholder + && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) + && eq_vis(&l.vis, &r.vis) + && both(&l.ident, &r.ident, |l, r| eq_id(*l, *r)) + && eq_ty(&l.ty, &r.ty) +} + +pub fn eq_fn_sig(l: &FnSig, r: &FnSig) -> bool { + eq_fn_decl(&l.decl, &r.decl) && eq_fn_header(&l.header, &r.header) +} + +pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool { + matches!(l.unsafety, Unsafe::No) == matches!(r.unsafety, Unsafe::No) + && l.asyncness.is_async() == r.asyncness.is_async() + && matches!(l.constness, Const::No) == matches!(r.constness, Const::No) + && eq_ext(&l.ext, &r.ext) +} + +pub fn eq_generics(l: &Generics, r: &Generics) -> bool { + over(&l.params, &r.params, |l, r| eq_generic_param(l, r)) + && over(&l.where_clause.predicates, &r.where_clause.predicates, |l, r| { + eq_where_predicate(l, r) + }) +} + +pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { + use WherePredicate::*; + match (l, r) { + (BoundPredicate(l), BoundPredicate(r)) => { + over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { + eq_generic_param(l, r) + }) && eq_ty(&l.bounded_ty, &r.bounded_ty) + && over(&l.bounds, &r.bounds, |l, r| eq_generic_bound(l, r)) + }, + (RegionPredicate(l), RegionPredicate(r)) => { + eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, |l, r| eq_generic_bound(l, r)) + }, + (EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty), + _ => false, + } +} + +pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool { + eq_path(&l.prefix, &r.prefix) && eq_use_tree_kind(&l.kind, &r.kind) +} + +pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool { + use UseTreeKind::*; + match (l, r) { + (Glob, Glob) => true, + (Simple(l, _, _), Simple(r, _, _)) => both(l, r, |l, r| eq_id(*l, *r)), + (Nested(l), Nested(r)) => over(l, r, |(l, _), (r, _)| eq_use_tree(l, r)), + _ => false, + } +} + +pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool { + match (l, r) { + (Defaultness::Final, Defaultness::Final) | (Defaultness::Default(_), Defaultness::Default(_)) => true, + _ => false, + } +} + +pub fn eq_vis(l: &Visibility, r: &Visibility) -> bool { + use VisibilityKind::*; + match (&l.node, &r.node) { + (Public, Public) | (Inherited, Inherited) | (Crate(_), Crate(_)) => true, + (Restricted { path: l, .. }, Restricted { path: r, .. }) => eq_path(l, r), + _ => false, + } +} + +pub fn eq_fn_decl(l: &FnDecl, r: &FnDecl) -> bool { + eq_fn_ret_ty(&l.output, &r.output) + && over(&l.inputs, &r.inputs, |l, r| { + l.is_placeholder == r.is_placeholder + && eq_pat(&l.pat, &r.pat) + && eq_ty(&l.ty, &r.ty) + && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) + }) +} + +pub fn eq_fn_ret_ty(l: &FnRetTy, r: &FnRetTy) -> bool { + match (l, r) { + (FnRetTy::Default(_), FnRetTy::Default(_)) => true, + (FnRetTy::Ty(l), FnRetTy::Ty(r)) => eq_ty(l, r), + _ => false, + } +} + +pub fn eq_ty(l: &Ty, r: &Ty) -> bool { + use TyKind::*; + match (&l.kind, &r.kind) { + (Paren(l), _) => eq_ty(l, r), + (_, Paren(r)) => eq_ty(l, r), + (Never, Never) | (Infer, Infer) | (ImplicitSelf, ImplicitSelf) | (Err, Err) | (CVarArgs, CVarArgs) => true, + (Slice(l), Slice(r)) => eq_ty(l, r), + (Array(le, ls), Array(re, rs)) => eq_ty(le, re) && eq_expr(&ls.value, &rs.value), + (Ptr(l), Ptr(r)) => l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty), + (Rptr(ll, l), Rptr(rl, r)) => { + both(ll, rl, |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) + }, + (BareFn(l), BareFn(r)) => { + l.unsafety == r.unsafety + && eq_ext(&l.ext, &r.ext) + && over(&l.generic_params, &r.generic_params, |l, r| eq_generic_param(l, r)) + && eq_fn_decl(&l.decl, &r.decl) + }, + (Tup(l), Tup(r)) => over(l, r, |l, r| eq_ty(l, r)), + (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp), + (TraitObject(lg, ls), TraitObject(rg, rs)) => ls == rs && over(lg, rg, |l, r| eq_generic_bound(l, r)), + (ImplTrait(_, lg), ImplTrait(_, rg)) => over(lg, rg, |l, r| eq_generic_bound(l, r)), + (Typeof(l), Typeof(r)) => eq_expr(&l.value, &r.value), + (MacCall(l), MacCall(r)) => eq_mac_call(l, r), + _ => false, + } +} + +pub fn eq_ext(l: &Extern, r: &Extern) -> bool { + use Extern::*; + match (l, r) { + (None, None) | (Implicit, Implicit) => true, + (Explicit(l), Explicit(r)) => eq_str_lit(l, r), + _ => false, + } +} + +pub fn eq_str_lit(l: &StrLit, r: &StrLit) -> bool { + l.style == r.style && l.symbol == r.symbol && l.suffix == r.suffix +} + +pub fn eq_poly_ref_trait(l: &PolyTraitRef, r: &PolyTraitRef) -> bool { + eq_path(&l.trait_ref.path, &r.trait_ref.path) + && over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { + eq_generic_param(l, r) + }) +} + +pub fn eq_generic_param(l: &GenericParam, r: &GenericParam) -> bool { + use GenericParamKind::*; + l.is_placeholder == r.is_placeholder + && eq_id(l.ident, r.ident) + && over(&l.bounds, &r.bounds, |l, r| eq_generic_bound(l, r)) + && match (&l.kind, &r.kind) { + (Lifetime, Lifetime) => true, + (Type { default: l }, Type { default: r }) => both(l, r, |l, r| eq_ty(l, r)), + (Const { ty: l }, Const { ty: r }) => eq_ty(l, r), + _ => false, + } + && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) +} + +pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { + use GenericBound::*; + match (l, r) { + (Trait(ptr1, tbm1), Trait(ptr2, tbm2)) => tbm1 == tbm2 && eq_poly_ref_trait(ptr1, ptr2), + (Outlives(l), Outlives(r)) => eq_id(l.ident, r.ident), + _ => false, + } +} + +pub fn eq_assoc_constraint(l: &AssocTyConstraint, r: &AssocTyConstraint) -> bool { + use AssocTyConstraintKind::*; + eq_id(l.ident, r.ident) + && match (&l.kind, &r.kind) { + (Equality { ty: l }, Equality { ty: r }) => eq_ty(l, r), + (Bound { bounds: l }, Bound { bounds: r }) => over(l, r, |l, r| eq_generic_bound(l, r)), + _ => false, + } +} + +pub fn eq_mac_call(l: &MacCall, r: &MacCall) -> bool { + eq_path(&l.path, &r.path) && eq_mac_args(&l.args, &r.args) +} + +pub fn eq_attr(l: &Attribute, r: &Attribute) -> bool { + use AttrKind::*; + l.style == r.style + && match (&l.kind, &r.kind) { + (DocComment(l), DocComment(r)) => l == r, + (Normal(l), Normal(r)) => eq_path(&l.path, &r.path) && eq_mac_args(&l.args, &r.args), + _ => false, + } +} + +pub fn eq_mac_args(l: &MacArgs, r: &MacArgs) -> bool { + use MacArgs::*; + match (l, r) { + (Empty, Empty) => true, + (Delimited(_, ld, lts), Delimited(_, rd, rts)) => ld == rd && lts.eq_unspanned(rts), + (Eq(_, lts), Eq(_, rts)) => lts.eq_unspanned(rts), + _ => false, + } +} diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 92c27e79452..f8d197c15e8 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -332,19 +332,13 @@ fn swap_binop<'a>( /// Checks if the two `Option`s are both `None` or some equal values as per /// `eq_fn`. -fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool -where - F: FnMut(&X, &X) -> bool, -{ +pub fn both<X>(l: &Option<X>, r: &Option<X>, mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool { l.as_ref() .map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) } /// Checks if two slices are equal as per `eq_fn`. -fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool -where - F: FnMut(&X, &X) -> bool, -{ +pub fn over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool { left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 06638e7187b..8f8aff622f4 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1,6 +1,7 @@ #[macro_use] pub mod sym; +pub mod ast_utils; pub mod attrs; pub mod author; pub mod camel_case; @@ -19,7 +20,7 @@ pub mod sugg; pub mod usage; pub use self::attrs::*; pub use self::diagnostics::*; -pub use self::hir_utils::{SpanlessEq, SpanlessHash}; +pub use self::hir_utils::{both, over, SpanlessEq, SpanlessHash}; use std::borrow::Cow; use std::mem; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index d5d07ccb2eb..745d543a4cc 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2327,6 +2327,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "misc_early", }, + Lint { + name: "unnested_or_patterns", + group: "complexity", + desc: "unnested or-patterns, e.g., `Foo(Bar) | Foo(Baz) instead of `Foo(Bar | Baz)`", + deprecation: None, + module: "unnested_or_patterns", + }, Lint { name: "unreachable", group: "restriction", diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index 856a430ba2b..ca70e3b7148 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -4,6 +4,7 @@ use std::cmp::Ordering; +#[allow(clippy::unnested_or_patterns)] #[warn(clippy::neg_cmp_op_on_partial_ord)] fn main() { let a_value = 1.0; diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index d05fd34ce33..8c5d548222e 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,5 +1,5 @@ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:15:21 + --> $DIR/neg_cmp_op_on_partial_ord.rs:16:21 | LL | let _not_less = !(a_value < another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | let _not_less = !(a_value < another_value); = note: `-D clippy::neg-cmp-op-on-partial-ord` implied by `-D warnings` error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:18:30 + --> $DIR/neg_cmp_op_on_partial_ord.rs:19:30 | LL | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:21:24 + --> $DIR/neg_cmp_op_on_partial_ord.rs:22:24 | LL | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. - --> $DIR/neg_cmp_op_on_partial_ord.rs:24:33 + --> $DIR/neg_cmp_op_on_partial_ord.rs:25:33 | LL | let _not_greater_or_equal = !(a_value >= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed new file mode 100644 index 00000000000..e1bd5cd5562 --- /dev/null +++ b/tests/ui/unnested_or_patterns.fixed @@ -0,0 +1,41 @@ +// run-rustfix + +#![feature(or_patterns)] +#![feature(box_patterns)] +#![warn(clippy::unnested_or_patterns)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] +#![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] + +fn main() { + if let box (0 | 2) = Box::new(0) {} + if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} + const C0: &u8 = &1; + if let &(0 | 2) | C0 = &0 {} + if let &mut (0 | 2) = &mut 0 {} + if let x @ (0 | 2) = 0 {} + if let (0, 1 | 2 | 3) = (0, 0) {} + if let (1 | 2 | 3, 0) = (0, 0) {} + if let (x, ..) | (x, 1 | 2) = (0, 1) {} + if let [0 | 1] = [0] {} + if let [x, 0 | 1] = [0, 1] {} + if let [x, 0 | 1 | 2] = [0, 1] {} + if let [x, ..] | [x, 1 | 2] = [0, 1] {} + struct TS(u8, u8); + if let TS(0 | 1, x) = TS(0, 0) {} + if let TS(1 | 2 | 3, 0) = TS(0, 0) {} + if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} + struct S { + x: u8, + y: u8, + } + if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} + if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} + if let Some(Some(0 | 1)) = None {} + if let Some(Some(0 | 1 | 2)) = None {} + if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} + if let Some(Some(0 | 1 | 2)) = None {} + if let ((0 | 1 | 2,),) = ((0,),) {} + if let 0 | 1 | 2 = 0 {} + if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} + if let box box (0 | 2 | 4) = Box::new(Box::new(0)) {} +} diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs new file mode 100644 index 00000000000..d5c3c1fb74a --- /dev/null +++ b/tests/ui/unnested_or_patterns.rs @@ -0,0 +1,41 @@ +// run-rustfix + +#![feature(or_patterns)] +#![feature(box_patterns)] +#![warn(clippy::unnested_or_patterns)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] +#![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] + +fn main() { + if let box 0 | box 2 = Box::new(0) {} + if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} + const C0: &u8 = &1; + if let &0 | C0 | &2 = &0 {} + if let &mut 0 | &mut 2 = &mut 0 {} + if let x @ 0 | x @ 2 = 0 {} + if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} + if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} + if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} + if let [0] | [1] = [0] {} + if let [x, 0] | [x, 1] = [0, 1] {} + if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} + if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} + struct TS(u8, u8); + if let TS(0, x) | TS(1, x) = TS(0, 0) {} + if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} + if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} + struct S { + x: u8, + y: u8, + } + if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} + if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} + if let Some(Some(0)) | Some(Some(1)) = None {} + if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} + if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} + if let Some(Some(0) | Some(1 | 2)) = None {} + if let ((0,),) | ((1,) | (2,),) = ((0,),) {} + if let 0 | (1 | 2) = 0 {} + if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} + if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} +} diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr new file mode 100644 index 00000000000..d1efe274c99 --- /dev/null +++ b/tests/ui/unnested_or_patterns.stderr @@ -0,0 +1,267 @@ +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:10:12 + | +LL | if let box 0 | box 2 = Box::new(0) {} + | ^^^^^^^^^^^^^ + | + = note: `-D clippy::unnested-or-patterns` implied by `-D warnings` +help: nest the patterns + | +LL | if let box (0 | 2) = Box::new(0) {} + | ^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:11:12 + | +LL | if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:13:12 + | +LL | if let &0 | C0 | &2 = &0 {} + | ^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let &(0 | 2) | C0 = &0 {} + | ^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:14:12 + | +LL | if let &mut 0 | &mut 2 = &mut 0 {} + | ^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let &mut (0 | 2) = &mut 0 {} + | ^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:15:12 + | +LL | if let x @ 0 | x @ 2 = 0 {} + | ^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let x @ (0 | 2) = 0 {} + | ^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:16:12 + | +LL | if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let (0, 1 | 2 | 3) = (0, 0) {} + | ^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:17:12 + | +LL | if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let (1 | 2 | 3, 0) = (0, 0) {} + | ^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:18:12 + | +LL | if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let (x, ..) | (x, 1 | 2) = (0, 1) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:19:12 + | +LL | if let [0] | [1] = [0] {} + | ^^^^^^^^^ + | +help: nest the patterns + | +LL | if let [0 | 1] = [0] {} + | ^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:20:12 + | +LL | if let [x, 0] | [x, 1] = [0, 1] {} + | ^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let [x, 0 | 1] = [0, 1] {} + | ^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:21:12 + | +LL | if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let [x, 0 | 1 | 2] = [0, 1] {} + | ^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:22:12 + | +LL | if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let [x, ..] | [x, 1 | 2] = [0, 1] {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:24:12 + | +LL | if let TS(0, x) | TS(1, x) = TS(0, 0) {} + | ^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let TS(0 | 1, x) = TS(0, 0) {} + | ^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:25:12 + | +LL | if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let TS(1 | 2 | 3, 0) = TS(0, 0) {} + | ^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:26:12 + | +LL | if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:31:12 + | +LL | if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} + | ^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:33:12 + | +LL | if let Some(Some(0)) | Some(Some(1)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let Some(Some(0 | 1)) = None {} + | ^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:34:12 + | +LL | if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let Some(Some(0 | 1 | 2)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:35:12 + | +LL | if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:36:12 + | +LL | if let Some(Some(0) | Some(1 | 2)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let Some(Some(0 | 1 | 2)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:37:12 + | +LL | if let ((0,),) | ((1,) | (2,),) = ((0,),) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let ((0 | 1 | 2,),) = ((0,),) {} + | ^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:38:12 + | +LL | if let 0 | (1 | 2) = 0 {} + | ^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let 0 | 1 | 2 = 0 {} + | ^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:39:12 + | +LL | if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:40:12 + | +LL | if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let box box (0 | 2 | 4) = Box::new(Box::new(0)) {} + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 24 previous errors + diff --git a/tests/ui/wildcard_enum_match_arm.fixed b/tests/ui/wildcard_enum_match_arm.fixed index 2aa24ea1156..4f8754a9301 100644 --- a/tests/ui/wildcard_enum_match_arm.fixed +++ b/tests/ui/wildcard_enum_match_arm.fixed @@ -6,7 +6,8 @@ unused_variables, dead_code, clippy::single_match, - clippy::wildcard_in_or_patterns + clippy::wildcard_in_or_patterns, + clippy::unnested_or_patterns )] use std::io::ErrorKind; diff --git a/tests/ui/wildcard_enum_match_arm.rs b/tests/ui/wildcard_enum_match_arm.rs index 07c93feaf28..5e66644ceca 100644 --- a/tests/ui/wildcard_enum_match_arm.rs +++ b/tests/ui/wildcard_enum_match_arm.rs @@ -6,7 +6,8 @@ unused_variables, dead_code, clippy::single_match, - clippy::wildcard_in_or_patterns + clippy::wildcard_in_or_patterns, + clippy::unnested_or_patterns )] use std::io::ErrorKind; diff --git a/tests/ui/wildcard_enum_match_arm.stderr b/tests/ui/wildcard_enum_match_arm.stderr index 7151a5c5770..e03b3be43ed 100644 --- a/tests/ui/wildcard_enum_match_arm.stderr +++ b/tests/ui/wildcard_enum_match_arm.stderr @@ -1,5 +1,5 @@ error: wildcard match will miss any future added variants - --> $DIR/wildcard_enum_match_arm.rs:37:9 + --> $DIR/wildcard_enum_match_arm.rs:38:9 | LL | _ => eprintln!("Not red"), | ^ help: try this: `Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` @@ -11,25 +11,25 @@ LL | #![deny(clippy::wildcard_enum_match_arm)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wildcard match will miss any future added variants - --> $DIR/wildcard_enum_match_arm.rs:41:9 + --> $DIR/wildcard_enum_match_arm.rs:42:9 | LL | _not_red => eprintln!("Not red"), | ^^^^^^^^ help: try this: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan` error: wildcard match will miss any future added variants - --> $DIR/wildcard_enum_match_arm.rs:45:9 + --> $DIR/wildcard_enum_match_arm.rs:46:9 | LL | not_red => format!("{:?}", not_red), | ^^^^^^^ help: try this: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan` error: wildcard match will miss any future added variants - --> $DIR/wildcard_enum_match_arm.rs:61:9 + --> $DIR/wildcard_enum_match_arm.rs:62:9 | LL | _ => "No red", | ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` error: match on non-exhaustive enum doesn't explicitly match all known variants - --> $DIR/wildcard_enum_match_arm.rs:78:9 + --> $DIR/wildcard_enum_match_arm.rs:79:9 | LL | _ => {}, | ^ help: try this: `std::io::ErrorKind::PermissionDenied | std::io::ErrorKind::ConnectionRefused | std::io::ErrorKind::ConnectionReset | std::io::ErrorKind::ConnectionAborted | std::io::ErrorKind::NotConnected | std::io::ErrorKind::AddrInUse | std::io::ErrorKind::AddrNotAvailable | std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::AlreadyExists | std::io::ErrorKind::WouldBlock | std::io::ErrorKind::InvalidInput | std::io::ErrorKind::InvalidData | std::io::ErrorKind::TimedOut | std::io::ErrorKind::WriteZero | std::io::ErrorKind::Interrupted | std::io::ErrorKind::Other | std::io::ErrorKind::UnexpectedEof | _` From a664ce7789a54006cc6c01d8aefbfa4477c9d618 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sun, 7 Jun 2020 21:13:13 +0200 Subject: [PATCH 183/526] Remove unnecessary lifetime parameter --- clippy_lints/src/ranges.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 45de4d29375..52e540d4e00 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -241,7 +241,7 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { - fn inside_indexing_expr<'a>(cx: &'a LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + fn inside_indexing_expr(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { matches!( get_parent_expr(cx, expr), Some(Expr { From 78f158e80e3a2ec8022e6cd6b2f62b17b3e96b57 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad <twingoow@gmail.com> Date: Sat, 28 Mar 2020 11:45:13 +0100 Subject: [PATCH 184/526] dogfood unnested_or_patterns --- clippy_lints/src/formatting.rs | 8 +--- .../methods/manual_saturating_arithmetic.rs | 2 +- clippy_lints/src/methods/mod.rs | 13 ++--- clippy_lints/src/misc.rs | 19 ++++---- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/suspicious_trait_impl.rs | 6 +-- clippy_lints/src/transmute.rs | 47 +++++++++---------- clippy_lints/src/unwrap.rs | 2 +- clippy_lints/src/utils/mod.rs | 9 ++-- 9 files changed, 44 insertions(+), 64 deletions(-) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index eb4b7a826f2..156246fb8bb 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -112,12 +112,8 @@ declare_lint_pass!(Formatting => [ impl EarlyLintPass for Formatting { fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) { for w in block.stmts.windows(2) { - match (&w[0].kind, &w[1].kind) { - (&StmtKind::Expr(ref first), &StmtKind::Expr(ref second)) - | (&StmtKind::Expr(ref first), &StmtKind::Semi(ref second)) => { - check_missing_else(cx, first, second); - }, - _ => (), + if let (StmtKind::Expr(first), StmtKind::Expr(second) | StmtKind::Semi(second)) = (&w[0].kind, &w[1].kind) { + check_missing_else(cx, first, second); } } } diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs index aaed6d75048..4f5c06e785c 100644 --- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -57,7 +57,7 @@ pub fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[&[hir::Expr< ); } else { match (mm, arith) { - (MinMax::Max, "add") | (MinMax::Max, "mul") | (MinMax::Min, "sub") => (), + (MinMax::Max, "add" | "mul") | (MinMax::Min, "sub") => (), _ => return, } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 78d69690c2d..214cf0c130f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1403,9 +1403,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { lint_search_is_some(cx, expr, "rposition", arg_lists[1], arg_lists[0], method_spans[1]) }, ["extend", ..] => lint_extend(cx, expr, arg_lists[0]), - ["as_ptr", "unwrap"] | ["as_ptr", "expect"] => { - lint_cstring_as_ptr(cx, expr, &arg_lists[1][0], &arg_lists[0][0]) - }, + ["as_ptr", "unwrap" | "expect"] => lint_cstring_as_ptr(cx, expr, &arg_lists[1][0], &arg_lists[0][0]), ["nth", "iter"] => lint_iter_nth(cx, expr, &arg_lists, false), ["nth", "iter_mut"] => lint_iter_nth(cx, expr, &arg_lists, true), ["nth", ..] => lint_iter_nth_zero(cx, expr, arg_lists[0]), @@ -1418,12 +1416,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { ["filter_map", ..] => unnecessary_filter_map::lint(cx, expr, arg_lists[0]), ["count", "map"] => lint_suspicious_map(cx, expr), ["assume_init"] => lint_maybe_uninit(cx, &arg_lists[0][0], expr), - ["unwrap_or", arith @ "checked_add"] - | ["unwrap_or", arith @ "checked_sub"] - | ["unwrap_or", arith @ "checked_mul"] => { + ["unwrap_or", arith @ ("checked_add" | "checked_sub" | "checked_mul")] => { manual_saturating_arithmetic::lint(cx, expr, &arg_lists, &arith["checked_".len()..]) }, - ["add"] | ["offset"] | ["sub"] | ["wrapping_offset"] | ["wrapping_add"] | ["wrapping_sub"] => { + ["add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub"] => { check_pointer_offset(cx, expr, arg_lists[0]) }, ["is_file", ..] => lint_filetype_is_file(cx, expr, arg_lists[0]), @@ -1829,8 +1825,7 @@ fn lint_expect_fun_call( hir::ExprKind::Call(fun, _) => { if let hir::ExprKind::Path(ref p) = fun.kind { match cx.tables.qpath_res(p, fun.hir_id) { - hir::def::Res::Def(hir::def::DefKind::Fn, def_id) - | hir::def::Res::Def(hir::def::DefKind::AssocFn, def_id) => matches!( + hir::def::Res::Def(hir::def::DefKind::Fn | hir::def::DefKind::AssocFn, def_id) => matches!( cx.tcx.fn_sig(def_id).output().skip_binder().kind, ty::Ref(ty::ReStatic, ..) ), diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 51282ab93ef..f513161bbbc 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -275,17 +275,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints { return; } for arg in iter_input_pats(decl, body) { - match arg.pat.kind { - PatKind::Binding(BindingAnnotation::Ref, ..) | PatKind::Binding(BindingAnnotation::RefMut, ..) => { - span_lint( - cx, - TOPLEVEL_REF_ARG, - arg.pat.span, - "`ref` directly on a function argument is ignored. Consider using a reference type \ - instead.", - ); - }, - _ => {}, + if let PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..) = arg.pat.kind { + span_lint( + cx, + TOPLEVEL_REF_ARG, + arg.pat.span, + "`ref` directly on a function argument is ignored. \ + Consider using a reference type instead.", + ); } } } diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index b8bfa676a16..2eacd3c80c4 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -147,7 +147,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option if let ExprKind::Path(ref qpath) = callee.kind { let res = qpath_res(cx, qpath, callee.hir_id); match res { - Res::Def(DefKind::Struct, ..) | Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(..), _) + Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) if !has_drop(cx, cx.tables.expr_ty(expr)) => { Some(args.iter().collect()) diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index f1e223d9a48..a9e6fa329c0 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -71,8 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { if let hir::Node::Expr(e) = cx.tcx.hir().get(parent_expr) { match e.kind { hir::ExprKind::Binary(..) - | hir::ExprKind::Unary(hir::UnOp::UnNot, _) - | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) + | hir::ExprKind::Unary(hir::UnOp::UnNot | hir::UnOp::UnNeg, _) | hir::ExprKind::AssignOp(..) => return, _ => {}, } @@ -191,8 +190,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BinaryExprVisitor { fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { match expr.kind { hir::ExprKind::Binary(..) - | hir::ExprKind::Unary(hir::UnOp::UnNot, _) - | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) + | hir::ExprKind::Unary(hir::UnOp::UnNot | hir::UnOp::UnNeg, _) | hir::ExprKind::AssignOp(..) => self.in_binary_expr = true, _ => {}, } diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index e24d2c4f495..1869638f6ff 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -312,7 +312,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!("transmute from a type (`{}`) to itself", from_ty), ), - (&ty::Ref(_, rty, rty_mutbl), &ty::RawPtr(ptr_ty)) => span_lint_and_then( + (ty::Ref(_, rty, rty_mutbl), ty::RawPtr(ptr_ty)) => span_lint_and_then( cx, USELESS_TRANSMUTE, e.span, @@ -321,10 +321,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { let rty_and_mut = ty::TypeAndMut { ty: rty, - mutbl: rty_mutbl, + mutbl: *rty_mutbl, }; - let sugg = if ptr_ty == rty_and_mut { + let sugg = if *ptr_ty == rty_and_mut { arg.as_ty(to_ty) } else { arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) @@ -334,7 +334,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } }, ), - (&ty::Int(_), &ty::RawPtr(_)) | (&ty::Uint(_), &ty::RawPtr(_)) => span_lint_and_then( + (ty::Int(_) | ty::Uint(_), ty::RawPtr(_)) => span_lint_and_then( cx, USELESS_TRANSMUTE, e.span, @@ -350,16 +350,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } }, ), - (&ty::Float(_), &ty::Ref(..)) - | (&ty::Float(_), &ty::RawPtr(_)) - | (&ty::Char, &ty::Ref(..)) - | (&ty::Char, &ty::RawPtr(_)) => span_lint( + (ty::Float(_) | ty::Char, ty::Ref(..) | ty::RawPtr(_)) => span_lint( cx, WRONG_TRANSMUTE, e.span, &format!("transmute from a `{}` to a pointer", from_ty), ), - (&ty::RawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( + (ty::RawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( cx, CROSSPOINTER_TRANSMUTE, e.span, @@ -368,7 +365,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { from_ty, to_ty ), ), - (_, &ty::RawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( + (_, ty::RawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( cx, CROSSPOINTER_TRANSMUTE, e.span, @@ -377,7 +374,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { from_ty, to_ty ), ), - (&ty::RawPtr(from_pty), &ty::Ref(_, to_ref_ty, mutbl)) => span_lint_and_then( + (ty::RawPtr(from_pty), ty::Ref(_, to_ref_ty, mutbl)) => span_lint_and_then( cx, TRANSMUTE_PTR_TO_REF, e.span, @@ -388,13 +385,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { ), |diag| { let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let (deref, cast) = if mutbl == Mutability::Mut { + let (deref, cast) = if *mutbl == Mutability::Mut { ("&mut *", "*mut") } else { ("&*", "*const") }; - let arg = if from_pty.ty == to_ref_ty { + let arg = if from_pty.ty == *to_ref_ty { arg } else { arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty))) @@ -408,7 +405,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { ); }, ), - (&ty::Int(ast::IntTy::I32), &ty::Char) | (&ty::Uint(ast::UintTy::U32), &ty::Char) => { + (ty::Int(ast::IntTy::I32) | ty::Uint(ast::UintTy::U32), &ty::Char) => { span_lint_and_then( cx, TRANSMUTE_INT_TO_CHAR, @@ -430,13 +427,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { }, ) }, - (&ty::Ref(_, ty_from, from_mutbl), &ty::Ref(_, ty_to, to_mutbl)) => { + (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) => { if_chain! { if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.kind, &ty_to.kind); if let ty::Uint(ast::UintTy::U8) = slice_ty.kind; if from_mutbl == to_mutbl; then { - let postfix = if from_mutbl == Mutability::Mut { + let postfix = if *from_mutbl == Mutability::Mut { "_mut" } else { "" @@ -465,13 +462,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { |diag| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { let ty_from_and_mut = ty::TypeAndMut { ty: ty_from, - mutbl: from_mutbl + mutbl: *from_mutbl }; - let ty_to_and_mut = ty::TypeAndMut { ty: ty_to, mutbl: to_mutbl }; + let ty_to_and_mut = ty::TypeAndMut { ty: ty_to, mutbl: *to_mutbl }; let sugg_paren = arg .as_ty(cx.tcx.mk_ptr(ty_from_and_mut)) .as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); - let sugg = if to_mutbl == Mutability::Mut { + let sugg = if *to_mutbl == Mutability::Mut { sugg_paren.mut_addr_deref() } else { sugg_paren.addr_deref() @@ -488,19 +485,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { } } }, - (&ty::RawPtr(_), &ty::RawPtr(to_ty)) => span_lint_and_then( + (ty::RawPtr(_), ty::RawPtr(to_ty)) => span_lint_and_then( cx, TRANSMUTE_PTR_TO_PTR, e.span, "transmute from a pointer to a pointer", |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty)); + let sugg = arg.as_ty(cx.tcx.mk_ptr(*to_ty)); diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified); } }, ), - (&ty::Int(ast::IntTy::I8), &ty::Bool) | (&ty::Uint(ast::UintTy::U8), &ty::Bool) => { + (ty::Int(ast::IntTy::I8) | ty::Uint(ast::UintTy::U8), ty::Bool) => { span_lint_and_then( cx, TRANSMUTE_INT_TO_BOOL, @@ -518,7 +515,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { }, ) }, - (&ty::Int(_), &ty::Float(_)) | (&ty::Uint(_), &ty::Float(_)) => span_lint_and_then( + (ty::Int(_) | ty::Uint(_), ty::Float(_)) => span_lint_and_then( cx, TRANSMUTE_INT_TO_FLOAT, e.span, @@ -541,7 +538,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { ); }, ), - (&ty::Float(float_ty), &ty::Int(_)) | (&ty::Float(float_ty), &ty::Uint(_)) => span_lint_and_then( + (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) => span_lint_and_then( cx, TRANSMUTE_FLOAT_TO_INT, e.span, @@ -585,7 +582,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { ); }, ), - (&ty::Adt(ref from_adt, ref from_substs), &ty::Adt(ref to_adt, ref to_substs)) => { + (ty::Adt(from_adt, from_substs), ty::Adt(to_adt, to_substs)) => { if from_adt.did != to_adt.did || !COLLECTIONS.iter().any(|path| match_def_path(cx, to_adt.did, path)) { return; diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 8b971e7064b..036dd16a224 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -101,7 +101,7 @@ fn collect_unwrap_info<'a, 'tcx>( if let ExprKind::Binary(op, left, right) = &expr.kind { match (invert, op.node) { - (false, BinOpKind::And) | (false, BinOpKind::BitAnd) | (true, BinOpKind::Or) | (true, BinOpKind::BitOr) => { + (false, BinOpKind::And | BinOpKind::BitAnd) | (true, BinOpKind::Or | BinOpKind::BitOr) => { let mut unwrap_info = collect_unwrap_info(cx, left, branch, invert); unwrap_info.append(&mut collect_unwrap_info(cx, right, branch, invert)); return unwrap_info; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 8f8aff622f4..7c823810265 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1,6 +1,7 @@ #[macro_use] pub mod sym; +#[allow(clippy::module_name_repetitions)] pub mod ast_utils; pub mod attrs; pub mod author; @@ -73,7 +74,7 @@ pub fn in_constant(cx: &LateContext<'_, '_>, id: HirId) -> bool { let parent_id = cx.tcx.hir().get_parent_item(id); match cx.tcx.hir().get(parent_id) { Node::Item(&Item { - kind: ItemKind::Const(..), + kind: ItemKind::Const(..) | ItemKind::Static(..), .. }) | Node::TraitItem(&TraitItem { @@ -84,11 +85,7 @@ pub fn in_constant(cx: &LateContext<'_, '_>, id: HirId) -> bool { kind: ImplItemKind::Const(..), .. }) - | Node::AnonConst(_) - | Node::Item(&Item { - kind: ItemKind::Static(..), - .. - }) => true, + | Node::AnonConst(_) => true, Node::Item(&Item { kind: ItemKind::Fn(ref sig, ..), .. From d6136b92a203207bf25ee2f3c7c56ca9c881e92b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad <twingoow@gmail.com> Date: Sat, 28 Mar 2020 13:08:57 +0100 Subject: [PATCH 185/526] split unnested_or_patterns test --- tests/ui/unnested_or_patterns.fixed | 8 --- tests/ui/unnested_or_patterns.rs | 8 --- tests/ui/unnested_or_patterns.stderr | 90 +------------------------- tests/ui/unnested_or_patterns2.fixed | 18 ++++++ tests/ui/unnested_or_patterns2.rs | 18 ++++++ tests/ui/unnested_or_patterns2.stderr | 91 +++++++++++++++++++++++++++ 6 files changed, 128 insertions(+), 105 deletions(-) create mode 100644 tests/ui/unnested_or_patterns2.fixed create mode 100644 tests/ui/unnested_or_patterns2.rs create mode 100644 tests/ui/unnested_or_patterns2.stderr diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index e1bd5cd5562..b39e891094f 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -30,12 +30,4 @@ fn main() { } if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} - if let Some(Some(0 | 1)) = None {} - if let Some(Some(0 | 1 | 2)) = None {} - if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} - if let Some(Some(0 | 1 | 2)) = None {} - if let ((0 | 1 | 2,),) = ((0,),) {} - if let 0 | 1 | 2 = 0 {} - if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} - if let box box (0 | 2 | 4) = Box::new(Box::new(0)) {} } diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index d5c3c1fb74a..096f5a71150 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -30,12 +30,4 @@ fn main() { } if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} - if let Some(Some(0)) | Some(Some(1)) = None {} - if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} - if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} - if let Some(Some(0) | Some(1 | 2)) = None {} - if let ((0,),) | ((1,) | (2,),) = ((0,),) {} - if let 0 | (1 | 2) = 0 {} - if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} - if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} } diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index d1efe274c99..1899dc657df 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -175,93 +175,5 @@ help: nest the patterns LL | if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} | ^^^^^^^^^^^^^^^^^ -error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:33:12 - | -LL | if let Some(Some(0)) | Some(Some(1)) = None {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: nest the patterns - | -LL | if let Some(Some(0 | 1)) = None {} - | ^^^^^^^^^^^^^^^^^ - -error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:34:12 - | -LL | if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: nest the patterns - | -LL | if let Some(Some(0 | 1 | 2)) = None {} - | ^^^^^^^^^^^^^^^^^^^^^ - -error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:35:12 - | -LL | if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: nest the patterns - | -LL | if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:36:12 - | -LL | if let Some(Some(0) | Some(1 | 2)) = None {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: nest the patterns - | -LL | if let Some(Some(0 | 1 | 2)) = None {} - | ^^^^^^^^^^^^^^^^^^^^^ - -error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:37:12 - | -LL | if let ((0,),) | ((1,) | (2,),) = ((0,),) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: nest the patterns - | -LL | if let ((0 | 1 | 2,),) = ((0,),) {} - | ^^^^^^^^^^^^^^^ - -error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:38:12 - | -LL | if let 0 | (1 | 2) = 0 {} - | ^^^^^^^^^^^ - | -help: nest the patterns - | -LL | if let 0 | 1 | 2 = 0 {} - | ^^^^^^^^^ - -error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:39:12 - | -LL | if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: nest the patterns - | -LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:40:12 - | -LL | if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: nest the patterns - | -LL | if let box box (0 | 2 | 4) = Box::new(Box::new(0)) {} - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 24 previous errors +error: aborting due to 16 previous errors diff --git a/tests/ui/unnested_or_patterns2.fixed b/tests/ui/unnested_or_patterns2.fixed new file mode 100644 index 00000000000..02a129c55a3 --- /dev/null +++ b/tests/ui/unnested_or_patterns2.fixed @@ -0,0 +1,18 @@ +// run-rustfix + +#![feature(or_patterns)] +#![feature(box_patterns)] +#![warn(clippy::unnested_or_patterns)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] +#![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] + +fn main() { + if let Some(Some(0 | 1)) = None {} + if let Some(Some(0 | 1 | 2)) = None {} + if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} + if let Some(Some(0 | 1 | 2)) = None {} + if let ((0 | 1 | 2,),) = ((0,),) {} + if let 0 | 1 | 2 = 0 {} + if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} + if let box box (0 | 2 | 4) = Box::new(Box::new(0)) {} +} diff --git a/tests/ui/unnested_or_patterns2.rs b/tests/ui/unnested_or_patterns2.rs new file mode 100644 index 00000000000..acf3158989d --- /dev/null +++ b/tests/ui/unnested_or_patterns2.rs @@ -0,0 +1,18 @@ +// run-rustfix + +#![feature(or_patterns)] +#![feature(box_patterns)] +#![warn(clippy::unnested_or_patterns)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] +#![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] + +fn main() { + if let Some(Some(0)) | Some(Some(1)) = None {} + if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} + if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} + if let Some(Some(0) | Some(1 | 2)) = None {} + if let ((0,),) | ((1,) | (2,),) = ((0,),) {} + if let 0 | (1 | 2) = 0 {} + if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} + if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} +} diff --git a/tests/ui/unnested_or_patterns2.stderr b/tests/ui/unnested_or_patterns2.stderr new file mode 100644 index 00000000000..1847fd8e098 --- /dev/null +++ b/tests/ui/unnested_or_patterns2.stderr @@ -0,0 +1,91 @@ +error: unnested or-patterns + --> $DIR/unnested_or_patterns2.rs:10:12 + | +LL | if let Some(Some(0)) | Some(Some(1)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unnested-or-patterns` implied by `-D warnings` +help: nest the patterns + | +LL | if let Some(Some(0 | 1)) = None {} + | ^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns2.rs:11:12 + | +LL | if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let Some(Some(0 | 1 | 2)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns2.rs:12:12 + | +LL | if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns2.rs:13:12 + | +LL | if let Some(Some(0) | Some(1 | 2)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let Some(Some(0 | 1 | 2)) = None {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns2.rs:14:12 + | +LL | if let ((0,),) | ((1,) | (2,),) = ((0,),) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let ((0 | 1 | 2,),) = ((0,),) {} + | ^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns2.rs:15:12 + | +LL | if let 0 | (1 | 2) = 0 {} + | ^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let 0 | 1 | 2 = 0 {} + | ^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns2.rs:16:12 + | +LL | if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: unnested or-patterns + --> $DIR/unnested_or_patterns2.rs:17:12 + | +LL | if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let box box (0 | 2 | 4) = Box::new(Box::new(0)) {} + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + From ecabed67ec75ac6498c6176a7a6de3ad53b2e54b Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sun, 7 Jun 2020 16:43:17 +0200 Subject: [PATCH 186/526] Apply self-review by Centril --- clippy_lints/src/unnested_or_patterns.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 2723af03c0b..8c281126c32 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -214,21 +214,21 @@ fn transform_with_focus_on_idx(alternatives: &mut Vec<P<Pat>>, focus_idx: usize) let changed = match &mut focus_kind { // These pattern forms are "leafs" and do not have sub-patterns. // Therefore they are not some form of constructor `C`, - // with which a pattern `C(P0)` may be formed, - // which we would want to join with other `C(Pj)`s. + // with which a pattern `C(p_0)` may be formed, + // which we would want to join with other `C(p_j)`s. Ident(.., None) | Lit(_) | Wild | Path(..) | Range(..) | Rest | MacCall(_) // Dealt with elsewhere. | Or(_) | Paren(_) => false, // Transform `box x | ... | box y` into `box (x | y)`. // - // The cases below until `Slice(...)` deal *singleton* products. + // The cases below until `Slice(...)` deal with *singleton* products. // These patterns have the shape `C(p)`, and not e.g., `C(p0, ..., pn)`. Box(target) => extend_with_matching( target, start, alternatives, |k| matches!(k, Box(_)), |k| always_pat!(k, Box(p) => p), ), - // Transform `&m x | ... | &m y` into `&m (x, y)`. + // Transform `&m x | ... | &m y` into `&m (x | y)`. Ref(target, m1) => extend_with_matching( target, start, alternatives, |k| matches!(k, Ref(_, m2) if m1 == m2), // Mutabilities must match. @@ -247,13 +247,13 @@ fn transform_with_focus_on_idx(alternatives: &mut Vec<P<Pat>>, focus_idx: usize) |k, ps1, idx| matches!(k, Slice(ps2) if eq_pre_post(ps1, ps2, idx)), |k| always_pat!(k, Slice(ps) => ps), ), - // Transform `(pre, x, post) | ... | (pre, y, post)` into `(pre, x | y, post]`. + // Transform `(pre, x, post) | ... | (pre, y, post)` into `(pre, x | y, post)`. Tuple(ps1) => extend_with_matching_product( ps1, start, alternatives, |k, ps1, idx| matches!(k, Tuple(ps2) if eq_pre_post(ps1, ps2, idx)), |k| always_pat!(k, Tuple(ps) => ps), ), - // Transform `S(pre, x, post) | ... | S(pre, y, post)` into `S(pre, x | y, post]`. + // Transform `S(pre, x, post) | ... | S(pre, y, post)` into `S(pre, x | y, post)`. TupleStruct(path1, ps1) => extend_with_matching_product( ps1, start, alternatives, |k, ps1, idx| matches!( From a9ca832b11f7671f5d88f299a44415cf964304e7 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sun, 7 Jun 2020 21:33:03 +0200 Subject: [PATCH 187/526] Fix rebase fallout --- clippy_lints/src/await_holding_lock.rs | 19 +++++++------------ clippy_lints/src/utils/ast_utils.rs | 1 + 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/await_holding_lock.rs b/clippy_lints/src/await_holding_lock.rs index 832910763e6..a88f922d8e0 100644 --- a/clippy_lints/src/await_holding_lock.rs +++ b/clippy_lints/src/await_holding_lock.rs @@ -54,18 +54,13 @@ declare_lint_pass!(AwaitHoldingLock => [AWAIT_HOLDING_LOCK]); impl LateLintPass<'_, '_> for AwaitHoldingLock { fn check_body(&mut self, cx: &LateContext<'_, '_>, body: &'_ Body<'_>) { use AsyncGeneratorKind::{Block, Closure, Fn}; - match body.generator_kind { - Some(GeneratorKind::Async(Block)) - | Some(GeneratorKind::Async(Closure)) - | Some(GeneratorKind::Async(Fn)) => { - let body_id = BodyId { - hir_id: body.value.hir_id, - }; - let def_id = cx.tcx.hir().body_owner_def_id(body_id); - let tables = cx.tcx.typeck_tables_of(def_id); - check_interior_types(cx, &tables.generator_interior_types, body.value.span); - }, - _ => {}, + if let Some(GeneratorKind::Async(Block | Closure | Fn)) = body.generator_kind { + let body_id = BodyId { + hir_id: body.value.hir_id, + }; + let def_id = cx.tcx.hir().body_owner_def_id(body_id); + let tables = cx.tcx.typeck_tables_of(def_id); + check_interior_types(cx, &tables.generator_interior_types, body.value.span); } } } diff --git a/clippy_lints/src/utils/ast_utils.rs b/clippy_lints/src/utils/ast_utils.rs index 69a7b6c051e..dcf09da198e 100755 --- a/clippy_lints/src/utils/ast_utils.rs +++ b/clippy_lints/src/utils/ast_utils.rs @@ -7,6 +7,7 @@ use crate::utils::{both, over}; use rustc_ast::ast::{self, *}; use rustc_ast::ptr::P; +use rustc_span::symbol::Ident; use std::mem; /// Checks if each element in the first slice is contained within the latter as per `eq_fn`. From a4b8bb88f210de7fa2d82fe64b48331126eb7462 Mon Sep 17 00:00:00 2001 From: Devin R <devin.ragotzy@gmail.com> Date: Wed, 26 Feb 2020 07:40:31 -0500 Subject: [PATCH 188/526] warn on macro_use attr cargo dev update lints use if_chain clean up alot, span_lint_and_sugg find imported macros for sugg --- clippy_lints/src/macro_use.rs | 68 ++++++++++++++++++++++++++----- macro_use_import | Bin 0 -> 2816064 bytes tests/ui/macro_use_import.rs | 12 ++++++ tests/ui/macro_use_import.stderr | 10 +++++ tests/ui/macro_use_import.stdout | 0 5 files changed, 80 insertions(+), 10 deletions(-) create mode 100755 macro_use_import create mode 100644 tests/ui/macro_use_import.rs create mode 100644 tests/ui/macro_use_import.stderr create mode 100644 tests/ui/macro_use_import.stdout diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index b1345d0b751..cf526409374 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -1,10 +1,11 @@ -use crate::utils::{snippet, span_lint_and_sugg}; +use crate::utils::{snippet, span_lint_and_sugg, in_macro}; use if_chain::if_chain; use rustc_ast::ast; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::edition::Edition; +use rustc_session::{impl_lint_pass, declare_tool_lint}; +use rustc_span::{edition::Edition, Span}; declare_clippy_lint! { /// **What it does:** Checks for `#[macro_use] use...`. @@ -12,21 +13,27 @@ declare_clippy_lint! { /// **Why is this bad?** Since the Rust 2018 edition you can import /// macro's directly, this is considered idiomatic. /// - /// **Known problems:** This lint does not generate an auto-applicable suggestion. + /// **Known problems:** None. /// /// **Example:** /// ```rust /// #[macro_use] /// use lazy_static; /// ``` - pub MACRO_USE_IMPORTS, + pub MACRO_USE_IMPORT, pedantic, "#[macro_use] is no longer needed" } -declare_lint_pass!(MacroUseImports => [MACRO_USE_IMPORTS]); +#[derive(Default)] +pub struct MacroUseImport { + collected: FxHashSet<Span>, +} + +impl_lint_pass!(MacroUseImport => [MACRO_USE_IMPORT]); + +impl EarlyLintPass for MacroUseImport { -impl EarlyLintPass for MacroUseImports { fn check_item(&mut self, ecx: &EarlyContext<'_>, item: &ast::Item) { if_chain! { if ecx.sess.opts.edition == Edition::Edition2018; @@ -36,18 +43,59 @@ impl EarlyLintPass for MacroUseImports { .iter() .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string())); then { + let import_path = snippet(ecx, use_tree.span, "_"); + let mac_names = find_used_macros(ecx, &import_path); let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition"; - let help = format!("use {}::<macro name>", snippet(ecx, use_tree.span, "_")); + let help = format!("use {}::<macro name>", import_path); span_lint_and_sugg( ecx, - MACRO_USE_IMPORTS, + MACRO_USE_IMPORT, mac_attr.span, msg, - "remove the attribute and import the macro directly, try", + // "remove the attribute and import the macro directly, try", + "", help, Applicability::HasPlaceholders, ); } } } + + fn check_expr(&mut self, ecx: &EarlyContext<'_>, expr: &ast::Expr) { + if in_macro(expr.span) { + let name = snippet(ecx, ecx.sess.source_map().span_until_char(expr.span.source_callsite(), '!'), "_"); + if let Some(callee) = expr.span.source_callee() { + if self.collected.insert(callee.def_site) { + println!("EXPR {:#?}", name); + } + } + } + } + fn check_stmt(&mut self, ecx: &EarlyContext<'_>, stmt: &ast::Stmt) { + if in_macro(stmt.span) { + let name = snippet(ecx, ecx.sess.source_map().span_until_char(stmt.span.source_callsite(), '!'), "_"); + if let Some(callee) = stmt.span.source_callee() { + println!("EXPR {:#?}", name); + } + } + } + fn check_pat(&mut self, ecx: &EarlyContext<'_>, pat: &ast::Pat) { + if in_macro(pat.span) { + let name = snippet(ecx, ecx.sess.source_map().span_until_char(pat.span.source_callsite(), '!'), "_"); + if let Some(callee) = pat.span.source_callee() { + println!("EXPR {:#?}", name); + } + } + } +} + +fn find_used_macros(ecx: &EarlyContext<'_>, path: &str) { + for it in ecx.krate.module.items.iter() { + if in_macro(it.span) { + // println!("{:#?}", it) + } + } + for x in ecx.sess.imported_macro_spans.borrow().iter() { + // println!("{:?}", x); + } } diff --git a/macro_use_import b/macro_use_import new file mode 100755 index 0000000000000000000000000000000000000000..61d3a827f1f77ecf6d8dd69590a42eb2cfb26354 GIT binary patch literal 2816064 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⩔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	(UOi+EP#LB+>D>qS+b9*V>({78Nf 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%0AhSlC;CgebPN>=q(i7ypxj=jKxsZ23rEl< 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%0D9Ndr`=Uzm& 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≻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
gpa z+9FprkLpVkH3gVJDZ;VCcT@HTVC0iB>;m>l4XCjGk-tiM=xCJcWPmd`mNwf=>Zc%B z3n4ToUsKC7r4eZ2ZePP2<8UO>k^=T{^CXFoBxI3KT9O(?Jv9~4Qtf1Z6={`w$dr#% zExaZXe?bY`k~Tchu>%zkc3)PK+73c;;u_@$;IXHn?rQa+0()AB19lH8V-To^M8HM3 z#XzQ!LIKrj|2a=qk8S2OAsm2=9bz+lPEa}K<Pqbm1dmw%HokhMP_Syic><Q6vJ2Rx zg#~-1sPL6!Upouplo9sS4pK#k(;kFfvSD=_3oqn{?%@X34|*=k)v7XmJd99)b2;hX zCa-OQvn7R_Qk4Qo8u)}MH<v^k@M-<R$Vt0Wba|?P5|fwPvj9`0$F(4&&8zb=<}D8z ztE4E3xv)H6F~BH!O42ZUJ}7e>)zY?mPn>DUnMWYq$l{0yUgP{gGjir}Q@=LNFQliy zLQ~ozNtpuNu{ggczxTua@e$Ka_U*VgIVxf3{4!L*66wWn2&xnbz5%%UYG3cDZtUJ2 zs+*yKwJZeTemLIW%06p>PbEi~gkB(3F{nmCb?Rldj=T(h4Y*b*u^S4ZC}A02mXwt+ zRlMvHeE?)$mtGQnfLxl2UqS7PBOMd@^kq!IS+(#lQYeMl%<A~J)gx6*BIL-FA?x=z zZo)IhgRWu1WTswSh`0&}hz0U)tYKo*D^1IUtR(gtVGq6`nEQ2upHEmOSW}c&v+42e zt%Av0^J#6p$|2o`6$6q0t|Jia@EHS=r0Y4%%_oY7;es+~!DEHoQu6s)!4a*4aosf} z0GBaPan7!A+(U!BZcQ;1X{Jpo#oa)6cHoFOuOW+a3fy-5*JSVyNkD)6^AAJq+fR}v zo!$5SQM25mhLNsK<XrKmBD(cYW=`pg6Oz)f$i9`m^u%JULSA0dcb6JaM!nYYmVUOY zsnvuqmdAC$2xC)-`;VOS1}7xnWI-uFWg+1M6^34jh85zz^T>(8`ky+Zk*K2~@*;w! zf~&oz&XPYlF=*Z6Vvz^M*B!PI(5m!Ta`)5rkFu^F@hs#IRBn?v9uUvg*xq+|>f|#g z2CQ9Y+JXKk+#5`xqQO?Wy#!^4P03kZd^$A$EGev_Ts1({u-Ac=B#DHI0P8|izYlWQ zi}w=cRz<##l1pPMhI{e>NSn`L4TY0DLZ(cfS!s&EqEsK>kbPiUq98l%3aG=AFvGEj zJog`2X(-lDad2!qqV@><AvM7;N)PRrCr&p5w18=bd?eyq#4Z4-rJ#%JSAWPnA<Y!J zh*e7;UBYJJ6d2pw8R+jN`P&>!!K)<8yE5uC0H;b3uYn_2TzL<(pHylRpcM}A@1|9o zMo7U12?`?=E2L4Bu#^j(^qtvq(sx@P`>m|Yc(FJcoTh|r5MX-Ts%(Y&j_$Xst095& zjqH0beUnQ>{%t^mh6APU0O#s6kjT|N_n9Wt0?jAD?o=`PCt}%@nUmA7cKs}*d$xe% zlyyP{Cx%#I(g`zN4s^DDd0BW&1q2EB1<5Yd)(B6Gq=cY<cmiU1wG6zO+$toaA9YPN zLI}9Vd419kqSR>kX*uDD0}?$j)<UVY0lU$o;d$O2M!9E%D?KEWi4v+7@$TJW7#Y{s zx7EkG+fiYEx5uCSSNR(y=ln&Adz?LZNe?W4T`tftQPrnNT5cE|U2SW&`z7DrWc0eM z=Teo~B;wG*$Vd~;tQ>Sj-k|T!EnolN9Vv19Mj?fJ0!#8_!pQwOXZ=KfW(_Ilsfe`J zQ2Petf+DiaZ)V*5?fP0>-G348rhn^xTQbJw6Be-90)FbF&ihh$r(g9>_fV#0cN6TG zsG2P}r4X!35{q2f`hwNZ&i18}BNea(@2{@D-Tx}WLWm(57V@{KNY@KdUD068$<@aH zN@J?0j6+1yqmnxup(jl8_X3I6Qxr+XLz1d88ug3xFW2YT8LMi+8}R%nsb|~;QJ=HO z4g#JVfa@7!NfQb~>G*4PN3qS#$8Qh!px8Jp9Wfgtgx6|35>enBi9wYbOes=!sRW{u zC=MG023PO@rB1$ySDfExlhDlh7hvBI?vbtgSTmJue)<OpyePu_wtB2ysjRB4Z;q@d z+uxA=C{G)0^(?z2NkC;!<_id|Bm+ybipwr}(RXbnguHZhr5wNPQ-lP(EyF6$1-Gv~ zT#nF#G_Jw6N6R9ACzT{RW#mG?_RD2*@eA?oknPdJ@l&^8zT*X1jR!Gn+xzcaDwM5h zF6UI2=1=sRNmZN3EA(%*EQ7Su#cN~~61C{TkpNpJG6YFqmUaXpik8&omO9iZf>_z- z*4T2eIS>B6RPxwBW&J3KS@Uv}nG833`R%!q<UtD*FpRc<1qUs#O)G8GJLfY09H>fQ z>4Fc#S+2p>BR%QT$yy^OkqI(+0^>H*^2M(nKAV*sN9e_rB<0lY(@n<*y{4-gtTaG< zl7fmcA{`9~VMr;=6^oT7_Q3#`=H$(8Q*m_dwIY!$YY<XPXrjVEydJno?2kesXtQ6{ zDRFY8Jd*{mf~OiI5_kc;cjdS0Z{NvZL=cKuRFclWI|xxOw>EfZ>~BnlL@;;78_s_H zOeK0F%^M%a_ZpDopNg|M0xM>8?RX2DbHu=xI-FfuP>KlL0<H<H95q<Fz0W?7v)$_P z)OXk$U}`iB6lLANA8pxth%3J%$JW%r_9TbHNeve%H6wr!DHpZ<eQ4q(3omhDAg^H` z=#mQjz%RD&U>o6V1TX^O4izOXxPebmHn}YX)5W5W#4<Crc|%}o;fw{}kj%y$K*=vN zz_S}7hr<=d<f6n=-+*yHZU}J*5T|<NnBIlSPap38UVVJ4(A8jrO-R}%&HH9|eCo-& z=KvA75fDXi2EZH61(wV1tWyoyw15s$2e?2ZDk!N+cj|!LJv9$!dl(BT^;O6!{-*<; z0FfwyWsQKl_}8zWNHDa^8yH!yVQ{XmH4M%xdE^iOhhw3h?oMK)SWMal6@@^l)@=vt zk)*`lSfkWU0KhEpyD{D;r)CWvG;!|X32P3VLWy%U2pm9L!BdBqLUCRBk8E0vC^~fD zkRDa?zQ4TeS_C983tf!6OkgvXAKmnwY5&je(muz11XfHV_3IQuj+<-4f<*Vfoc%zK z>kVKKfS((X<s@6nD;j4T{K*jp!M}d>_VHj3!&g5)_QhWyk##sfIXhwc#J}&viL?8# zZxy&)1gr|7+AJYQp#*pIyRRnC$n<@hD1Rt18(c1ib4<2KEO9tEoC9!`660hnUAQWG zeRT!Q>Jg-(VNkE%Ki&Oul-v58sUn8U+|jB0a>WrB^o}0U4{o2PWG_*&B*o<1LH5UC z^Q>t<UZ5zYCJ!=dgcfuM@DebYwrcwot2G{_O?uCKzF-N4>WPKwqP8q0bm+~f+zv|h z89yXvHY`ce+NouwC~n_YhMBh`9sxr=*{1k-`&y#q^XFs&Jnw{-M^{%1uw3)iP?|hK zZ<R{1f?A@gsTM<2gV4i>l*>_nWCZYH6xY|X{tCoP4ewKSN<(6H0uaV-peC3=C53ry z4=kn>s4GZJ^|Q_+(Kh!N?Gzq8(ox77$hs<TdK6!`Q{oz-J2nMzK3faHnlKoH9E@6M zS4+v8!ImW2%-$V;9!`N5lNpORbE$yctJn^>{7~8v%|w5}<B#cVep9IuZU<i@hMX|+ zO4GWymi{HE{ZMmZwMmI#;l$8Z-ZYhgyjm2{3sExG18qWin^rNyz(sS^9uAvEOFGZ} z!@g_9B{IenJO|wL1+vv-lT)zXwb-of{p~kg4acLn<mLytugETG(0ZYRgx3_K!avAn zgNZR~GMd%B>_`wf*ij1Z9=L0iw&6)sV!akl@#-L8bwZp)22@8D4>3;309}20Sl=}% zmuWdB+XT)@-~=dd14*3x9(C_|(4Tbd>dI(oS66?1x_R8oQh)c4AGGEslloewWiBrK zSMBp^29;RQP`W64gm8%?B}D}cAsD>yau~s3pP0fWXtcBMU-Zcq@aq7yiI8M<>;Y{F z>VqYVF##yzpVZn%oQzva4<EVqB=`x2bCSWaOq`HHDS<C_ADHyJbkTSH*>NV;Ui+J8 zc6foQwLvP-96GAXBUl{^NY@6R7nkqTq5EGb7)#o7VVep=<<dKJ|6kYWfI!PuX;A%O z!N86&E<gRdahfrp>ua-9h{23I#Ww29hWfnc+484Dw%8Acj@%TEgMD8n<ohjKZFoWU z+GHdh%oa77?;!M(8zGmvGg7CA!~AHt<=gJ@{e63kCM;KSO0`TNo#?}R#K`eMC$AAB zCB+`P)Dq87D(Oky6Kb0b-%!VYdB-KPpU$e61iH~K@o?tQJocvi+wj?(Jtodl$yoAn zcSB@H1veO(b%W9$IM)0KYwe<5%Sndg4_HE?`DF5t_c?0P<0~E#cBrOpr{--$!G?0E zND5%!0}$6Dj}MKV5@FW;hH)~aRe@Bg><T)N0aQSCMvy>H71f3faju2R4l~J5b1|Z? z0}I6KdYA|)%{@#qYvter7pVa8IaJaD#z)?xWFT<b{42`e@6Hkon|G^V{ZS8ncyHDj za{SQ)LcBy!4GSpB&{cQ8Pnz-e=3u6$lc&PWIXydx05Ez!1<)db2Rb#%1CgxLhn_1j z$iz_iM<(FmT}>|&8Iy6TGrcr6glb80R+=U7GOA4C`Pk+%cI_fI&Q_d~@Rg>rVQDnP zwIR+{ku8G{RQ>|~?YwDidrXt0LMNugiV#!)kgvf*-iDNiXy1^3CPX>W!6Ol~Dvj*i zxfqj0PD6Zyw1F$IuOlMKA$+@|NH`()7PKss(2y_=3Q$*&cByrhFL$Ljl&a^z8&zy< zE)YG5gTi2s$m$iEr6J|VD2aV7U~F2J{ytYAULz<_V4dqKctCJuxw^ob=7TE?%}3?j zIr@*Pv4v5BY*4Uf6b{DhF;~jSmp+B|hMuh`rh!<+qc3%vWA`=<Cm5eUd%FTtkpfac ztsRjbLgi}0UVgjwArg{!71bB8bw(Nl=l8lL$_nE>gH)GljTS6#e^c1q9d5b+AeODD zv=GA^n0Nyi{rk&qsvUu&3UTF-tzC8-<q)M#?0dpX&aRiLOK^xNGs7;14$JI5=b_KB z=Y`J_DoZ#rK~93CV*Kis9k0(XUEHwU!9_wakgbT1!fb_?Z+GFn0sAB<swM>wPj7c8 z;1N&g<y7*kFuj@V*C@EHe(83Kg=qKm@X#H=C>Pf>rYn(!CZos&lq(U;OAn57M50YJ z`IctvTmM2vvK|nFcoWg)T|HRQs4X@Y7AX9>vp16IWI7A|D(sMeYO)V0m7ufp$2N3T z!4l1<0-W|3PZz#sTsFA`25==z9vfOWs>3{EB>~~t$)6ULj<^e+U8;rQ3hB(<``op2 zr=t}v#JmOTKL`A?z&q!x-SFVh<@M?I)^2!Fx(+lim_Q9-zZA+PzA)T&s~f>tJ9nc6 zfHq_lJxJbXR3{w!VeN*;Hnl!1irdi;1Z{M{6izegs>GM<+6|8lt)I~-K?4h!T5=K) zzfH*XIB1mG872Cpm#Dj>Tb@$SqJhhfEZ?&tMQBQ>M1Vygi*SAF_*<zhUaidEKZqau z>gsRmzngW?ZK<#=;y%rQi_2kSNDVcp+P<g5J1Nt&mpbXR1Js}_>l*4>FwgP6sb7p8 zBj)1uwRJa2MTPjr?yj%D*MBgN=^^3)BsuL3ub6+HEycguI^>h>{&gq^!<5t&H%D6o zJZsYaFg)s{m%j#>dVlxSxlu?Uwz}fmC!#GZN;nW!lKIMHz-N(A$_G*{oDxt2k0)wv zS7tz(Xh#x`M$z3#D#bO`nR2PjO@Eh9V`ZCf&utJlz4Mz^aY~p>-AK~WQlehCx=G1& za)6SR@n~|_yr~gB6tv^OElBHD<9T+U-agf0J;u6iGO1uO#awKVZn<EhTIsXar`sn1 zP$yL+Xz+BWFlB;g=IH2abL_IHz||aKX%VGPFjQMCa7(eGBF<i5dh`UI=+W5&POTY% z47kUjA}Ya>QseZ3I+v^~?hugxhL2QDr=Aw6>*&c(69$Tm^4jy$sWX2msA>x;gcRIG zC(&gSw%qZ%EXlLGDjCL;uIf)xWfo8<1SBzcGDLV|SJzh13qEqjp!{h-X5c2z8b?`O zd);Pk)frfPK(N3>57r?&ZY^`maROW4T={UoHD8fXh3M;)HwP?VHWM)Qc({S=qdk)x z{4c~O|L|1&pF{Gm{fBW!Nd;{|q2%rk+?FsirDcO~S3o&l2pKA{n2IKf>r-qlVU+{E zVSM7%_=!K+Kl(*y_FoOI!uVHv?3Vo{bBzbwc`{dUS;Q^;jx9UJSBjjj(DY|Yyt3Z> zzRB@hw*r<Zd3nZ#=Xb$#=V%9}y^#zh+W7#O^?1tbD}i=oQ<0HYh%b?9Zk)3&0nC}L zNz@a|sRXo>%AsxvE4&=9e_`~~)r@$(?#S)Kw@k)y34S6eA|z>u1@XGNySsn<u_F)u zzIk)^gH(<W5>}NsBr34Vy|+75tx6;km^-jb0KQ2eyB5*vKcaH!*{c6ZDgMvJSGq^$ zu0~_Lz8-!XH~QMZ)B9h*c$cnI1S)t7HN@X!f1~!RUlyA+VO8}l$|^_N;_-VcLxYeK zuXzF=C6zL@5G+rJ7G?@ZNsTScP7F>Sv}fk*=<xOyEfpG|EYvAch!dj=v*!<w?1msu zd!WxN7`0jq;OX!L#nmoP9Gw`R3-@|<c!0&0)Z|h?-v-cM;~QCBJV5xgg8huu0~EQ4 zfO=>E`Qsi%<V=TWa50T7&NV()kN7Sn%OnuLeLSeDpMUFaFqM@<d(h+bWeO2Y57Qdl zg}{^*olebraobu)!~g+7CMYwaU=*xu&=H5DQWq&McECr0w9J83J~7*pU`OqPsYRNf z74KGmVXBLtRf5Bw#9MMB1e6ITFtb)VtHkM(-HhjYs{P0;9%>tlCjg6szyfSW5o5$~ zN(FhvrRYEM>Inexao_Wo6B}PWy7^#-8SuO{KpY`RCb76#S9d-Q|6Yp$KrhNdS_KX9 zK7{PK#W>s5Q>y_vK#OmT{AP3m5?E%du^-ps&54zG<D`F_l|Y0OqpsmZk&jbQdA`05 zZ_cd3siDCDOV|!bYhf-+1QTwu(ZHb|_Su_L*9SjdaDCwTU|&<a+h^dLNwUJ)E~DMk zo9xu^pwoopfP|Nl{9%fr=fiWZk2j~T4}QF0cx2~?NhrC5;C+ICb7FWexju0B0QbS| zK_)91Nedg(TpyoLDn<&b6Q-t^gGjE(nS=Odvs9c0rS@EX7};TZPuRc5JqBhBm9b(u zW2`{OPH6`Ptd!m(vaGaI&cjKTg>7hhH7W-m*~pO;6B#}|b2Z8<vx21yu3a%KxE2fc zdy9#Vw4#GAZd+fwq@h9e1X(Q5TTy1pTVC9@c4eS&Wu(rBbwSv$D!9_k<;F6uUpV}D z!BNS<Dx$nTZ}8Yry?#Q|qTT09f}(4neC^1;1>UZeioltmlN*(F`Fv*uJz2aoP(PM{ z=Svl(>cg4_@#gfUwddzyJ><`;W{Wg*$%@n&2(uY*HZbBq_<lloo$ev06KBi2y$d(O zsmW?^u%2#<Kkwhg(QlA*2IGUJ{BbX&E}Uz!O0uHL@Z=Ck!uyV2!~QA@<weq`=I?iW zK`h!%Tn{HxK(|@IuupX0UNSF~mQpRLGhB=@=ha_uQK-pIb&N<nTFbISPXnquo|3;k z=tR?~=Px4GcE<5qld~AXCrq%5f^E6LoCkbI2wyTj5cMZ31Gl<AxT(->3(~lYh_Z0U zmpbw&=99RWcI3O|u75iypM#k4e-?SI#%_yW<zK&%e~sQr6p!RjAkV-|$}3W6rM!kd ze`;Dvc*9{=<93W9$x|ntSqLj%Elkm8W2l7C2>%2419<l0LXhaXe@F+uww?GwRnc(- zrv-V-6bn>%RU}jhwZ`!)4r1|JER#RzQs#`N>VZr@km<9`!b#~2aee|LfE;E5t8d>u z9b9p1t4aa_lvaV2$kB#DXKNcVjvu<fm(v`lfLt3L`R-CjYH^~y<48HwLJpNE21{cU zj5q;gJnQ`?l|8`TMWhqQ1eWQN?rTTu*-xY~5j`Mh*t|GeVy-N=fM`-Yw6p+1ynRun zEHowL8*oX2aY5KdvJFff?UJCALNl)}*jBvhAl6^*?;qYiB7sc}v4MWjHu+c%r&^GL zI3+Yc^GR?wAat>m1XJfj2m{tpoDS!T`#$wx{i6Bl4fYeM4}X8ZzcDx1>p%W5$kT;F zhSRs0J8mdGJ8Bt|5DH-m3-Inw#;upndXi<OeqCOE=VYzygw@5~C@^gGBZN=*8$o-E zu;hpZaSe{ukJJ7R6K8ro{r$vv{xFIPGa|^G^d|oU2Tt)UObWD4OS}OZ7Iq3ipU9Mk zR!hSEf|mJoXVE97UHmjdP$%kl*kl{!8(HHGDGO;prUq$a+#*x?X2gr~_pNQEQM!+R z8kOBOIS=~4{!w_O-aWoQD~Q1j3bMMvfXILib?wV7i;vmSf@Jl+z@4VxfvJ}VWQjd2 zKlo*ZF`@1ggi`pV@n(?GlEDkZ?a3zM)>HUUEBkcFCYIehPRr?jt5dh7#I*`Ik}Zff zZ3z%Zg>vPtpk6(>r&c;Q_GfLGa;d6frI<d#>X6L>$4y{8%mp5oEAPvL&fEB0SB4>} zc>z^SHHj|7dL=7-E+++HMoPc5gLtBum;>tOLWm@|y0XIe>PnTR{pbEc%$RQ|yBd}1 zi!TA&brL07I3B6T!@C%jI=9uN=t}b46!i^N>FR31SYe~G`Lvw^(O(4SY!d;GCnS`k zI;72yGdP=J0F?kWkb-r}T2tr_g(o1UG44-KH`J|}a<vKSj-EPu5iX|*$>3aTgm0<= ztIWfnhQvb;c9TpIsD{%n3gNfMKGI{;Db1J97q%TEBwp917$vZ9ky~df8c%B9$}&EJ zk07sC=<j_VQ1T7B#Q<w2du;6_ts2=e$^f;)RF9TP2$`fB-4`{jiT;xlP1O(Bg%lC7 zAD54koFgqVE}wgf5gfaj86-OgQ05HuXIL&v<2HN7AutV-07601Ee&(2LD18c_##Ql z%yrWL$(6M>2QRajWO6hF=*SBMG;BOZ>+3pRWYR!DmQ^np^bokGy)miXiV5#DEA#H^ zO51nyldlYWvFI_`#R<R%sxAaloC>E3TEs#SQW3)jYDs$oF8%;PyvKcYW4;rH5Bl#r z{XtyIxLvXqZj+Ka3cWw|e98lmX4|*5Q$Z?f@bmSl#55qXmC9TrmgyOsQOfyreXWLm zeXWP?`V|)+aIPx8s<FR5tuus5eiA;A%m7uB$)m@4`hI(@vLrS;xLjj!TTxp>eJh41 zA*fh*BQO<I>5~KdHo4HgHW&$?*^IL{Sy~m~`<F@E1}RPiVq}iwnCjGew&pjq5-a2S zo>q-ARv!c-4nm115D8MIFeDJ^VV~)r&Kez;^~>zc=}V&xGyUcCFqd@X(<3(L9$T3N zP`KjbvLqRZ7z@Mw=N{|0rlSMX;D}B%2Zll#GIGvU4|IWm8Ger}MXw>Br+{u*q{@=R zWsW8!ub;Iq0#akCvIeQBB^ge(v8zUF&2hTS&))#bn)+1DIdhD3UGk`ztXNU#D*Q`W zLsd^fxmGh=)Kuw`tNAj*&7w`-UC&<Y68z^8pnU)*k&N!%s(`(Y=;vXm5i=A<IY*pC z8F*NtsOxglFeDJ-{61^|54|GPwDdm-%K3<2ftt-N76JgBVgb6^v0UrRl__yZ3LF;d z@wj^g+!SPS%AX&ktYmlJ?;bzg(?Oi*MFtBvq}^!-pVzo6RlAeG=Tn%ei+n@FiB5q` zax_ecM4auu*f1du(Ga#YOrV<hs`xZP)Dm<NdyW<x)-m5L4Z{=^!3zRm6Dhc`Fiskt z6!A;?%+@ZGJDduzU517nr7mhja{PEl$OPQkJ%y0^zq^}zMdgFR0O%9QJRPnB@>H<) z)pP3iSCTOD^PON6z3y;Z%U{1yKa)OUC&X>Nu)ijzc@mpJ?S$WkBoR2<-QoIM+Q9Cs za+2NqPGHqCaFt0k2jseg1TGx5_3+Hl1=-rNE=Dh&NKFNl{H;K~dvbHHXO>_27I`|9 zqC*h_tq*^4H_~E1RZ)%UCxjY=YDs}1ceJ7Gz#hNhnOQ$$dYDdjy;e$fU-w6dhCZ(M zwt_DzX2s$>Y5^2*;u>})<O>Qln@l{0N9jP2!Xa8xY7~Jui(e8%ZGM||EsR{8X9svY zj0*z7B)F0a$RAk^X@Zn&bGh=j8Su6f&9xm%Cp+93_FtAzx4l)OJS{-)3^2Q^4E<Rj z9u2RvWZ}9689#Qn>Lh9F2M)dlB0eDMfP^nAlLEi3CCRH7F`|>{ahE3emKuSG0f@xa z`<W8im8(-q&M^3c6f(lbLIn`RS)0<IrKV6}nO`=g_PzD31bPNkj7?hLu8wW#qnBDh zpA7Ge*P7?n8J}@?kIYhPQNqboPr8o$2@)Kr5S^SbnWtx*3Zwh*c{X{T<WgBiF;$#} zFiJV1l?UVtmu^0<dAKOytI2U5)d;iNxL0KVZrI!2)LF-l*F2b5C3v$@4IMj&)VU*F z0Xr4nFssuinCvhs-~nLwdE#4g-CX%Ce>WnU9JwV4UJgH75l-F%NMM33LCMGRxEG`C zYELYPU30tZH4FL#ZmIwu5wTvx(|pa;u2>fumUr0Ih{*+12ULFowAX^n!4mXkd<{Yc zZpUrcZS{bHz|?|90Dm~wr_x(!@{G)L(+lkfY?{+nssVohfWt|3OV+hf3Ve$hfZ+yU zs53{XEB1V01$|XTv4&(*rZKo(dM>nfD{9xQDYb~4oH@w=MplFGg2Yzt7W7SLTCpVz z>i8nGwX$N2JLJ26c%sRuej0N;DIuw*aGEsj0L|7-m!n%JB`YDr0#x-F<qbe(QDoN^ z&K}IK`Ltssm=By-IQyd4|H;C^KLpNQ5L53=rLUtzo;uPJb_w`D5Wr-?@m#q_T6NPo z((3Q}%>I1(Nb|Ej(r9~mPh1swgU;eosM;O-j8jKXoKu%^OT%8rx<OyA(zB<h?!??K zY65=yVBVqnQ0)WLG|m-AT-qU=Xn%3-{Pr<(p(jJ%Nn&)Z%(<>kt{udP9f&qUa03h= zcZ9okdr5q9)=vH1$XjxH?F6|Wu;LhAIHOTV0L|nOY(;z{&czFD-?IaM#@f*nXYJT~ zU_d4{^o~(Sdj0$ps}hsU(S|tyT?@o)_&wJTo?YW1xk&p;&mTPdqJQwb0pMcGsu1?e z2J;OYP7lCH%%wcHb%}{t6m=EX9;lV%(HP-tB<50648W*M6jLh=h+26?%aX(TOjZ>a z5&X7c>dLbhNK8F&EivIQg>D_t0$71K-%eqt-5aY5*EOJ61E@y10x=r_pF1xx-Bfe? zflE)Fzw>(G6vB2*$P}h1cH^l-pClD11qOoBOsK#8Q>T*GoKvU%ZY1XEQ}^?D>evOq z;DD3fl9yW*ZnVVg*k_zNdg7cqNItU=3qHag2@4b8deNcq+phr{04o3z4^S5p;UAw0 zj!W0hZ@(w#7{DFF-i8p!#Z7eu+EjrJni68oHt*446C9WR+L6%iOHBE@k(iG0>VCjV z%q+1IlT-*|7Il@9fF4ouJ|Flq){dSzYsXC|2_h653Xh#h%J<f8_27}gMiwh2qmZFh z6j7}oJS+GFHvJ-1#lGlEOm6^bMQ&hQk^2uPE6Gcq#9XQ>SeKZ>de{@viUCXIhBAtw zk(f(OtxL=>0+xr|ehvgKs?PNuy+C5>fg4^MFs^{3fxZh$83sPz8><V4<BZrpHUBN# z5Rmw+FPv33E?zkM;)#U=(SYPQDwhlVwcvG+18@(;^wgo66rkFY;#Clk5(kp2r>Onq zO3d-p{e1e=@v}X3IV_h%oG|#gI4kR6an0ptoH}~uoH`QDVFtr(5lKObmz-dP@(GEy zcqsh#BUl;8zQiX_6>6U?=s_piUtBxCeb5W=03iS%Ba9%y+_rXcoCFDX1?BBYrC?%b za{Pq3Ja>aiwx~0yqzZSik;FtnV%#;(hO$?@TDL{ZPMzdMi+u7CDriuEU>>c=X^r}Y zk6g;mx1W5W<3s>u2!u2^`4GsBb8CmOda$8-i0L4114>H@S$4*?X!YAQ);X99GFhvf zOa5s4s(-X6gUAT81>DtK+)S2WvD>9Sb-3{ZCDah&AkBDNNQdoPGW3+1wCa)M3;B=0 zdE*XHd>76A?JbBp0?-Z$T~SNHJUG;X54`g1tA45hn#S|t1<-W}4}szXU&`<Sa<8C+ zAu|mq4{UU9h!fARe&oam1fhhi3i1@lA&WaS?coFdXkUSh?JwK55fCA3Lh?c5s)r~c zL4FP&n2&h=k-^(}*(p+qiq27O!VYq2IF6}DgAL2s9(IqPI7N#aaQX$z-;Nx{yoVFM z>0ERw`-Rn06p%wqM1;^EMr0$jXKSbE&-*)o<ZVhu?m}-Vfuh_``XO~%F7-SkUIRQ; zus(3()gFE%?Vt1`0lkDt($#oCv1d=QjsC59tZs%eXosj1+fZXr&pc}gDRLl8DPh4| zpDe1dtLsn)-0{c{DsV~klER{M>#*bqTW!8+nNm2Nh?>>7laRA(&6^pzsP!Z#Z56am zh)nUHiFUKry4^%miF9*-h=z@j1*+*=|c>&=_aU(`BWBM>9NT@Z&wfVXPBb=&!= zFgn?JGM-=%r%Ds`q{mIM-n{AjMXjeL$$7Y6@uA=a6DsX<Gd~n>Y9MSCx}N!y*Ug5k zLZo7Za7Kyu%B>@}mWjwo7<|?i9a{0U;3ki;_v#SNBm#Vn<8{oiSr&~aebYJ?uMGzR z7f@|eY@9`4Z%UT@aLJMzTq=@U$r6sW;WMZJQ|@X)WSJ(7=H?|`J_5xXe|iu`03N)c zQ3E_zw&*@!=HfFXGgyFI=%$x7t5(G2z?5W`;U1XJy2_-xx_Wz#|1yj{rV&P0wtxWT zIVcr*N`(P^@t!bo<c&n0+l*@vJV}UxwJ)szd5q2<@L?0XhRUk&qw1K8p@7u@h&h<O z)(?rbHV8AgHO^;mQKD|Rw<ExlB>p5Z&9!4_?{nu1+6-6<jL(ivCQeF~DiA?-D9o2Y z<764mO3JR(PilW(5-A#+3_?mG0C?vfh4S5I3t!?x9oqs&B?BA?x;!9XG0yZ6xx~9L zwnd#OB@y6WNCJP@xo4OO65(6OY|E0deaUtf8fv&_A-5|<7qUNIE~#>vQ{6204|@}z z5wOkBE-@hUo3v_bv!x!{Rse7~r-ct{HFcy_@)G!~Xz?W;B_T*+wjvB=)m@vb(eJOX z|D*cL{`mNYn53ftBe4pdg*`|tM~l(lknay6Y?U0Oy42tO@h?A6`|;xsx|sS(G*$J> zkDYRan~q5?Sl#6nnc3p#)ebLV;IiO-y8b8CqJJtcmk0mDJ&7n9O3Hkt!J!C922<LA z8e@^7^@)%+&rRpNMQ|kRip<ia2dWz+W3}_VjB+NA3&~&#UR{Af@$V$_i#+{ln2Wjc zI$gLBdXcEjLXr?uspC@L$#f}!UW@nD5d!(65JCMLe`MTz;_U^Wh+s@<$)S;W0l^wA zx6Iy<#;>nw{QCOs{vnKi6rv|hpOtHKR(E2W1_|h^PJ?{C#)PxDO({+y&I`OLp_&FD zTX&l(NZ7XzH~Yt*y2CA20+hLmdtxY45_s9a?C-kcH+LWDfZE8JOT?jpZ8u=|E_N;n zYmz?5%)#RV=$F^I8IY~|c&T^T@)Q~HU62$2-*x8eXX>R^*n<|kMTK8N{F6*BjCAtd zXLI%%2<4;6$e#7nmUvlc-X*+Ukv*Af#Ml&o?}WPU|JmQ^6y)=pnMxVFqgjl*3QDw? zu1d@LXzNL`EA-}(1T9rOX2r&a)`6l+67b*!6pAZBA4%7MysZwuNV@J1q^6R%_-*xA zU3wm=7n6V;0Y&Ub*xmGO{|NzND#c-eol8?AX%O671vU(vHA$?%B;_CxcN15%_Dh)i zV4G~lx8XPo@D#vc3^QGyfiacqi_`co^-6HuuCCN++IYnjI9)-EY_OjoXiIfq<<m+k zAi^^Mhk-Hy?UecjcdPr7DoPwl^$BGF$-gW|M2Z0;#W||>SaSLD0zUyROA{C59a1u- zm-iF)v&ALVk`&5ihq5SXBghUT(|sAxR}i4-JHJqzMQ%~y^8Gr!qk7>PO3BNC^9C?r z4xaiLVn?@o`SgHJ0S|SBp${*7*K1Av)&DC!|1Z_%XU4H5ct?dO{xq=4;N_h7(u(?N zf73z_T&kH6#mS+f4D&<)x;s%x37~VdEEVOSr2kgnIwXto&km@$fDz{i6lE|@@`8P3 z#WNS{lwds&;XwYtN#?rhw_@p}EfHrb@mRzXS~zrC#B-rnul;zZ<bW0q)g9cb+_L;r z{YU*zR<^!{xnrZm2#GI}cH01jB9UU_n!bFu;7$Q&fn6@a=3X+ZWdG4UwN)~=j!>o= z5~yQSJ#;_c?S+_4p?z%Zu@uq30N<vR*25BDQjRb0F+@Zlt4RuC(1E&c?3U-Azl<7K zNVWrx3&<F?5lXTwqW+%Vtq?smyef1vD4C|hC3lskscOd*?%_XpE&sV>?r;f893t=V zp*Crv&(!BpA_bg@6b%eB?rHCqP)a0S9~7eDAG|%GH;!Icy}jLy^DX(82+fUqrljf= z1S9B^6QCFxt@N1O<8AiLRNlfHjn5<mOab<kPy!m9)4>Ju9NoZ6J!t^9>|+x3#K#O) zk!t>nsIuT85}`^$GC&{~5&o+2)*2RSNtHE6*~(U5nKeHy+#4P*-(TlMprRbEaK_Rx zs!>(^bhNT5MyJY{%Fdcx1<(z3|NrFNTVG@vbHoc}W5E96$e`Y4^E8@`y*!QPM}0J0 z+s`pTu@SWm8YLS~2Ux*Gf7xwBt*AcIicsO21XKCr*-fyQXghPenb3=c0KuJ<?pHv$ zy0fFrj}6QxW{N~Ac<eN4cAldT=G4$jMmlp5)q<Nl?)=B<_{;V62Y{78HL5=Roj)A@ z<0s)h&}*Tu4K1by`^iwZTxvtLNlq3^BP)TkMA)0Bwx9Io>PmWZb)~wpaiLquMl8q! zLF27SM^r6;4)IUPs}%q7AyQ7UZ``Srz2p+$e80cpUyNRCs=}3vf%0mPissGnn`5)z zgKR|wzA)$htM~JtKl0CSj{koD_}%Tp<44aUp;Kqn6F=R*ebhR!XHNTfi>*vMZ}3V& zfOxYZ3hMCb8-4B6+2KpW-L1FADmKfafNMjFHo=Z-NeXD;Qam-c=A8bIBp1rG3t68j z6XSRzF2xJIcN8DxWRii^hUE%A#&}aN>*Sg_PJIxkEr{)8Z4ggY?0vE0kzRbe0FB1J z+QA}|;WwxSJ{EU~^Wo}ns6HCIe4FdQT7+?}J-E98amKh;J1maAhxG%IkwZhG&$jD% z(OaB27%<3OoUf6ampYHq1P09tFN2)yQmPh3G`X6p6@Gs^N6odkw?XrThz|G>@?tUY zjm`Nd*#j_TNj>8?hj+lU-aTsnr+0*vN6cdAtGu0UrZbhwz!Cs#S&?=KoY;KkRLkV4 zMEwmD_r2ulTsm{)+etw$bu(b+apmccoRSl-?;rNvDH@i=8SG+eNGM>ent(DO3F+~e zFI?pi4Tw0odvl3sb_?mXXx5keDvID@H^?(AQH{e4YAL84B;RN3hNy;G!s~@qYUP`w zE7-js29YkiEp<&v_3dFxY`g{ggd`-YnBi6dk|Ndj>ofF)jxudxUj!aNmuVC?%rHhe zHruP8?wFK0t^u%i!9Nmn#yWe{DUnld)gf2wHi3K1l(TX$OqKJfOhc)GTPc7nlgL$U zvZxKtt`^Lj&pY^tcc?20WJH{xsrm;bECv1S6qxdo3~W8gd{w_JI?A}0wZ649m+b3P z{_52ZL?F?@yoKW$g)1(!BfvoP_=BW=M3M2G(CAjb0{U}AopwedK~IvJ{>n)nrm2$s z`u_HzdbFqU=jG_q>i0_+IV&<qOEO6DOmQOJY1Yg5Ql-0amt`tUro+(#S+p5e2T?$& zD3x4*jsc-(aGy_p^#W~c^{Z7*(o+c&Aw~h{$CDi@<8<}e|Is>^t1lpyt(#68*)yrJ zI%B{;;fe-vF@`tD=7D=GiCP(PB3*Ogz1lk2<<#R;_@*h3@1ie%lqk^*$w?L`2{k-t z_5)!>d;eOW$iTg+Za$@mDQ~En=7D1Kq<veSQXRabwk@o=I@z#G3D_fSD|n+}C-mjU zFn}eGkQ&aKBLh)Bj8yLRlZuFYidX!ds{_C|qpE`FdP40nbO1{83d2i8)h5ZS<(&nQ zl)p)IoHA|mCz01Knli+uz;lxeN-kduPV8AU<xjqmz9z*(M@?_;k57m0e_0sr31Tjf z*}$r(HA?l>u@VTsRlG`HlX?b51kz`0!%HU-$dQJCJMgwK7$iB4h6yC~C)uE%V4{Lk z`_0|nTDMqr30yisB<q$L)hr}^qb(}revsKuU||0by}o3L5CPBI#)iK^@8a{<-lc0m z^Z}T7sqLps9H+XoNng@y6>T^T!52pQI2?9e)x4J+G=L&=QjEw`slq_Q#O?#`J>^`@ z&!5<T0x=7wXGXngN@YHgVBuk(NQf7!zMoq<cw+Rlv;ESY3GkFyT`UvK(?w(QMJ`hU zwf*m#j%R@jiOl1PrWOUdN1;ZvtD-lm=mQt;?nDsH&we-%*FG^WLfs_tmVDSlOvHFL z3d@!|a6A|~<{$#Z2VxiJ-Z9syf)hudO7rfY?i$Ty|NY%xL6r8=t!zrCn{2AG(h3XS z&WR4e00N8+BCIYF01ossi|qa{>f&Zdj%fV-I-0=`391&ETa=AZ1h(8!UmqEJds@!9 zdKKYI%xs*LkbaXwj1O^g;KlT?9ulphGEeHe{>Lxa2xC8EvgPwb2U;AUyrd`-P?NG` zl5*f<iV*$gHzR7T@cEl^m#+Fe{PvSaB0n^a##2%UhU)^iB9V4R$`8+Nd5u@nek~3A zChp<PDM_4A5FXCgW^<}~>{;e|s7fC`<)+yp!Yqm}g|~2?1K38Lc%_n_92DQ>E|qQ$ z<<O<`ew|CY6(UyKx}sQ_V$T7}PK3h+yBPj?vd5aXq^c2;gxM~(JIDH@R`<?}G^5}9 z0;g`ZdgRVKE7t|$0&ghJHHf8@GuD&qGuP;F@MT%9uQy41Up$Owa{H<_Z5mU|q2f?! zEPyi;+2oijFHsFk*GaCo?r4@d4uO>%=PjGv6}epxz6cu?M==;fBIPE-nw`a|SHQXt zhVeV<r*#v&Y$FFVt>!iNz`|$dj;Ps9E!VV^R>-hOPEiFG;>hIxl@@|*ra~xYN0I_U zo)C}-+UpRw=CU$0p5F<hF0Ay!RS{|cHOr)<w5AfuGXjxTMfmErdf3^u^0h8pt<?jr zi(?qM51l=Tqz<+CilE;R>cN~X?j1yC%&h%<Psonnej4?oCpXMs5ISd7KAYcmkMHl> zW2CdoM#W6llSK@ZPWj_@PdYu3^(3NJ0)_)BB1jL=T#`}hJu*z56e&#^Xbmh+7~gbN zE9|pE6nCUmApa<11~ZIgSLhmbi1-Tz1<0c8Bsm#Sz7TYBQ642sW9||W1FmQLA_tVt zX<l6GG2Qu#c`<>EONE28%*fRvZ08Sj*hE$g`Fm6KcPg>0<QNCzCoH(mbM?$zuB^H& zNdT7gda!n=)1Z!936D=4b_0ro=p`}j5<E5l4*eNfm;iN#es6t%Gehk`LTN*g2O$7m z;V1T+>g8PDwlBMces6avU~VL$fTE8xyd>Ric2U3hB)n*T3NPhn!wI@nQNan67G!3^ zQklT>;*@ir*5PJ;w1V_=>KStYAVM&IIHCF$)&2`3Kh<P<a$<BCTyWE=gLkoTd6ruy ziKu-|U;%0%BLc!t37*g7i2;>TVE}i;RH39oX|!ISFYQ7h8IodOD1Ipj%0XEgdvbbL zxGHcHB1k);!_cn6a633wZ`wt}OkXM1?=a{om+p!UOXGGjPb0);)b|yI+Cbx}fqr3I zft*&L)q$+1(pXSF?8!MfQ4?LyUeklL@(<ZdEGIpq7b%IYE=AyKN^p$;az*Z1)RCQ| zlLZasoD6{yVG(MtQ8T?B&sBrxm>iT_fbRo68E~O3;Fx-K-Tba+e|@{HLCIFb+ETm^ zR5aCfle6?(s{#@!lI8%BCRL|}Ky0H`F&wj(+ZDR0;iUdkXhWO5Bb2^mfUi_!D?=0! zq33%>*@AcESu<zjZ)$SBpczA|VHWnFEdq*Fl5yhevM(@WYy#baK4^cETkDINF;(7W zAvpsXOh`c#OfpXfacJeEtHqoCnvo2TYB}T%W=+#D&&*}jsu@FBEdZ=ZC<sEZao`GI zu0F9DlNVU#QImF%%#oiZz75BMU6_D>ii68t(NQ*r-4&CHO5J2N4^w>BZTliM{ddp$ zAo&l_kE&?kLM5qju0ssl`?)9KMf0;}#;l&8i_I7yWWa<3Qk>{50PmAaHq%K+b56OL z83Q^r^k$-mL+g|XUchNHW)LD)(qF2uUMyUmWyV0B1K(g$!{5??GNlF223^^opKSqU zOv)BhDHe_ah>>+NqWadCHe<-==(~bqc|e|F_R+!o4Wo7~1mFYO1kh`cxyuX_*=~qM z?cDB$FKxyoq%;YRYCsAB8GX87;|rTHFb}1G^LHrSI2MJa&AQPS>^(bC+sqjI^h?Z` zQ$~kre}0ia$LMIvl0ZQK?J%Ks3hB=p9oxUY-RNkA`j`xs2D)GP20oS1QN^e&Vb^Ch zAQHJ$jeA=2awx-Hy%z>EY*YV3jSf)MsHLqapW}wf#o6Xf-^}Q+!<Bu1!OYpKNGWzo z+~rRuY!fLI#oe*14l4VN<hPD0z!sQtsX%t_&DB?+Aq0FRrmn7rSzEA%te0x_m6(`+ z3+sTePN$@*Z+Hc0&zf>K@^}Eq2G(xFD^ipQxjfa41dtNTyeAX4+A&x;0QD+!;LI`* zt91GA=^2CVsc*rlWiXU+8Q=u3>Q3Qv!hqWy2yD$|$^^cX;F>|}gwHi=leP(Pp;DJJ zj#$@KMw6T=TmP80D$Gj4n!+eHYpaQs;fM`M{Q-W2bYMJO-+eWG=+(c7Mey|>6dJ() z{fGF!7Bi#92{apN*Md?-4X7%eJnrxBj%01?UA1efW4C*hN^nu?K_4L19M}fncd3D( z2eZe94KyO3F0*9XnN^c&bHSwl5~4Kh!eGU)L`{uF2=b-GwdULNqCuRE@0L{*Mo>;t z^hTUlXqb-s+jjV@r}Sjs-~H{bfuCG5((d^aQ$+j}lt=E)vW7uI@K1+dUk!rp>wo!^ z0zCct4?5>Ui33$r_x=6hRx&~k8k0~fT7dO{33IrA026*^Q?G)cVl#Awl&}S@<biol zyi!O&qtKAJZEk8j%j)Lc{bB$39;V2VIJXlh_MQU)@-vWKcvK)c|L!aIfpHp^Thq10 z6b9^tgf}mfAciKlBr!Xv1?}>d{H>k(d9fvhJ`Bs{yZs~FzV|x_=V^wVx;CxhCWF}v z{BuN<_rz*TBkU%aMZyM5Y9yXn>Tkzg<jzX^0Ax#-f2+~y<GbzyABW8e`p6!Nt*oiw zNIUgv7^@a6zCCXTk~Bi-8_aYZe8Sk_J+atz-HlQ|2(~-T^qhA{GoT)()H@bgIQ+WY z#G(4oKNLUTfg<or*P5Y-7paG1fa+ri5G1h3SxU7W0#|=7+x)U%)#lX|=n$$vSPp6S zq`p88OLlvcik|`-0kqQZzS2Lv_!C8cxW5%D1o=qPx8PeNP4i6rLloVbA7A{LFgw1# zKRoXG>ZrJ+$r&cOu>eS$yu%7eLE)lB6igm^@plE5wPv^TwV0y^V>L9hXx_cymwVCj zlxliR^FS|U@YH8X4f$#opzJxT4{qPA`0aw#r%sI$!T>b20%&uAQhRCJ?y?sl75_NL z5v*`@8J<!*G0*Dx;%dW0)B;ur@nh9ee5r-Ri$3ElE@YY{N_N6`)(3>AUOq$q;#Q<a zrzARHs6+Pc=vSVAQ%AT&s)}&!MY1H+n}*QtQN7>PFr$b{VSbf0^uT8Q4e^5r%MmJI zzJHcH8+@^YRuplX$3>QdR`1;CZdc2PzT0(zbHXb@2Y6T`e8)(DCgI!<ze*?d9qC+1 zVJN@v?|!Xr_N|<(m=d83a2VVda4Mj%I=?Ts5Wy*bsG7&!asN)P#irzaobMTefDALV z0{4N%Hek{eAX|}LV99pvzIyC-`sR{8!J?f60T50Ehe`8g;@6&*)(ybix|jyJ0UF=t z>WcpXaE>S(_t<?adfOnb!vaX#-NXHHcZZg-V|t!MV`<YQg>w-ccrbc_cjcO%J?8dd z^~k-T4^SvaeZv+EAd5xwQs-k_SkrQW-;-H<_c3b^)w}z<^7iS5@qAFy8WhI>S2G@- z7@Jna#PF-XJ}ZrdDLN>+*G>uf?kG17l%K%70%8gh9{@Ph&AQf7WLoNeV++wt(XexK zphe)N2YTBvvecfRHj}<P?2k`jIqA=ilxS%T9KD<hCqOU&Xz=Jb<qWJembqOrErI)7 zCk<7aeT);J&{x8I(hq85K8d&hjv)k^5Oh>#0|(XeG9}1{$MgdVrfe@Xp9Ux&@D)hV zq~FW$l;0c0w;f*W;A14?nL5%WL-tR#HZ#yLAGJZWr5#&DCMhfn;0hb!sW99L8o}%- zZ&QTnPlu1+qfL-*uIfL-c!wT$Yz})>xj>U~3#XZw$%HkiY1Mlnb3w|KfSk0mSuVza zCsb6?r5Sl~wZI;^qK%{`QFRy`>T|pQjsB3)5$8M$tx*)Fa-sW=yix>Jz5%e%ObQ(x z<ppF8mMysd%+#bAWvEP=iIw!XbCvu8JTpCFQ(&J0u?~k*OB#k6g69!eGvvLyd43`+ zKoS7prN+Ex4V?MGkTmSix(Id5cg3!{x|*2iqUdlK)Q9<>P}$qsXs2F_yeGg;V#-M? zb4%+3F@9r_dVJBA9a=ZWERg#tR1|Q#^(?bZdvsH#wFM3a&zrj*n{tozo=?zfJQ6=G z$cDiEgaKA;r5)rG=<DOvl}o+xy}-rKR6l)nPk;xxxWS8t=qn)H2~dPu0FOIK`B&Z6 z6$D26o0tk4KLYI#z|MFX8b~w{80sUjUe=%HZ44N(d?A1Q_`t2NE_@P{!l>&L()H82 z)M5%sCRNM59cA|8UBf3|06yDbsgRQ^=u2(G{iH?%-nLUyu8^{>u8h=pD~P>H{>;ZZ z><tl9GPB|fV|QD;D`(5deDnWGW^gXyr9th4n3(u6Nnko{M{Vo062!S79em96fq)D0 z39h|5ih{^6n0kQ7>dg^9L*-M<JG~|HXRDoXl_d?QkD^K31)ukurQm1n-fO!u!p#V! zR0nWs6{hCcf3CsaU}3T*5LCu3$pZ<1HSlZcE$ZDS+a`EL%O*SsRcK5(HWjdep*!?M z@g>bqBtc4f9Kpak0mQkX3Pf#d-)Y+2++1D#`5x^44=dYwQO5Ks_|Q;HhT=sd(Mz}N zVdQRY*)Q0Y`!Z1qVv2wSQNbYHc~jCjZ4;ciq~j5^88wF-H4!SuObbVEIWK8^)_3tB zH95Za8n|3;YBevOaVCCKM;NF(_BH=@auBocP}YZm-IXO}{IGeW42TivLOV>pBcCv` z>#{F#opYZ9)d^2epI9OVSDVsb(&mh@X1bpr$?LrALsA$|K^oQ=b@E-NOHjN^QGduw z6q*aNm2-xU8iN8|k(gC<6e_C;^Ppwj*1uf?b>1Q-<GV*eIDpcq>hREZL7ajn#uxc_ zS*FkP)x^jvfDxf{NYg%`l7^fNeKI}WMeV>dd7mrONW&3W(@_Dv0~8N>-(8BQw9+;% zojT}CTrcRSREg;&@??tY`A_$XGE3qe^X1>NK=vN%lb#?KtX2SdL20UYoPoGEclM|G zpm&Lp_@6`o)Ppn!zj^59gvb^Q)7K1)3a1CcSa0x17^iTL#-0MTT5;^#IMoW*!pxtX zot2pnJ8Y%~%uakAgc-FoH!MqfA|NtBXzhNz-*3h9#{tt;NhZjnRB0#LO!B0-YICHT zny;l&Qzce{RN;S>rX+vmaOEWO!Tf=p4!?F{_>oT{H@yHtGEeFPLTu2O@w`od$Tf4r zR+wO!Oc;~|ert*nJXn#o{5{4<?r?1N)&2(W2AT-a@d$i~O4A^q;#^!?&J(i+3iC6x zQ{C7Kv7#u!OA9x6oq#btwBkHAG)0Jm2zL2{{4Z+jeg05=1awq-)5Qf5BkC$)ga-1# zF@t9>-FC-g^-f$2T?_CDth+tL6n=bX`ciRo-$-;ye0m|>t!q5W4QeNGX)V&+GFsJ5 zsC;Zc=X+^o=L>i~B_DvH%5WmbAFDf5{Ka&Gpwi7vCmxH87*(0#0~1a*cpi1!uscj9 zZFn;Zlw<Ku(H!5g_D>CPTxteO){=l1e)ED*q#Bmi_SJZX7LuMFzzby5hj{OaeiNVP zz^=b=1Mw9vkS&6FMWCn8+X&Fd)fckn{^sdc=DIB^Al3k=0cjBb2@|4!8b(LFi_L%| z;hml#-hp#UoH*3)B}JMU{u(uq@!_yg@9mWH^tfx@cg-)n8U+N1#2bzfCXoPN&HS;2 zPwRGfEGlil%Yq6@?GC^TB{59BJ>0_cBL*UHvameu`R_OCzkj~J-)c~^F&dH~;slCa z!lT9naO)Y=?y^KMvJcyDbkXw4M*O?D+(e$0%K2t|VMKFN=Dq^sG;5$*AD7Fc?g&GL z8Sqx^q_p36H*y|PY%q@kvYdsI(15jTmk7NZct5<Cxytu<`{R4u%y+x)xA)c4@p1pF z>>M^_Cd`t=#S`3D&Q|lg5~!~H^z?Ak4L!jy3-IF${}z-Kjq3pNdZOQbb9dJrQenlB z2!e10BhDjgv5KTEob%{?x6m`tJq|BIVvNZQRz0BgKq#MmG1DXGlcXq8h|8Rl90atc z>ne4-t3S!TJbseGJrNyHC{l_oEW3jvaPh_XmrjOA23Jg73Q)bcuSg0#_uAM~!YXKW zB?a2(0ZB3WprI!(dqIVsv$wOp+Q%&r;wgF@u9r@$a3|kbC0RfFA=FT|5U40HWs`cv zlAQU_l!aK22+6oIBFFz9RT0WP%&|>P*je0B=U$pquV3)FBErE*5ep@p0g*XQ>iN%2 z38KyCMy`6UYi{bh$Gy5KZg16@)N972$ut%%e278|!3{WkZ|$wMb%S=#PUqUIa{dY1 zhhX`D6P~qUhnal#t<?$5PQB`^q4=<RxVCa4;FwGt#4Rtbj&tj0b5hPF2Z$^w(k#X9 z-1b?sTNij(|9+9wPZ&08QH4*R3|_gUhdaS!@FGpFukGz}eLdbT%Gv*%4upaJhB7!% zuy9v!d@_*N_#YFMeonjQI-|p~hf<<dl*N!6O+K8feJG}Yz`~{f2X1f`%1{9eUgQ?1 zfUqKi4J`-KI#xttD(YuX#tsoEZcS(vN&vJ2fH=(!JzRc6$m&2ARiy*H?+(=spQ>Ug z4~6my%zaR?+?W@GSbZ_l)Aw-bdKKa!$G-%Lw=P3qG;(pYxes`K9@``dNiJ^ui(DjC zlGZQ|2X11gOw;&yh|<#nn5omw+T8=OI|bd5mc-A3umOXZiv{&(;klJAM4|5Iywwu% zh9Ve}p9!wJ$+ujXQKVS)PP)N5f#AU|X5k1`POi0a7^2L|%tKBGJwTP0LCUBNvDDHB z$PG}DeSj#?dwa4PQ^}*7s3hYD(hvJqIbbN~Mmz&tMJ7_saQusQe4%6+8)9(E)=0@9 zk0kQL<xE<r8v*uLBanoH9Rc_!8GToQfffTDUj}_aK^z%K!_O;oPy8I{Ve&@htf09x z9FitwPAK<a5r<z-zYZi0uM3|8FoI!Kg>Z{i+z<M7ewEh^p}jHXg{<l_*Br53IO3}s zGrmN{H!70$%pmKC%x#NI6{tyw1ENwr8N-dSM|7MH!)RkGDd8qc4+Ya3dd1i*kueAH zplocWL&2pk7!Eozb>SD#+rxx>PBb&~#ijv@chhBLmg7{8^ge_0OA~00@gL>1{;}&{ z^9KnFZDM}Dx?<Z|4}I7EAaH)~?}c!3<1k@Yg8eh)ND5$H=}0)8-<*LH*t{1cqFZv) zm4Qn(X^3Zx<3lR1TS#Owq60-NL%vMg{kFU5?v!(ZT^J@Yo&|x%CuqW5!XXg%$mGFc zKbzJf_n~{q-?r`Hsl_2xB8a#lf!p`n8y}svs2et)y@zCm3;ly_G=@tQ_Zj|q?p$cb zCylyKOS@i`sOss}mGbuJ6}*g$B<=y;?F+a*I7zJpA6Q&rmva0<b8;y)Jd=f9%varZ zN~Zet{oNy^PDe2<!$eOkaYyxUEKn**2pHQX*}nJ@IDh^l@+HIZu4M&>^6Cn%2i%aF z<?-;tfdnZ$Gu>NN%b;11R?yqj&Q+G0^haI#;*-Gc>0x8Z+af06OV5Ef0S^Dlu(UB< z!TY3o5{B5m_WQ;?O2#cA$v7in5}7X?w}Uapn<=#!$B!jZ37jhY$tWDPFm*965#*x; zvc+4^{*9OyrEsX9Pqvda@1O2|QBCxuXYhL0;Vh^tT&VgddEF~OS5vCGb9FWJ=e24^ zyuI`Fy~LwU7IT3LLeyU>>@yue_Gpn7KR^GdUb?xcBUVYArUgK{BFj&UUN1&-QTvl{ zC0bk;v_kTN@sF2Vt>L_N6*3d|&1ILEB)#I@rbeaCD9kXIk8C{ITWW8p2E$OLBkrC6 zq?6?M2pUJEAQuG*zogIlJ8OKe?1TVa<RLGS1DoM5f(xr?awN^<C9Ti08+jBlgue|J zgpkRi5BZOhTcLDcp55I(iK;+;C3OsV)yopUXe#!K`-E&blML&eVcBVyO&73v30e)F z9Aq!KHmX~5Qt;Q@l*hIGGg)6Mk;us;JEbGzgP@CQa$cjXJmd2w^*OL$fLB-ly(cd4 z(*c)N*Zx@DwfDE*pdlW$?2F%ZkAUVWH=}Z%lO4!yLWV!Pw*k9DecR*KQ9D<OcG9Jg zca^%Ne-P0%@64iT1MIhgiwp+!B2Gw!`yAf@Dvj*|ehw)EWQ#c0x$I(7a2?5?SMEQ_ zn(l)z5p94vB^p?H))RcDVe&VXRx?T5a<8B_q7}&HNVCJ-*)%S_BNx+;ly#?GV8T<S zTbwNcBFztzj|daWieMtD3D-6RUnhB7sUP}WN*IOH1HnBe3SRW8Aqk+I9Ly<Rq8S4z zN_Ud1yL*zbHm#7*CqYV5D@d;-4~ig)^ME&VD@`Vkhy5)rk@o~BXW0wzAtJ-|KJxLE zm%~8b#%qiTNE=k!kP<^a16?Xosk?FSzLhp8wx$XAxoIFH&l@K%awV;>UnZMsrGZj4 zaMShDg_auk1~-BznS?Z)Xpn5hl@`n}4*PfSr43T!1&WD~C`lB#Nrf3!bES<)S2C$2 z8ASF&caXTS^oadHRvB>A;1ZAvw`o$m)=(OU)}n@cgH#<@V*8W?<V~%yZ8S8eGREi= zJ_;@aCYjVrN`<%eX(8zgd=biwfV!<n!JAzfD>F5;V~bKn7mLB4BPA8ET!iyv-A$s< z<gA<2GfDIqQ_1Z47JztjW+-7(zcXy?VltRZ{FiCk;Ko#wH@~C4Q%8uKD$F(tTuR@h zm<2}yZi*;0*$8f6=5c>Z>fN_bWTRu>&zn`EsFDgh;zDiv%~8yDkwS#_+ICl|zsnG) zM@Yd%l}gbl5YvVu=Gg|9eCh2|?SAR_RF7Yh61Jp`Ycg(fLJN9K>J%jM33FXe7R4O~ z)YW6s;iOmgF0<=p@L*#S@EK%;$DRt4TsV0#;mrM|Ee|cZC(X^Q{z*T~Ah`_8hxE)! zy8ke<)Z5hL+Y*!xYLq25$M~~Mvf(Va{QKYTe_i>0yZ?3kepZuJk=Ia55u~WZ133OH z-}h)9&y9akEyyTKAl6RZPCzE1&@+C5W<x&Z)Gs#pt*CCV&^*9-76*{?yL?aWAX`t2 z$BUS>Dix0Q$KCihL_$U6k=ig}>S;)?{_ZRHfuSX^_>aFNLi}7%XQ-&3jUk2?G$Qdh zq8$u(Lt<$5uYD&>>`R)u+Pq3`K-R&`fFHDABkJqiOL1}erp4B!wr75(7Z;()@$tia zLoG(zVrA$9?B);<-@hk1{FmzEy-F!uYj|c9p-thZ#-tZ@io!JAv<vTVn*K(<fEK>F zWfCDlNCg2C+p<oDnai$Zs+x>~*VWzK{o{|F`s<rJ<sO3O-K&Sdq^bmLG!??_+L*?< zn^$G}x766?zSi7BK;Kg;1-&f9;bUK=bjD;=O~lra68*iGDXoeR41ew$E`zDm+UtL_ zS<`s62%J>7KdD}6>QDA%Ds5+9*8gU|ObHXr*F8*1Fh7)qYf`>w%oJ|TzO4VvemN(} zFOradi$aUTcrx2M-S0WG9ToFWlTjf5ID8xQ1~N)ex+&ZV41uV3ox2P8^ODO-+)A?M zZ?%n}i%3x%xP(IBegs!eil5PqO*V&nn!MJRbOjn(ZJx|^JR{=9ZlR#cv?AxFM0?FI zRa>8G9tIR*`T-FWVj6|P&scAMsY35m^K!C;Bq=ONW2W+7iyBvodA*l~o88f;+Q)H5 z<X4q*g;KVp+FxDTH<z~FgelndAR$muni<m6)ya{Qe^KYjLBfNQLWo&)@EL0LWxe@J zm$oW;DnTiF0Dz~*^wx8~wlUvay0kSHcL@4#K@nbBrY2u<ZE4?JytKGKa5F^!QIsGh z2_1rHA-eldOH-|O5=F-9zfykmw+H20DSH0ALp$cMc6}h)H=aPCtSLBrVWUP31+ON; zOb1G-69?L}8x14XRi#g=?n<z?q4*kkonoBnC49~tn3hFTJal5lQzKpB)~X7kl(^R? zcMupcGL6Nb_wVB9H#||&CCXt*=X;N+!y`$pbp#wTX@EmDY&2Z<a)GWj0i)mh0H7E0 zm`SB0>OvfFXd*q?L>NdnhC*lJhh!Gv9;1zl+*&p5+WcPlKE<4N?D(QUUm)|0n-DjQ zId`rVrnZpXN_G<FhkH{0$CYCsdV2IKoB}`wfq7yg<ep!6;|CTsLoU)PC1W1lf!*PG zPsVYl1PUIH8GSE)gDFmVT#vWtO|tel7z#8jm2lsBd0;CI==<&oS}?pGAaaDHppukD z7J#YInNGX+`B<Ml2~-Q@3CRlt|4rEO<cpv|wL9Bu)Q6ljySVEz>MdH=W3$$4XV(@I zyT?2T067BF#`V0Nd0RFt2r+OVMg=wt*vvu|XZ2cVt9xUf?9~<kEZ|Y_Wm1t3O2LK( zK&w$3c9;NiTw^&nFs;MNXs|F&&Y!dA!KEjW8twwpRw*6OHeK%43o;E?S9Z^<-9r>t zZJ!G^KEbRA-yl9Gk`ql%g;&XW(O1@p??IXu7Y)_PG4&TF=OJ_L{!2cyc*w#wCeBXG z6{0w)Ggk}d`A^g*C?X=;k9ar9Ek_(TZ^aukQvw#hkmHEOMJKKkqPoWJoX^$t3xF@| zIma76(wBXO$G45RpbBmhHH_RXhFTnkidg;F9iMKtnyc_6kqZX?3usIoxeoe6uFd9u z=pZ;k1QZRB(8l3VK!Gyca16-W;W(Z9iW<lFl0JAcmNW_bWK^^g9VK1}!kVpB%VwHQ zyN3=~+D3PO*g62z$hxNPH6RBHSEwGq>=+sZf+^-kx3!j~kjyfO^g@!NDM>VrF*n0p zt;YN_qBgO^2pw$wR1|jL1dx6~u@6~Y#y*)%*6=BoWb>YC0LDZ+>A37DhSNIAd>w|S zFF1U42a+G?d0b``FT14-BG4nPWe(=(UYU~%5C;V)-7#(~yfmmnEj`p1Ex{}Wrr=!@ zQ#ZHq3M@1m5)=Uvj3VAD6lgNFO9n|lYX`#s)nlO@ZV5^|TaXT^{-A{AOgq|QUudVt zt<$0EqtTEwCTSS%^*7}L+Z*$Hp`kYG1xp_@JOYkgVtHOe`W%eYE~V5fL&Il?%}T(U z1g44#)=5i~1$<gtKths;kqni9R0yQYmS&>t!$DWO?SwQ_^kPzg?)%;22MNDdT?m{< zkPv?Xn^O4B)*ttWuMf>Id@*vC*OiELSmJynAB_CDcDf$R?VRa$(vggpvNTys37m0b ztnNAE9$#2ue2d%z6br_21c{%PaOc`N)3+j%Xk%QLgsQ<5nP^Yb^MIPVGH*%R=9DA$ z5w&1o5=~coI&Zq2Gkt5*9!x`wKeB_wqdM6^`UZ5?RJ*1YCJtK~bQ6p!Fg!{>kyAv{ zN<(LQmyrLWm;|8F4IoyX^lozChLH9`_o5C@j#%R`;0PbMYAKx=P2WGf796Gf!^e#` zBIaZQm=rvioa8WZlU^CNsp%Z%&&d$6?l{r5Y<Nfk)5zkx4!T-E8aup0#A%^HaRO8# z>(j}qpZkK6ByRI0a7R?562`7D5`@Cjm1*f@-Oe?y&%E0{XB=jZl<+-Osnlh^tbKh~ zxb4I14MY|=T>`vHq3+At*Js9UALuV~__#u1Xr7SOllCWD@a+8P^W%Pi?5G@oE_@l3 z2m#47`M_oCt8WUo`80<pJkKM+IK<)cvh_7G-EF@C0G!wn8agGil)+EBf7$*qa@lPk zJ(FTZqFfD-w-mCzto`}=rX5xA7-V_ex3#5Q90a~ez}k9%pN#I{4xpp+2}v3m6^&HQ znQ+xiXEtCF<U(Dd>jOueQ1OM?3b7w?WHmc;9a9++7dDOENXn=%Y?G-%mAYy=^&l^9 zF@e?*pcl=?Gz&;nC~ABo)H@hM-t#TpR)=2%rtgRM73|!%KkO-3+^Wq(j!~C*hbZ0V z`mVJw@Cxe{Fw#!|BE8w#CS?|sDMF6W=M^c9Iw)vh2la8^4pp=`C4G?*L5xbaU{1!y zf>o%YGKT1#T1`m=ykw_fK9ej&^)JwULjIwa^Au8wd|(TL$;A4MYJecYb?UL;hz~A! zYV>Gu3}B{h$1j<D1~{@7vatvU1WDeKR?fBM#jf>dHldeH+9oj+j{^=~8n2Max^36| zblWz0Id30P95yNqF{P7K^0)s#dG7%x*HzyCA4!&|j_HAfA_xczY<Z{b?Ce?$$g+)v zo2+6vIAWP{R~o##v!0n%p@cwa2?0VVDbxg#&|4Bp2oM7Khd>fKgx&(=M=_m*(EgwI zlzY#;bMMTZ*<G6_$rH1yojd2A@}9T9-<LZeU@|uF?uRza3vysfB&N=`P}hR1uSuGP zZn7uak~Z>Tm%Ej7&I=280I6YJK-yvh**Op5oa~LGY2+Mzwl%ZRVqoeI0svuC)U%Q3 z6{&ZN^iv=l7G^+ohE+Q3V1L%$xH;zvUf4__p#GkiAlb%-^zwHCqpAJg&JwBhk~OrC zF5-tp<IDN(I>45*n6OlRP%mP!nr@_bQ|n!))*bd;o&p&W4#Jk(l1WJx{zd5+y`~L@ zsSsiZc4W3VE0Eypwn%EvB!h<fwV-C}Pvnx%%{gEo9?<orH_~Yaq>ok+J!Ps;$z+w1 z>h(Cy!=?jA+7jJInp68M3HVl$1$XTt1tkmPFZFUauv(j7u9e8fMc!Mc;rr1wxJ3?} zk^~n8eHlqie2;NyVqj!g%viJoJG7FVx0f_<jN|~;OnMsN6GpK3?(8^n#+bSlY0YH5 zE`SwBl!j>0sNoGTM_N`v>UM*#Mu$(l*F`dL=oOW3__TbK)ZxjHmu&$qhc?6&i%l7? zrAdJmNzGbF9UspN?J_XbrPvO!V5aZuv+>P0yK^`#RG&ING6vuhLPt<c8T`L|<L|?w z%@=T)0>K&R8Xy@_p9_LXAfkQb{Bw^_6J)`Yhjz+ArJi^E)Vzz-{V4(BQ<<R#t&A~O zc8NwK=a0pfZ-4NJlLl9zB8!()?WK){ywc8hpLWvbd&4YQ!k8=#JPu^tOU;>_fbT;} zd&A*z-T-t5nM^aFBLUQGfdPy$%AOhoi*%Qa*>amJ>HCxf86Ew?Rs&+?(kdqaI2!Z= z-Hw7KBwvu~)6g%_KyVkGGT|cUwTiz1+SgFy#LBs7f$y%0mXQ4ht(Fdd!!(XO7SSjG zJP$mJ?@@~0km`5H-X!A}u$x5xs@V#d7?sL22D@LvD-YOH$X-JFCdJ-B$v&vxpoKR` zB$>A8i208peUoBuD3u!mx>;<HMTIeDL`~W5N=hD?-WvRgg0S2df+;^T=t?{Q95#~R zxVj{q5FEAVImSRUI;OO$OYe{!z&lguOagCp3JGFAlZ!OY<fduUphv8;dzEPt^g#5$ zbg-eOF=nTG;piG8V309DnzXX3kg?pv-ytt4RK}f~9<d~;M!-`PiTyEpP=`)gu8deR ziALkjQ75mUl+?i~rofz}aZ0K*2O4MNr1OS2sU#@`&pJJYrMWiA0<+e!X~{ZM>ZOrL zm1UAVN}d&oWIzO%S&cK2M<djU(Tk{A0^b9-rNb;3XRwess?a}$o>N%ZCDI{mY-60E zBI<y;N<o1H6f!BN3AK&C#)vLRJ;P2f0cKUAHA%@{sj=s!DFR7^NF|%95=?<0H^IC- zl0a)IfDb}`GljP$*G|z+EK`w4C5aXo&S<*=8(jz7EVf;_M)F94S|gHJC0mSwE&z+h zA1ovZELYHu79@UN51P_ISUAr(D~w2jbS8?dkflrsz1}Ef<Bz3T1qrn9>J}PUT|h4< z*e^XV!z4&#Ks}+cAY@T@`T66l(IW|n3I{VuXOe7)J1n+gNSt)dDUBpZeFKGLnoe61 zPbphRzMWRCkvx)+K>)6!W($B5+~4C*D<p{$MUaAth@cDT;26J+x#ks-L<uoOi*_1K zmW$wMOfW5vOVF|aof+~V^n}7c{t_dSfJ!UCJQInS1@~Xtt$AdhYmFXBpg|HXBq4)p zKr#jFB5esoYMykaauHM+qycC;rZyEfmV1pglt&b#ClainB!B{C0njn49BZ_YDq8T= z1>)JbB}rs)QP;7?ipYYl%AifrupSV*2HhGbm{>#?#pxNzO{88BXj<KXSk7|%nQ2}D zXa$x4*)=q~3BXyMU}hd=Xqf6*&@f<OMGQ$Zn$dKKOpfLi(Uwt13~oy^C>6Mz;08@L zl;*84Rm#N3astnlqqOuo#;m**PSb&5iXO7~V8Ktd@ixoz(G~M9QO}D~U}_LR)|vsn zr!gH<!19gdO^mEn=~cThQzA_kSA^Lw!(An+I(qND!AL5qQxsIDw5$jgeT?Z#ddgUX zRX`T0w?F^@sEA%4_Et*dOspxL!;naKGEp_nG%nE1UiAx|xoNW5tf^L=ouUnUl}1Jj zBta!jH5oj;#i}0s%4XkYqNa{bzXgzxBpn$16*OD3rLl>p2In&;ZjvMH%t_8A=uGw( zh6@D%e%yTYwxrBFHn>EUN(8f;Bw7`yK3VhBV@?DRF@Y4T(jc!{u1vT5l!%F@9vhrv z1O<;ME}$!9|M~HLH~4tF4!uVH4@zfdW+mr(8h|U@uqhjpO^hkK9vd9A69I*5H0Wn0 zAZICqTdQwr#biK_pmdu}U?~QF0XhX$&2*0i`)s^JO__Uq^a43FU>wl#9IW$r_cXWf zR>q`EUb{Rl0f$65LwK3uFQ6w1-5>~~ld(f_iJ$d1`UTqKG3o`t$^lnMz;BvMmBdgM zUQi;BV+It~c~c5f#=|4<Q@BVP6eqwl?Ppp$@-Mo4afsh7)#DT6Q#6Mr|8${VFM_p< z5;jO0lf1%Y`#4reVFa1H)PaM*fvTSI3afBu9b(e;X0v?lJ4kY)%^Q7KX=*#ubW(X> zr^bAT2)pQt26)8?GgndJ5U@#PX?Kk2i8&Aw73Gr9I<Srylc`Ag1-etcLB$6c59_m6 zHhalkS5mr27{=h76*xc>oeF(?6R#u2af+11fLwtjnI%0fmV9OJlqRcj&m;B@R74UG z8zf^R!9je=*sE;Lmg=pH-40^fV7ySz$M9hMBs{v|R*m_J*zI6+x<nHi0EvuTT&o0* zLAmLxh*2(aAMyck6yapAQ0J7fQ`x7H`i}VRpmq^~E;!hrUeOkDecsWI-HsW^iEbh^ zl`a*g@gA?wJL0#4R#U|pl8%8fpcFGm(IG}qZt7mOW0XsYD99KM+>=1av>GW2+$8U? z`PufCH_9b42I#pRP+LGRxxu{}!l^DyiPyOD1II<EJ`bqh4yMbqvjlF|Jibd&bmNmN zkD5g?)$BB(j+EOiZB3ld7)6!5b81;=*f={YZOGh*10pj$^?3+`j%y1ol(X3)1PD$R zLLg;c<GvuV@B+ZD5<Nf)h({#lA`N*#I`PF<K)N6eX<PKLm?nELO&*W?g2W2&fYDfM z0Y5n*ZLCpE8Zr1Bz1w>P&v^-)`wX)!2^dN_HG=_#QlDuO@i7|{10vMJj+J{@B<Rb3 zGoW$diMK>-*ttMh9m+X1!8rj7pgvs$h>QO>mtlf&uxabX24%cZKvfWeSkms*<z9Uu z*uJoQ_Wek;?De;wy>q8&?>hb)Q1{SufoPkhg9#<Wes+yX`$^=<P5dHIFRNszw`hB8 z$}VInBG+u+Ba7iWH+L|?aNURYH}MNwBue9SEmy#=!>i)2Y(*L^NpF*7>hR{~$mh9& zUjW>#P5w44*cs|lXto02i)F79oCl5;k|L?O!ucOsmE(^?9`tO9vY=TC$Z5iZh>y1W zc)fR=O>eKv&0WH;LDwFG_xFSCl|t!&w2kgfyd|UtkeEgVJSGm#L@U+CUkWNCIrWVq z`b2Y~S%Q~GO98WFZf>tYjZS)S(#D;HLEKvOsn*yd(dZ+R1vMt<AzH)Z`=N8wZn-bD zbGCaleHrbRdV7{n(;a5=ZG^dDkkasg00)x5U%p95o142*C#KnB9L(06cyF2%8%u)0 z6!nexA^cY-_XfCsFqoI;<}T(J*6UwweL!ww2Bzme2+z_>Gz>ElCtd<ECZdD^dIK)3 z5*$4`UJUKIIah3ODafLezJyL4ttrq6>1u=}C=u%DCGLp!^@F8#KcMmqVPm2tRiH*q z&$j5rraXbJAf`Ow!g{~Hdk09tmOe=*o|}uB>`hFbbZD-$D41%YpOvU*n^e?+3`es# z(oOJwgH;k^So)wybr1-Exw#dA0GOMjd|C?hCq6T<<bo3IF^K<G2+x@_(>lh)LxR{W zBLcTVpKSpGlG6aZdeQ+&AR^<H#y(TX1lpKQy0?-gicmu9Cwu}A@#!<Xb>Q;?6hAQ^ zC0I>fAw4sjki%37I*3S7zay0I7cH&yPhSxPt;Jx{jiFN(9ZX4JY*F~ra4j0f7cBs# z0%ko$zrJazHseXudeWMKPdrOnED&76+gB$8J|1NnN1G((*dX#qaIcKJOiZ6>Ydx7g zM3xuJYn0`b&1u#~V=(lIY3nf<f5WkK1&ae^R?zqhF-mlt(h9RRC}X^(UL^V@t#|0y zVnyZ-BbaqY^xT}wh@SLtiC`g42o(ijFzULV=ukAjvTzA=bEbd@Jq3;>fDe<tkx&Lz zwZH>|!V2R2#KsBvr&4EvWsLiobPk`K5@%p`EH1G%c<;pG0(?4DH~`nN0_vduPRi1N z(4&Mqm?fiy0HD)~cA#rbyuDS>w%8BSZctgvG1ByRz*Yz7GOEenMMETt<Etg!M}sH- z2;$80(8<n``f1nGV&eDB63`&2g)lWe<sCTu_}3Rlo={%33K;_}72BhvLdc%AQ3v<R zkF{-93*3_yt`+J12JQHpm3-+i#ZzxA)9J=a?Ix#WG6&cS+z*InT(uKZGPrYPDtalM zFOvX3#6=iMXxUGC<X{A~=p;?HBXSwz!QVBXoc*f6iQiQRI~Ok)t$3zs)nR2n>DChu z*pkk#gq?vyr+E^JPsCi4M?R6^VJ~rp>EQ~1CY?UGYjmm;OTJZ@YAjf{jb|5zy3pky zKeaVYUhnSs?j6_4`5c{?Fln_WEngc|2~g4ZZrwM}l1#?t*-s~*{%oDvn&~pt7f`QD zU>%=V;Wz_vCLo|m0V}vc{x*18)0$Wl9Yx{cGiZ=AGa$h8jwnBT91V{KYBTil#H|h9 z4jElpb8W8}C9gQKNzo{iJynuEF{PR2%<yWu*v-PWx8|$U5wM&)Shdc36lW?@Bseh% zH0TT~jd#mMy6Y6AK1{AZ5#C8JBsH)N;4x;%<|K1idd|y$Rv{GZ@VPmGET5Z;!;eq; zIzdjO0vY5}dOFa4!#~dayEh>%wNMd@INM2KrCml`M*B<E*zA+8kiDEL089y&CMi`M z<=G56lF3QdeQ|p+q95Ip1@G_5Vq3R9^ZjUpz0YFIM>huA*Sn(A*S2Nc2X|O|%k?9N zItTmRiK!Ck0}QaKGW7_kuqB%{Gd^R&Os<keD%e$EYf1fD_TF)+LM6&xzvL#a`Ifq^ z96E4xh@l$Qb6*^|`R;@8(NvG#q_hXP4e1K_osh8A*_nw=2=qxYM5?%`OVTC5oWr%N z)$_NPk4`)}a(Yp{=y~6yw`knJHTz`IF^t<<2dCEJdIU;Ea<~C$Xf~Qt()v3hCdX>7 zG~Qv$?)ZFe&b8Q`+`ErQ6{i#h$i()@WQwV1+WxgT{kp1f;@zZkERBLGHmpz25C!m8 z7k3Iq;FD|G&4A?MX+e_%%nMA<N#(f|5CEeCbDX6RGl<2WlGki+XQdsqoV#2aQ{j{r zwkQseNjGkx1d<Zj(xqmrObeCR#w8~Z=fV<DF+AAQSNHY2){C**?Qz|S=L&)W8A#x; zfVkUoK*!_r)rBVDb(Gdhv$dcQCzixj81!qbRpnpMO~Zh!0WGkCi_1`IyJ|MYBqR>i z2nV`{lt=~vM{SB^9iW&Uz~3Yz(fwrx=qLi(G^GcSTT^w#ujUthc-Jl>f`Y7Tb<9F3 zXRw=qCx%9;AmH}_wTWhUlRP9Fy=zz6@Hq#ky*)L6c=B36YH^kH;IYO7{@`Ok+bqy$ z8v7U<LmU}4BW=j0xNvCBd5d2VJUKe2HL8dNBcz55?>w|Qhc5#0L`7~B2XhN3CVQkl z@(;4t>(FY9%Y*$OFMuwIRiu<t!Y_Rpr)Kf=VA;f=pW`psi^=LN*t}~X2^0V<njmom zGp_TZA#g)CDX$RzIOcnZ$>Sje3Ke+;8JWEPcr|={ucG{eoGYP$0;&Bp4W#l6cZErs zjWyDVujF9#2FY;9`4-}sGoUt9Vd;T1Q!+;qtLl%f!;7=zd_#c>C%Rvg8d#@+Vbc(8 z3@SUmj<|C&=S!xfP6oF#HhD1X>ShNiE434D&Q}!3YbW0n<XcdUn-*^+hPkEJq2b9! z_KQtGt`L*MP^T^)Cp@XeCb>P9%%sO2*;h3&EH3$GP{wCNZ!9WhjW;pI=k&00&1|49 z=Uz-tm8MY7r2RWRP-yll7de(Cr3cRFt%|ZJ$Y)sdUgC2BXp9*W<IC7V3$CnUaC@~D zA=pvlv`Vdzw^9IJWd_d`)M!c2C<7i-NTgnj`<4a7Az6wPXU?>^vvyNr5Fc`tT>3`N zt!7Z%7PLH>rQI`uE^|SBL8!M{&ppzoat=;g*YYf#Ab_fa@+>awAQ#hv@98z$?XllL zJsfH_MQHRv!Fn+)e~<({TQ29+1%wB5Y>IP9R3N3q?29Rm@y^r@9CeSZn+C$>nN(6F z07N(oUq^8kta=OL5rdV~TORZH=bSa^a47K2QnN_LI&CmV%v!EUdbycPo{cI8KsuF% z)^&21ft9vAq%uG#xi(}#Z*1cA0i2OuTtR@zWWt15gIl#X_sq$pD^|%9MWE7{#DX*G zS^?KWuuxnz$XfF)GEV50xwvw?-U#~bW@WL{xo&j@L<iuFKuaaoMoA~Ioi?vQjyYo# z3jKS*Jn5mGt~4i%Mv{s&(%fc&6(~{d=w(i)k2Ea<wY=|BiHLe!Y~axW>ch*nPyaqP zRrF=_7PNk8cmfs<dE%NvhHS>{qH7!*jlr!b1Obh;aC8D(XfEB5F$&AkcX7ahU4SGa z#hHe4US@Fm<Y!kMlwvdn{plp}9I$~3_27PqT>2P=g7IJU07C0k0qM|d;!MfHr3o2+ z6k4={Imk}B549h2$l)eO)U#y7S^Sv5B{yk4O4}>R?-fiCS%QohYp!8QZr838L04ub z4KLafY`@z4JBz*(f(@ubj-!fhP3m~v)<wjwj^Ag}`HFK6j$5`_!cj9lO&iWB*XhIu zflC|Q^uf&e3R(xyp0zOBXu@3@wpJmAglii*UUW(~M9<(?iCvkcQV=4aA#Im(CyT$5 zHmd26nRBirvrwW;da9sQ;a1g`Cnjy|Tu1iZOiZ_lnh&T4{e#HuDO(>-3=_`|yk|t$ z&BVCe55Q2EFJ3Q-zKtasYZPzC9j9An;vGag+2<z7UMMADGg99ql6y2??>4o$zSP>a zYqfeRt7v*aZ=+vOAgz&zFma?-G7KHPoqu#`s69>M9+fyyx9v<5158evdsdBha_&uh zv{I^CnJomQ_E;x_@52}zy->-$H49vMT4q7&0!r90j=$lPXKV6K9y<gLh#srdJCX~H zH%^S{p_3=rm3#691OV_&^%g23SIXE9!zT~bWWgLHcfJlB9ySkoaxF=Xv0ClW$x{iI zdvC}X0A!mK2sjqqta2SJz4G$XJk4@&g5sir9bz;aO@H{-Q#W<0kduoA09@2Dfk-r? zOQUU+G<@r!o4i|JLaV?alrH9g$Jk=r;gc7-$xD`$#MAdiisKtoK;7gyS?cd{Z#@u5 zQ&i?r+)vXgGKBL`{TN$6J4Gv*8PJhPI0;B>%`rR~DY<7)?Fh_(I34+e^{VaYF?{d2 zRFqlf6RLt_Mp8eyfpGeTMxNQrt;$O|z><O{O<Qq1>X1*~Ta}k`W~qxW<BcjY^g=l> z3jB!8;b`+-+B%)VXt_?cnCLR%OdriJ$Jl#Xsp6O=g?I*B6Wuvz^zdWsJx*DXRP?OE z3#C&NM-LBS=H2^hQ?lXclMw*04SUG5Ib-ZSZV^e$ECM}2Ig{1Ph99k5tGu&c5IG_M zL$oc&U7Cj}kU*cCa+*PPW|~ehWlD7g{4~erER8`qfGo`vrvjXc3j(l{XZA~DP!3U^ zA`u$0_5gYy;Xlvp$Jl!m9Lz+ibt+JyX8Vy2KiZ`+_MVg?8fGE0@D3K57UE|3@Ni5D zy7O^NP-Ytyx~mY-q-LvZH^=wcrD}k=IWms*Dcljb*DC-fSxbDx^x6Ep92vxw!c3`7 zV0f0|5L;zCVt6(`@4YHe!yw&rB(u8=BvlU5K@rKl`DmC_AXk8vB=0>Oe(2_lCX##e ziSJQ6M577aLrMbXxp-#Y%?Av53aI57=?&2U!Ya@3V{ASSC<>ebR44*`Lory6;e}`B zojr(>L=rJ;nLm9-^H9F%X}LF_92nZKgVP4qZKIrfck)i3es`py;h+PtbDD^O*_{lt z^HjC6YuEfdd?zPcm=ZVuX&p<;E}W{y2^T{f_t=6PodWoF&hdi<#%<#9#G5M3B8Q%> zH-66Hi9$<0865^2aQ<nl2WDI>Z}_}TfhatJ8`F*r-bo>n4H}LZADb-i_E76aqjwNj zDBdGsd$`DQ^Jn~=+e4KYYG5m%47FUx_BXpfdir^{2OviB`H&{00DwJd<LD#C2Y)K> z_7D^%OiyG2s3(wuhqGn3J&d1sd(hRmvOt_k|8om^I*RxiKJWGb^x9<WTV&P{N~jvg z#f+b3ki1;YmDM(0slD=Jtj5L!h6)W`CWkA0p^8ayUbEgk);X^m9BUKAIelKQ+dS`B zyMKJOv8&lxIv0Np-JvA)gj_q?V4lYxSK5oT2yLvASK40gojbLwu&X$&zqr_L?CSQ` zZA>-rGIf~XL@Ve9EfHPd+9hXGS_+mb{6{l;oZBt@hyk^()c~l8S;=xYAIX=ejdKMN z5hsJh@^<ZVU6G|ZvczZ0-C(85;FQYaLzGs7p#3&xjXX-3l0k@<w(+)ge6@=DP@*qs z3Fxfm6o<fPyP1edV>0(56{WGW(vz;{M2jzI_xCKfWI7f8U0<dN{P8B3$bkG-@bXZ$ zDJaY4BU!CMnj)KTpuecW`Y9B{zOKF127>`r5zq*@Md%i!cbjct+e;42ZD7yZ%goV2 z#}5qMLQ$9%4V*Hk*|5w}XuQO+O#`mB*t4f2zw6_XPj~I&V`<;g?YHZTbVJdfID9z^ zC{#QaFneOdMM(_>P@AIqDKFr&F0bhG3S3=;02>4vC><^cR_d|7-f0tI9M~h7e{_Ba zk9T#fzjs_nX+fIb(a^L=&(HvGj%L6U6X+~=gqm&I4KuXqQwKB$lLbrKh>o(M{SkA7 z#;(+}oQ94%dY)573FS*gBVZ=tAJ(6&={n77(0_ZUS^^^k;nBpJj8|PR-t8>S%cpv8 z^WKeXI(p)AH%^(EligO7%6F-4o03{5^U=_|VR5hq2)GVN5N&T}${>PH)opt+2m6}j zC&_bPwCBFa;RqxrL2s&#=|kJJNmJ&kMmNFea6@jwMc1cZgk?GY0?n?gKn4(Y#jdc8 z@se*a)G*`?S$AzwE&>3Z^nMTMEIN%{YEvk)I7PS{^)5nY*RDOS)}CIEn6vB(##O5| zU)TR;;3iQH>St-YA=Ta1y_Plba28ZrBvqund~9CYSo9dX7))0IvJ;r&O0#8Q>}+Se z5!d42@kKjjvTiJinA!J^FGjP+h@fbR<m3iL2&D=tZS=9eFeWu)#LF&_JLv6DQD3;| zElofWXzfSYCQbp2c6%f31OCNK>iPp4mL=yv(=E`?VFs5H@Ec8|o9B{qNL_3aun2(} zZwl>cIp>fX>|IXIE2I!snl9%Ed@Yo!K)I2$iyO-3k8AmnCg6C1&{k5wNdwFR{0uB# zdS2Uzi=(dOqy{!?sDPt?8a-q1OOnKaH^S)CYrk}6Ax6Me0Mw?BEUp6JYN)@{5@Y>d zA@>@FF+0_yvb92g%A(6@Gu%i}?*<%7ap}h85ZY$z<-d{<bilFFz?Xu_Y3ZJ1b5d;g z)PXV6H+^rt*O#I=$wu>TpCqrytc!Hy0LGIbtT>u%H+d&Yld~RpL-G#9MJd3S<<bJ} z9wBFNgUy~>QJNfjfQ%EOl%z~TxWKtkXG8NFlY%$-JbfWr2Ou4s`WA4hm=zA;JnwZI z5S?Q9(42&bF!5%3i5lf3Cmk%xF~#XX1RtEL(wHVO93C&0Z7TVWE%@vO(Si?)1tc`M z1RxloFqr5@*7Xh#D~D8~sT<jFt(khYK;pJ_z-A3RKwvSxF(8%19SuYZMn1`K6&GzY z5Yz+LBb>BmlsTmmJpu70Oi{E_nVoGEZ9<3@MLB4Ah$zB8G)vo=8Tz}-5@a4FCs1%i z7l#-Sk>msc>{co;gtWHc?~y&UR>QzD3Bxxzy9H_aLT+c10#1`(vSz;NUZM3NR4!?* zfnGs)2hfsK+8$fwa<4e1RjxXS9Iy@&<EpfY9%XupF1ad(Gn-u{kq`DjDgb4cxUw%& z`jc?Gvjsb&RE)D>R+7$0kZH6Tke+Ka55=2+za1|drx$)I>c`OWECCc|T2%1^1zw@^ zy6zaI3BV}|YbF587qn$qoCZGufESA2Df+Rlw6zm}eT60f5tbF&0hcI(maN%S0vMOM zSuERPa6NlY>_lf)(~|(5xoG^E>$V6@V$}v_UKu!BNtfrY=tT@Y%#g$=*N4Rb(?(}# z@GiLkmc;CVT4pH}9n&F(Gs|Lds^6_Q`}1Ngum?1_AQf_9S`b$n<j#1zoTdd1x;c(( zK}7dJ!Xk(vgeCQ)7pce(a(vO(pGVF%sXNd)SZr5-)cRs^0HaS=_f`pPCoY~;j7yHE z|Ar*{9oUZ%Zy@9dS~h4Nba7iiL(x0paOwq(b`85dO9=vgD~#RpbR{eY4s~u*IuKfr z4w|+wAmK=yq~s2zggS{b$vlZu%Noa1-u1E3jGg0Jpw4KjS)6eljKb+8T0&Uf>6ri+ zA{<GJgsuV&CIV9OK|S`B=oAvNH*jE-8M+Nq@;5CKjI2{HJ6fR1i-{#UK<9yBnym%4 z1go@w%LeyVVrLRdvMSZUD6|u9(pR7?Ac5q2dD+r>GRaX4+Zq^!jxSu?1z-Z{974i! zVlIg#g{K{zlG$GX$mmW;+e5->0J@tin$1I6?Gw}dr@P_M+pUaPm@ZA>D#cxRk<y=p zV#+YPlv5HlDQ@m9t;$7Tz)~VMO!$yOL8?c*i_Qab4Ks&y<TKqN@tHe#QXC1(!7)a~ z%mbKAV#4Ks{C3z!;+b3nNBd?*C7-r6tIOR$%Ojn@n=22Posfa^Y~>W+sP_YDG$~Ao zWcK0$IeJylYBhLb^s&c^gt~GtizDq;V4b|xll(q!wz^6;c%WdYZo~Yo&cKJ<hx!#( z+06F}JNy8Jk`{tbbB59fu#RbhsVQ{ie&{AwIGu@QqH6%%J4=^fO<I+*fslmCD&<^z z%UH?1CF=up;tDnUrZSo%n%uVaj3#H>wg9ISs6FzY;Cg;3MB3$c{3?ZP7r0(DJ)8#g zi6k)BI5d-e4qPcirZY59py+KjXy7Vv4G!|0LAY=FJP4Z7$_B%lyjm1z>;^}Z<|Lwf zIhyYn0;~i;{m@s1v@qf_Hi^aB)&pkLfRxoHS_Wy;Ul8IE)rRaL4nvdOWX4}~=`FLw zTqr<~L@}qpnKfoZ=5AKdhJs~8m;NEL3=}NT(8<@NE(s_y!Qz)EgkzrL&`}*V=DT~o zr^T{WVXclDX;e(af)E(xeWddEYHlvRj60NhOWrDK1wCX4gHD%>LAKT%HA4raH_~;K zTsR5M+aOTpj+USu`HwjjIAyF6>ZMV3aA^}ZTwM%Bk0Ydfo9GczVOsOS-tqQAANy%R zEIDk@scJJQfI@&-CfySg&uEru2!DVp$2|bJiU|pN26_p{0FlASS&Rpl5H>r3ay}bK zSGd>{YZ3rOBLU3fy6t1f`|~I9@Xz<CNxSZ}95f&!r2>{WAvxMBv8mol2fi?z1xH5( zF@gexY6{FxiQ8k3%2^s2&bg6yKJBPzI7`=%GHpij01^5zci$dOQg<KsXwa*X&rSLR zP#M~EjAhd4k35Vf1`k<yxPs{H7s%CE>6}#i`ERIN!9yh;D)EyOMdJZnmitx3k<t`D zJbw?bNyN4jN~cq&3eDp|^SYolkIZE>`j}AwC789-MOtGS%V0uNvEJwqBSuRzL*wnB z*t?E%3G|F9ahLcHXtFnR97qNTkI^~?FJE=BAJH+Vpu^~P!7;#OMwWq5hl|@-6WQ!0 zv6q|%6@qkG4p3=|=uCPq9Ua^0Wl~v=>CIG1RMZ2*4P+X<3XDNN8KaG96h?YsMa|66 zU7nuNMSLD6)<Y(NI=rXVI>^s-x+)=TsrYK~<cxi?ylO@STL8>XDY_|AbGiU$ln-`` zv7z%MQg+rGtzuqlGcM|qrvXSO-akM{bl&ECceU5ojcn!_cJ%b(15&(HnxU$g6!97E ztPO36ZC6vgxifmavOHGi)g5S`j=p6AMN@bO0OXVA3-SS2e0HtoE{PjYOzfU53k=O| zQQU?nM>wm~I6*-;22F~7vGh2mXv&zH!}l{b-6EkCGQbOk5=z#r6zS>dhDWpJ={k$D zX#8oM8U3va<rc1<qHSh6e7X@aL0N1tEi%f*K=<yQmB#206CaFAOlB->;{p){fd2{r z^=eETkC=F7^x->Va+Bj$(gl&2Rb>|EKapbQW)A=0Y9kLZ$zx@{CB#$!B4wsZP_qfz zMMbKu<%5WrhVNY2A8HnVEJfE9dfkJ=D>|tjY6A}1_#Eq~ue7#8lf`Kuo)q})kloZO z8;@AE4SZlU8>zBl-SBy%3!u50ys9ko#u{3li3wY0A91EpJWtjZ$`XJx#tGsWW<KR_ z(0VmPgZx6pHI+j&fvi?-YfyWua~dd@k+$cI@A7f<EoMvxEjhZRxZ-G}$23k8`9L;s z^05<MOiFF&n**3OIT@8{>1346*b~PCZG*<p;wHj7DWx~Z6Y@B>vq>43uB&D3EUvR^ zt3<1?sYVGWhw*`Ct0KHC%~?co5pCiqikdEyOKlsGJ6&XL6GUoMo6HPFrzr6o-+~m2 zJ?3^vsvmoXWXr%JY1n|XjutZXpfKjxTIUS;Lsu=r830|+0xMr7vo15TC-PSgz095L zl=(&25ro*Hi7a=Mz#uIn^|8Z_T)Lx;ge5Oja_O)oIjRy2h(XB^BL__~c!0^l4V*=W z(^}Ev3k&o+2>|vlV|w6-H@lO?30IdT2q52TlG@3B;*)I^n*v5^J_=`_F~YzmkUmcu z4e3qvUm;c8uqHOa@g}<oqs~9R34p_wK^d+9eOLkH$sEf_T2H9mg*t?e6@W>DL&)X_ zPDnPsR?Y5JXsALu25C?WRKo|EQA(}0g?monIr&D^?x3EOboWoU=Weq?MxO8oIVER+ zlb4G0s0Jr^f#MW!pR8$Nzm1L+zjWg<9Gu(J($|D8VjM#`Q|nK?8wKjDaG%i*FsRaG z0Wy|L6N&1iB4x=WJ1I7i3g~vkL=8!PoS_#f7DlN>mnL&*tT#hHna+D`dO>$ElS5KM zX?_M26Wn16rdx5D942{v)S!4Q2C_|P!6y+63Pz=I(1O{|vPoVUGM+Vn;ui$?U*s!T zqXbooWW;DLk=#=|boQPmlOMxP)ygRde$#lt*amT6+9bv35@wNT;uZqWN4_Ab6GV+c zGPFlCA%!Nc;p}v=L|+*oz8kH2!?m`|yQ5bG29(UWe92^_fk&eR^nM+`pAoMaOt2DO zX;6%2iAf0_6DgMxm~>a#7&sC)==9s#@4kM=V^m6Ft<wt>_?O984s)ThIEb@5z~71a zCcuruXH_Q{PNbNqwh`Lqc=UH-H)jL`NgU4<xI5D=fB^!K*y&+(kvc5mbA(<stsinS zmReu%7wSy_NJ~;5XZc8|r`sU#*i#K-;T#Zmoh>Y(!Jz<hj=Et)w(=L9K2=w!yEGT1 znt*ByXxpBCG(GDfO6mY3HZq)@(Fv#*7Hb7$nmW~)6&xHr+&}6<{>z?bS)M8JOo^W? z5u|`dp#bLAENqfGNgW&t#eH<I6Fx0xLnP>i=IgU`E+V>2y+bLk><xHxN31qMHXz@l zL1H%of>+01W_X*u)ya(vl_|~3)7UPxz9^>jej(R`C}~dp2uxudAgJ^8phN^<Y;D^d z9B9ONQV7Z}Oo5CiIm}|Q*d0!)L?d=7K@)_J0g<c{tij=-Tj}H{g);S^fR5o?o`#;J zXb=*KRJM?ZBuRl8i%pRr1uAKPEC#_BkQ8!FVtRj0lP|P+5~KjM88}14D!`JJU|ft8 zlKVHB6p-a4MM!Sg41IrX8>5jt9smi#P9XLJR!%J&>vOl<s%;q~BrhPST2K`Iw}_!m zmu=ubsS)MNtFUaL!0iK00EAA!!K6)$P}hW_H9=nGI>j)g`+@yUq+2wq%R9q-iDt1p zQ(o${=3zH2>E%OIhN9PI8B{kIHy=#EZ@R$}!%de<6;?@F3y6xkd6|=AeD2+<iFuEC zO_et^s9swrl&j>Skz^85q<zoO!}iusB!z+>D!XT>4kfzn)<2-?kGf=LVu7r^C}Elf z@+Vrz!HAPge96qvBx_462{PhnmxBJIht9i9Fr9$8TxehmQ%WHT9p;$h{@oO+))G6$ zP3#Ha2IYVO8>g0#Tq>Wa$CmQ`;Xy<t5QQ*$sn^BHNqPWdOB|)wE}37Lde7);!<Jtt z=x>>ai{K}(&NS|=|ECG)@M<^U_m=#jb#LB@`3b>dV~f8ZE9D{)+k98fZ`fNZ=CKO% z<7oy0shdDJVIHiiS=3I=wE0M`)H(Le=S~fG2)Y1O6rnfjkKn}-NS>tz4qMqm=sP); z6uEijlo`50X$`Jz>H%;q)6Kx{dCS}L);N34!z1?`F53V!01l62A|qxbMGtIt1utf+ zLargXBqb90qs^|A{ms@vVYP>-{E+jU)=!n?sWL$MqHj`jT(3`0k;YGpabN-AGkma{ zn>;K6lroSs)SM<~mX4JHF%KNeW*~k4c%v>Z%%HPqxUS4gY+jJaW^ibLgt}0iA)!+b z*9}zz7oJIq-gJ^kbL3XYnj?@%0vu={1c}V`wkg9&N{dVMgA|qylw8Q9@lw=h8x)wA zL1_na*NkZu#_^|`@C(!RkRmVop~EE$RD2C1rj#8emt?A3;hed+z>yMLm#vP({<K|t za-KQYE<jE*-~&<wzA%lvxkz1>>(J$?@*@Ak{!xes+!S3>xHaU^q3g;AIf>C9i16-o zowoC>#td<^fLmh*vbL~LW?$cX*#h&MJRrZV!slSZ@<X%ZAxVqQBAIUY<_RTJu-{pj z@1GQpEWp6jTC@NpX-LT?rbFTxxuqjboif?j?M1()atc2XF5bp;KuDKT7AgT^j|?A{ zqZL7yGGE%G(*jHE9e~8jvhzddX9pUbABAj`dR74UrvoGr!NfQTS4}8-BQanUO5j`S zq&v(Ct}0F&L+Y8^H7HCBZvzXM4!so4;u;4-+FZwxql89<Q3DoQk~35(g1SSRt#scT zwli)j14-HCQkCp06esF9=&CYmMRtR|ebL;yLNYZ?ec;m->hEH8FDdz8E;})?B3f0< zlE^bfHZ(ogZC+>gw%Dl*tO%P_W+N$j08ULMSClwv=h5>V$L5e`MFm1TpTUQQN75SE zq2-q~OkzzSd*CwxxMhl_%({tF?3A)b8CX=kiGf_FwJZ)50F({=rb#V8E=mPKx>z|q zA1nq-!7`Z+4me}J-tR26G4hX-62tybye%qiU1DV;z9Y?&gu>SF&L*u~i3U;TR<59R zAUa3B(>5er!%Isnl;kj)xJU+&1T9Ct)JCV)@KSL87igk}BZ`Q2MQ5fBKaruLgbA05 z{Ld2k<-^Vt5KWrmOi}wt&OP2hz0{#!8g;07-b%y~Ckx<HsIWz@OrE!nIMzI`MWdNU zZAKbni;_Z<=d~jaHqUFz#Fl5dgheX-q|<Yr*A7ux<!I%$_JaPflf@r{mlq3{z&kEZ zv&X}}GwNV-yi;^WDxC>XO-m~ev%$mPIpSDzycA5F*(!ZhFz2XdDvD2F_~z_J*BQx| zhRqsYNcJT$9D0%$n(zvdq$6KC{75wj(TYxd6=V#GS)?qz2@ZlD8rD37lg{vRxwK4- zR+wPRk{w?K30Ajiv7Zh3y1bk9@@*t(iF8V`fasK06}{SgG~~<W26<*$I*{}O5FVak z$=SeWk`K^6$qDE!h%bO&=qJZ7$AaEMQS?%gG3M9cdh_!b?(gs;^J{Ru`KhbfdhOl< z-?YEC_&rs;7z`!!faMe7SkRBR_$u?PkUGcaQUrp2*r<xF6n!53E<>BY_q|v4+tJ@w zm;K4ezj95dWQSc{wi6=vqSTt6<*>Q0g}USkn-`lWa;(rFvL$P*<9(w48xE2NpbR=l z9}VfRz+c<yvRhsIRBxfzmTAaut?;+L{jC*#+6q5yEx1qFiRkP4A8rKw5AU&P96pJL z(*MwpiQS?phF=Wnm?8xxrKtpGi20mf%;%Uc9G6g#{AQj)4L48mi+*YiU|xlSl#`N# zYypU-xMEZAfx;|lS+f$(_db`Sn;4=Y`KFnf(v-j;@MD@TOkx0-G(yovO-^e3--HCc zJVP#D_y_$BHp4yO{vAFbw#+;a$RA{DwRy=e#=7K}j`ry3IIQ+Fd2g0a-N1Sr`v;ED zeqH>5!Uk}&*^xUf^O4xH=1*eFn%~5hHNWW$Tr=0>(L3xPy78CtCHccD?=UYD8(9B? zsIfMP&6x6l{VklJ{LReAe#tD+{=>$dtsie(&p7n!7bRCQe=se}(53X0w2m9=yiPi9 z()~d$%2U$S!`vNBpD=-P9fy-(#}!G(BA1Egmr`Hsp3uZ;-Zb7KW|!)x=1<fYS4G@R z&r)+qoR)q)peYt5NzZ+{h8MJ#!xs?fCK5`~4~+t6u{wEy`*h+L6jBn>L0=;5LpZV6 zAUKvt;T!8D3_w|<(-D^>6@v>+QW-$6p~F!Nsi+S@KJ}(AmUjM>fY<@RHU+}CJPUYT zy-_y_mJ>OdXTyz^bFG7XMvKW7$+3W0qO%Gwn}{$YyWeC7mIQ%F-0nCkiLn{?%vy)G zPLgt+T6XlNS^S_BNv&blDI`K%kV42Zl~?$gaks8v^kO200^(JP#(lJe#TQ0){~CrK za08GxI#X_xffvEg0=$+#_P9Z=1p6YS#Py_9yNGNe6UiTXAUSn7`%1z!5Zjri;-A<| zi$qe3y6&h1H%|WR0(yzh_cU?O5H^wq*0{sy)a_4uyd8;M#X^<xh6Us_p-Ixw*09mB zt0-|EP--Q$luee}5$`IFwG%PUM9DG!SFyke0T*0HCVRuj8#ZM5>@8{djcM|>X;s*g z+LSfS*5^kJ>cfdG;*~+aU9c_TCL@Q49~q{BuZ7%q{LjG*p1VYtZmf++lPln87J?Gh z<Ai5|vMtk{aN-H3!Pyb)!Yc<l_)IIoG{&3w0MlrY0Lf;Pe+9@eeGkkr8rP%tbdPcW zl2;o*G}5K0tCN-%0FU@%i#E5WyIolzP=ZgXK#nbauZ#<JvV6AK<wj4No+;xwp8-9O zMhgC<$J~(E?IsC^@<kGC=^D~#2+WJz?#VVfMP`)%9-StdRRv|7rZchO$K2}}_aOC< z{7`zs(<cX5g;;Uxxa0clgBlu8@9}~b1q#wt9a@+7c(f7Q<^_=G0q>MNy<&-Yn!n9s z&e!w$8--@7NE5-S7HOjdGb<L}b?q5LI!Hp2TT#$V$#xKc&^6ta6!MV5b;Q8J6f(R} zaH(_?Z8rs2u8P(Kn~0s0yNhI@?pM;**Rth<{E2dO8mS`0z-_LUtlB$qbh-pe3&IP$ ze4?BbUSMgr3Kqx4wvo<DC4PL~4qFDNxkZZ(Xc{p-ZJB9S&U?C^<PYoWw*bxx*kk%h zk=R4Fg4yB8$4$iOi?C2ip<C?A0+9A5X=rjt2phqZsI7y90FV{5UT~<uWWon#R2$nq zIj2$TgHGrpVtD@*06LVxOP22G1sXLQlfW(_r`Z*I1#&g<228Ia5ne#l3G`B~rBA^w zVv;uqmrJ|?AZD_NNC5y0Rghx+SL9S!V~a?6MYTYE6m4*DLXgWfZ7!5sMLuO>)GGkD zD`QMb92~o{Y8ZlhMNZxxdk0o?Vxwpm)S9Bkm>zoM@Y@@a7L=p%tU5p6Tzq7&UF71= z%n;GW76o6PjN1j#TJ4AYvbcC+X&yiLu<+=7A@76Yo6I$$II40zSoIzp8oG;3a`=<} zEQdeoPjmQ_{yc|;S7Or~`k+6{p%40#9Qt5Yx&Qm!_bRnn|6@n6O`ZS6Gt`wUeYzO$ zmT>;uTr*f)oSWOr|Jpxv^rv%kv8Pu0-MP8t&hq^7syu#0XZZ?#vEPu+!gF&c>(?>d z-p+C#<GRNGsV6^Zo4N!bmc?MVZeGjFI*W@zQ{LX2n``vD0pD1rk+O`~3JwGdqaR$V zcdrYW%;l^7bGG;Tt+}~{h4$QBrw8H+f4;JJu-_#)=bY_kd5P6zf1!5H_K}lx@5WUb zbeHRk<9z3$*0G?b{$$HmT6wguUk!HOkDyMkzr9Ur!Ari8IFx#?*=A9(7VS0lli%2? z_8+f<0ljo#y<gwGL$9XYnVZ|!Ik?zvGXBq7+tkAH*?iL7x&7Rl-Gpw?!{<FWXHZOc zul8t>;5LX9mAN@uOZ23u`l4>P)2*qWU9&}9K${a9j;KQix2gLrt@hpS^iD4~=jQfw zo4fVf%|H1(IHk`dIA#7Wvudo82|&w|xw#8g7Y+bKA9SM+`L;ZBdHr-F82IZ!K3t{) zwkD%5?%$?%$PDzn)y3EF&(y=!pV!nipWCWfOJ^U4<mjo<Ii=^(Iko%Z<tvw)!S1tn z3W@&GH^ZH`%YiWI_swD!`0Zf7-amDbxVkTH2aBy<O}+FZTh&Vcc$d}8bAYY+zB=o# zx2ntQ%d3#j=?lA^mGpb0hfgI{rt#(vo}u&=)K8h==jIkW%{rHD0f6thxeMt;A=BZI z4_>xS-BUd=Ne!|^XJ@}=*lpQaQ)gWpCobIU^mE?MU53=R-)rx^wnJBzW@&c=4VY~r z6K?g?{9;=!zy5u0?%47whhHhr&CzpcUVgeAtM~ie`M#!1dssj2ZB>>m&6y@>_3WK? z-a;&akSEtdQ>p!XVzc&8qt)wKI^O=#t*XbKfv5KA-`uLM=<KhbrkhPm{o`S1NN<%4 zyI6nZ>AAVf_}?3irVGEdRqgE%sZ@t*HzkuCMlQM8;bj1LjKc~qy}G7u)o>?3%Yf@7 zmIVD=aJnD#uIwHGQc=BRs~ngSGj=9fm-umiB^MAr0%u)r_uZY(7B&|MHxP+q&O7y1 z4!bVg*sYaqOm9q?wQq?#I&5Ials80b>0?s=7@VOFHCK?5L48R*?-N_q)j<<Lm`Y8( z;I*68#kiRDF&qKJ3>mL)(xvU?mb!O&vwBFUy}ZBPKW;9Vdgnv7DZZ&5_d|ueSWy4| zfisY9!Z)(@i5Q1Fq!}sO`QeYAq4wzfynP~^)ZZ?JY(amacRI$GFQyaM9(YL>Z%}VJ zcbmEz-z_3-neJXg&pB0=WM2$sd*82xQbS_7&G}ZaR9`-}2nk<kf2*k(HplRoLHbh9 zhv9oWbvDM&IotUk81bL)+NSam==c*qUf-t9&V8>h7h=u*w2;?M^;UfsJz+TV`x~^@ zntJxRXQ+KECj`N%tKO0jZ~1q@UfPlCNGgXM<rgA4@wi<7^hy9Vd(6(LtTpwK$8J@7 zy2n-}aa9!`8W+f#BE4ZQaD4OPZhZ-@Ks_${^3?_P+7m->kf>u9wzDtLw)e*gl-0ba z9gb)>11%F(Tht_@a=WXFW<(m-veU}v8^YJM7FbiwRJBEh7iLl_st12SGm{DRMRn>w zm}UK>FtyAbJ9v7j(OC>>+pgxpi=75Ky*gL)&D0gD_q}05B+b|txu&l3#G_;<-|cFv zrk}l2-6OHZo~7~855<l(^~L6o6Igue&JXxMr^^_#?(eR!yYJmk?^pC?ih>cMD9tD5 z=H?IUf6QB3Sv~LJ5S-a{&l<N1@{<ybYX^pl`qmkda%8@kW`nDD|6A;|^?eY9mtTh3 zUg+7{_)?etXZ$iP2UsEm3sAxjcEGUg3vbQ3M`wN~l#=?*sb9XDlC~GEhK$A7FG%~4 zh3IdE3X2u^sY7L23b>W*@!-Z(SG#|Vuwquo4Ldd8TdAL1CVx=cei+9E7GLXhIAOc{ z?In@@tKGWzHk=mMkNvf#zLWd%88W~hGD45?H_95N?d1hd*eF)}_+6XOe{;tzYHxj| zPx+~O5;}l3r-#~#W?lL9(4FeMuY|O6wssh-R#9nEtw?RmS9fw?mdz$O@KZl>1}YF% z-buDV-TARw)IpNL>Whau*9FV!g`2iI7Z&GPQ$ObVSQZy@I`z?Cw@2=u@`d{js9PKl z&rVaNR?eEnd9*hs$ox;7CR|g$dczjAzrNgVI$QEXpH*rvT3}~M{S?X3JYMgr+leg0 z>U_kNP6u4+cEm8nL3SL!%E5lCv)Wf5JsL@xG;3w4zJk;|gq!U0`pP=%urK|SO-j`0 zLueyvKZ?61wV|G#=u#3GGajD<0jf$DH5*+K*N@M{9QEp59*66QUuNfd+r)>Xy=)^5 zwQ*?`#SAxD$ZDJ?16K#$Na1kUk*6R93?$2MJo6)ZD&l}U)gM$RFbA(ZNdoRoYz_w9 z@H!+8j}tW{CubMA@-AyH2S?~(IgT$6S~t!-#~BTOGgqAVSa;10kJtk6C3N)Q)q1y; z_VP9O5!GiCvTV>Q({AH*j`ZOlC{Uu?z0R_p>uyIp;tO5!oS$aqi0F`T<Oy*Uo~R=< zkJQ`!Lr4YL5bcvimaF;j1oTxgQsdz1UO!lpXYELG3drTi|D~RoOTJ>)zXy(Q88JRQ z&o7){?=c<3UEkEpWjD!l$Y_$#vSumr&uZT?PMn9*eDpBv@V=hXYKKT;d&@c^Aok?? zU;UbTgxKY)#7F*gt7^`l=(Jl(AuQ5e$~!D+{*EXO#$oRZlnI=l>Laf-j92^@>iI>( zH!ktK;~9h*NvmY6qo&GNv49<(#_9d4%|mtI`Z$$&98DbEn1b3-l1XgarnaeECo*iB zuYs$N?KI25C9~fdY8csc=InOk9{ZznH>-o99`A2srK?Xw@d2$f={MyOW{%~l*CT55 zS5q&N9xsm;r+yCEB*PKvjiSr>d|M0gwz$x0>i82jsXfH(WF_hYm+<7Z+NL;vd+Dh9 z&=1605C(A|fhg*+Z+SWBS_eT*UG*-)DKT~*Mw{MtIj*YE4YAZ$&984(7Y2>hW0wSr zD+G@|`uWfV@Mk$OZ+VB)T~jwRlPjqo{ydz=NWOER)3JhY{EJ8!1<MTeK>~ad+4}*8 z;SRm)>iVW7gph{TN2sdn{uoD5y|t%>f*+U|k$NbOiX#MMyXr+49obfd*~dw2ef61e zOZ9?Qa0^Qyv40#PT~pg%kJ28>FwI5Pp@c`v9z_^Y)O2UWzJDbqQa0CTZ?!=C_~!6P zM-opi7MV)CdJ|JAPW0g=&Jz{N9O=x-ke5sSMJCU_%Zs<FgDZ<fM8qh;&K?!Yz0nkW zbu-*mIDQ8YJ5-f$j)=}wQ@sMFfCNs|hdr;yaN5b_W;Inx1dE33yZSSjrn$U-5*czK zovVL-ixOFZR;F&X?wZYzc@cp4YIyl#?0+a@)g$^BE8AnBe*Vpvcu1<b>#Uoj1g8rM z&A7baNKJMBD_r^6srM)=<bp;%-t(yDuSVQht#2s3>FrtRq3Jh>*<Yu9;+mPEnMKYD zGcyjrQD^8Au)l;pFYAZc)9uzz*VHFOp>~JozT07xL^ST|*KEONCf-f(;Q3!r>P8J{ z|Kojhutgd?bk%WG>nP1aeQnQ8=@w2s^&z)wOqKD<uJcoj8v_5E&xWLIFY&?>&IcC& zBH85S34v*ra-5n{e7J3VLkHU{h0+1?2qZP-P2Y)orX)WI{`vm@j9z1@_(TAy>acGW z+43~}XJea(`eqszbxnQn%h4;$9Gg*AnR{s4%mm8+O&c)}PgcFU6N+5Ye;q5)_U)nW zX$hM1thE*2_^Pd1wq3l8GehSYsdM7t-Vr9G%a-Y$6mBx#uc>$b?q-`w*Hu@2(uC|a z343;4sEC{BR!yCHSU6|>Y)nJTR2u#XOE-UT)EZ|a^&;QM+NsX^X-F?4zd2GJANPJk z@!uhV%9zF9Ox&<kf3^0Qgs$b9`j^*kRXg@9pH}}L<JiAvo`!kP4bR@Jj4wg`ux-6u z>nudohrX{!rP=_0ta^26vpR6(GKf(<`g6&ngUNV7;F>yrz|LWB#AMD)^|Q9J`Z76M z+O;lm3-ziu<L2+8T`{`4^?~?Krz*;75Ar%c?Q%QE;Ps9d>{N%x+~@T&Mbv>rTz8|E zDn?8s*3g44|3dQ62R(o4+cw$m)Vz2wQ9}StIZQ%>vHkw}_1Gejv{EmPf;M@hMe0a- z1NDd-)6EoZ?zlR`OOJ?}rIoDG$aD;+v)T(PQtEIY_&=RKss5O-n)XNQpxPaAR2ac= z1=%F(*B+XpbBd!-LPq<8?ozwglPqra!-u6j7{y2=l5$xaS2i9c^@e>(4~XRq2elEU z`OD7}85TM*Z6E2HaXs9lzev$UPGVN>xYkI7m@;*B;i%euYg`hNL91RgaD$EC-q&56 zDWw^E9*-Yppb2uQ=_e6wwPC*YvbwggIr?Wuy`r~SJVd7?h5Hz(JL*1BPI%s{P*YP0 zUZAI$8WyjqyZ$J=zGj6c#Nfi!HT7B-{>zr7##VHJWn}2*$t{QnaMZhBtrM>`ed(0J z_V>aUn}CU)peU~7Woc6ZO$yfpapFP+KJ($XZ`PUHCJbvB$4lP|3+XlMD}i<_s_U~T z6BoA2S%2Qmxg}(Rw(E;{Lc8kYFdw&C^_}HVEz+uKrY7{te~o2NNS4j54Hvrv4Ls-; zO6u=<(ZxYs$JPHRp-Q;h=knz}@0Qz4V<XnoU!hRMQt;J_@T~4f^7SvqtNLl1q^Zw1 zP2;l}U>`}i<lJixnJi0n=Z|kynm4ZmO?3jRGP11I>yA6EMDk1COAg}3xU$rDz8lem zIs1ro2PuQOJPH5LrB|zWMz<vTLNXNvr}q_G6pW<4cxiAtH5{Ey;yGO-2P9~pc8^pc zk*bqlK2M}Z1O4`!n@qq|ZTY7&$an3UE7Kx<0`?`=hu*4jxR?5iWP#B5&SCYanJvmo z#8;n6Yz*PIn)+fauAmjVcp64c-Tjjxtr#m(J^C`jGhybDdMOlb?O63ranXs%tG;$E zzePl1smkPmzI;Fi>BuGJOA^zbH$p=^>7Bt^m4l&}s;LisZHv03)45K4heSzj3~yxW z#CoZa@a-?k2I$R6*P-`6B4m$_gT)kl%Pv#DTvN}*A~K_A6$Y8VH|pJPTgtdDFu!QI zTvHcw*Y#acSKzz8tbQ8PK)vYE;f%=l2~~Da1;7?#WuK(TO$R|n9Np=0Nx*a2v2k*n z3?-l#e?KHpy`}OQdVm+C|5hS#KtDFPH(}mDO`UfXVc=DH*;DYA8#xw8R(*iG5UTLb z%}9~{arGPMWL90WKL~gK)g4Uyu-$|+s#{19Jew6}obFSjFdErSHTCs`5<-BndbFmF z{GAio=s8V-`RYR-+JrdM8Bpp{Qe`%*Dlmr@KklkSg3B2~9^-kFJo<81-)2ub^v-Eo z86xku_=Rpmv-$K$sfUVyee&nG&~+kIp1w}5VCYLS-itRwEsl~X_qa{mo240_XbrE5 zdp5k8+uTFals~*lU39A5-z!vcmZv9kYt-@IfGD$gle&cK9go3}#kt`mVqnx%>w{(r z!g5x7>eHt}?qcs|wtv1YfpO~3Sb+I<rtbKxcqPn6$_8dFY$wyZ!p<7I1QvOlgpR7M ztLNnotAzoIi9)jDO!WP~zgZm#>euZ~b;#-M9OXpKOy50cyQSrJReSby66rq?>eIu* zDxdhnkgFSJA=z${_pAf#kjH`Ggwd>wOLcE&X{ED_<E_UQU*oykqig4BHZ^q#zK{I6 z;kflDqPOo<!Ej+1-iG(zfuIq~Qx6gwn<%SG$ql(sn*8x9Xs;o^#qMX?lc5WIYVQ`c zVLJJHlL}_E^MlD!fAKM@LSY4BJj`RCe-?#4zJhE{zd=UP>DdWlBR8$AbN*1$3rP(d z>7^fbARmj|1o|=0OCX-En!3N3T>2wV70ZmChVtdPl6qxsuosU?mH+0C<C{7)^^JT9 zw9Gyimv*5gGvT;{g%DppR_zRb=U;e>4H>0fQ12>#_QxUL+vshpsarfMl)KgqW6mHA zkKhjz*W0cm`<l9NlT;e7pn+e!SU;w&!Z|3|2==TchhGww_#yFzo$C2f7ARIES>VoB zs=gQcx{QJSTuG!c*`RhRzt}lU>JCzEEy}q%mZJt`kW5^5ue#@ki>}BwzEl0%w{#YY z=Q$g+oFW%TWF%j(7PyH=Mfunx>FlPoW3oBw7#2v##mD%LwpwyL{|lYz8<810+q7@; zm?((4D_}YKWsaY*qYjBdr;jJ;4^TS@h>3er%EZ)*ar?ULcwP1Wqo}UTO1os@l~)-t z%#mX465pe_qN^8RcwQC5+FruOeIU!*sy$-sD`{)0g11jfxc=-MyhP3B>PkCk>8y3b z15)kV;qIz8KXQu_0jO>Tg26iOjJozagPd!P*_9D{TT=-Rr}o=K=m+C5+CS>YW7OxK zutlfqtFMlsAv=z;{-qo0I|%SASL)<et2cQtJT6T}E$`hx&yvm-7{+r`sXhA(<3xVN z>KNyFQG1SmI2OIio}JGmjN*t<l&m3D|D163NpkzQE*LcFHss<zIN_rSRev32&2+-t z?+<Z#hB@f!u5V4aB~38+n-aku;Pe?G>@RP4c2p#ocB<bbvtLI&C4{c7UkEj3Lsm8% zpSk{TO0|SJcw<hunD$zU;kK`XyOICYBxzs(#zMU-HT+^SLtpSep^2f_U?R~rYqh2x z3!{lr5v_`S_D-*4&98G06XNgs{LRV%zp1xBga{y5PB<Hk;<y1jP*cx{2Zu*FqwK}P zzY>riQ&VsI(V%=7l12P1B%iM8QE!Rka`+yb&;~K$aN||wn)=#fHYHNdR5PE6dSlG) z{!$euE-l@q;(<}d(MY|1q&p+~2Bm5t2;DDH>GyxvTu={9lwFL!f!BP&%X`(k>^W7* z5v-}t!S5pO;W3Sg>s&RD$|WFc>S1C;cmQTkPWaj_H?u>^W$&PQnwsDMC)YXeAWg`5 zlGPjU0Bg-t`ENu)8U!Y394bUg7!Yuw47I<6zWsyZsj8{ZNH8Y#l*~|3HgQeWCGE;Q zyOMCLsIwkObje{Cstc~ONoRf$w7T>2gpFuGB6Ws~&N|OZEc&dL&fmamG*ZXQ-s~Lq zuyaZ|4S5`m&O{1NM|smxBrFeksy9SM+41s$FqP?pQI6-}0l&e8C{qc-=4QP76DIzQ z_eI@nk_@}`vT)SDecEXm>d9VV*5o15yS|s~sGv^-s9#sVox_D@_Q_~n8=(?Y0`{1= zHV7HG+92&eH(4^7y5Xe{-Xz=x*g8z;6Y6{a!Dt3GYtZ}WWmtw}Zl7|PS!a{_cK`@H zKxCVX(8Gzqpv>0PL*ojIrIkihQ>pKi7b}j(o@?sGrc&8+0><6j>SLdgy!Vx^YKF&d zqjO2j6+)pk^~>LK#NmJ<2Nb6@TI#GQm#<$6J0BO#MsGw$3g<ndwEI|oYnOtd6NRW~ zi0q5|M!;{Lk>78Ub-6|urGp7KeEt~bB>8QgAyiXunBG9Pf72EjjceQ+QSk6cv=7l{ z^8*NFOE!qKf_&EZ&k5;wf|3w(dA{jq;iWRt!`;zCHutpb#JUz-Iu!AYxSg2H<-EGA zt{w42Mcv}5q*@y`rWPZt2E%?6P{MkN9-GXAdqL6kZ&B<cMud)ms29TMoX-|Slc#+u zT(=%R)T*NVZ>%KzycbaHENN=$xRl4}XN5;tC<PP`Rl}IRQe&_0U0JbC=!4>$5YVy* zh$-VSN$*#aqVvlUhMHSvsL^Sj!rga?_?bfCUj#HOPh87M8redhFly?u{}&39Huztb zHWSj~2T?x1oorGaR=p?|sUI<pf`g$q2b|QOgj+vUu&1glddzfFjYOsjHmn74urtrd zzWWtY30mzgsUOh7vwjzkTWiG#UiGtRjdqMs%w&tQcS#7+ou9wS?&5ti;fB-pzvNzh z_#b?fj`WqOBcS5ucbt#AaW!>m9B<I#khCOvZwB+dHwMe#FB1#WS8ct|^FfJ}O0&hO zHsn2=%MHXewMT3qeH{7<IT`Bik-80q&0|NoMj9F8?t6I4M#sZL(?h*10yMJZnf-0| zt&uMMA-78Xy*1x0e-Z!j%gMRYu9**#{&G|LMmBKAMY>0t%s3{WIPstQ@KDJ&bQoFP zSXt+6H-Ah<8L7eC7U6?xsq_1>Wc#?}A+6+t0&D9U7wF^%4>#l-LH_4WYv?FZQ@`^? zrJA%`27&V2DRs%uqJI_C*DVyGUsv|D4aO>2FI%&w?i5v9q|(u#1PQY#?w-n*lBe^G zen<pPGz^ILgFaf}AU(V`G8PSQ_0*tvq$4&^>QhnqMK<8-t9NfwM)T99yys9(v;i*F zGYN66S4iU#`12#5itHeJEk6!ws7_s*_)R}?aCKR|DGVrG7%bH3u%hNA;v&l8PzjdJ zCU>eIC4xMIe)6zXz^ZW^Qb-PC2l-JQ(C^O_JsVsDbuP}jv63{iiMysA6{bNXl{a;V z$o!X5pq_000Bui{WV~MYTGiry3q3ne>kc#8KmAu41V{>1-WaM2mQ8nqh4!h)r~5)w z!iZxJb{&b%aiXO&MIqQ6iQww~r3n<59Qmf%ls%D>@+wJG$WbJyUMuA+$s-CKN!FOU z0-#=<zo%<c-~83kPzhC%aFUj+op<ZahQ$wQ?BicTWBR5A(ZBp63&?eaQ>iR6*U`!b zDnK{Adt-71=u@8iHuHRK`RlgZoI$i)Gh*Y_R{t&u!1`-(cZB*i0E#r9wxv}1cO$)Z z1>nV<?h?I<0xFZeJD=6K0rTs>NBIHZ4>eVd3S80+iieY@={krU?4Mo?)Umipr57W& ze4Y55dghnHYd|qb)&+R`e}}fVo`I(rtbi_w|Iy-1*3@l}u;*qgZ7e9vce|ZaLWSq= ziWdtRIhRouc%g*9mn-w)B2u4{a(V*}r_LCo&5NFRhGBg67foz&P@MU-b`N~e2Hw(} z(kz_ZNHNaHr<rUwmv?aE$+0~N@4>J$e#jeu$MTRXF8+TZO%IBWD2`iGx5HFE(XThS zjUP=>3gWjBvrK$7<Dg@^PIv059?0X>hx7~o77i9_?4g?H@uUMF&xeBUobB4>vQt$r z&8ULcu_zORsj1cf2zS6-STA1Xp813*ao+n@1eAa*Qin}&My}F~cCv6zJ%MZtv+XgH zR{b`n=*6qOz{=WW<<-VosWr95Gn_+S8{*wQ=9a{%{S8-NqnK6PB02DzQ;owR1WTSK zTH1!WMRI5b*^>+9M7Gn&MY|{GE#d(A&n=-RHhVUdohSG}{>YSOyO!<eTMW|v0dRyH zr!Z07;30iRJCMwL`F_0IG-oy%o__jQ*3=KNqr-L^Y>4`Q!GOoXcSZ{aP-YC_rx7Z> zL7jc!zlU5#FTi6aUb+m*(ZqRsgHqdhSb*@9f)!iXIjS9ry4jRh`mFB!=x`T&_Gpnc zvafS4TVQyd*AK~ZS%1fJL_f)*$T9A-vs`NGr=Rx{vNGb<=R}=tHR#8GlPMI{U};@j zIt@!sH{ML~oS1!$YvEohS0bh-?Lob7X!EY7{>OpY<Sds^Gh&%XZ%^clg?>v|vQ-rG zk`x#TE_KGEdn-gkxqUGpKQEg&xIR&Vu++hiP7wF$UaJlfVvzWaw*2pga+u6)H7fBJ z$>!Ui@c-Np-*J5%ong9|(d+lR2pHM*qPP&Rh@VU-3aC|4)G<0NY?#V$V>y5(%ZT_I z5e5^Zzu?3f22QK1UI}F2*o-uXYLw0W(=E&~7;HjeQjeJ4z$5*ITIv{^WG>lvpNDoB zR_XpsyoLHw`4ZSAKg0qXsnTkvIyA)1;d04by6k{SgBx4YV6Vlh=^j;&e82>Rr<KuR zQhL~DV=1vU^*SmM_bk#@O*b2TNEWJI*dpv5;S<7d$fOHFj<h@VLoRNvlN;2@KNYM+ z{L$(OQ4iFtUb))SRa3v`K~`vCY|w;W^CInF2dJTcBWd|g#X-~mQj~E!NLrpmk6DGz z3@3^D`cQ>*gqc*NrT<!{GJOqrSVHRRZDb*Zz~JgDau$PHuho8jg&@>M8bFa)+^Jp{ z1#$-G<K>N#Bkp@L+$MzSQi)r&-`ut+!j<`jrtLJViB0$H*{OEpN5Ml#sZC$C7sC_K z;9>e0k`!E1H~&Ovq|k$wl&z@EK=R-Q<{X;>7mKV0ny`L}8YwHKrBrJ5Mpf^;BcgW* zE*d)%=Jld65<f%~ttsi_ULL}eM96L%w)wt*#wAL9TUSA?lizTiT;k}pdq3v7ksq$A z^CJ@1a7l0Cd?h9CPc*mpjE{j_Ty=wF?Om%0C{-;us$L`!3Nbt!m4!aOj3|<NG?1fv z>&@eVdUJvu+6$PLW@e+vsVypM>SZ#CY>md3rWv!Usb^aBMOxfO4n6hLD7v5*=yA-* z_>uP2q3E}ZaFMtB+|{*M(GhqR9?brJSD^LP_Qbui-_LgCtd*u~s_-mOYC8uP+sy!h ztxmZ>hG%Sg>kI?MPx(^FV)7n#O}%}L+d4ACBAXELzJ!?zJJo4wk90D>xtOV>>&)(i zsXXKrHTA9)gM4gMF%={Vq=wS(jTTd&jEswI`K5Qeo%E%(`gc*COoZ^DAn6`?FTGaQ z&=pf{{dSx(w07#Fme$nsUl}G`t0#B}x_Z9{p7*QxL5a<_7lnSOS3(Kt=+a5s1#Yt_ zfENb6W~PqvrUVA2pZib)T_HZYWDL7Xn#>{pJS%)LG~370kC&?JxdE5Nv!^jfP1W~P zhItz|qGCtAytaXM+>K*7IK_C}G{*b8<bO?IqJ8O;Nd?{YH2>eiUy}4XsgHhluyXoF zV-D(NHxBX>`y{)RCza=C2`+l$#3gF#G5?iv4k6<hs0;W>R%ZK^E5WiUd+4e6^ut>! zoe4~fT=nb=Ho}z7)^}3n-8dw#{a5PGe-LtYNph~KS5VB+uBvAag|^hLZYzBxNBUDV zVv99yP`8R86iC^tsSC!{fLvtG_)y*#mBmk-wD{^9!lfpK_%E7nUsFE^dLdV3^|%y5 zv$sfF<Dj2_=U<X4kLKhVNvtQcb;1WC%VrJf1vT}L&)=#Jo$MT`pFSAWyO<C(XuWWP zyOqOfs2P3gMG7_jY!%%RXee&fnSVq+v2>LYed`AX%&t&5syc5oYLWV$h8I{~h5Sxm z*zK$g(Ohe457}Q*kLCF%)UN2Z#?lhB3!k#4C=Na8Edj>zuB;*|!&2qHcQFFBH^Ie| z*T^dw8q5e@Z$hDCNYw7q`8{1h8=gOP7AWt|9hRip!SrN#LPE_M9ne)P!NBtSuEs4Z zbp(ao_=FtrNQMCnCdF`*sMXU!WosY^{DSQzetuMzX1`B^6ELHr7AD{_2zphg*FH7h zTdAL1o?k%6p076r6s|Xq&+3IXP1McTW{IAR`g>$c`PC|`yJrN{p490x-B*4+XHD&( z$bCX>TU`>5a~bLPxMQIqux_Li`3FO{Nm>T{y1h?aL&=2HR3-=NC=unMhoo*fCXB#@ zr@@?mBeYiq==l-ix3Y8_>o=)>{_FA11CpkB<}-%^adWSG{p}<2O^z+EBEu@>xw%u- z%Dnt^9S+H{?aueL&SQZAc0Og3aweym4LcaB+m8jucu<EPdJ)r(<WVwp<^fN)&6?D$ zmO=`Z7>@IB@T-Rf3(m`#y5!g*eyj6e>>5?zepe^bYaJa@mCfpVG0aCBHg?g$6fKVN zS9h1|i)-??KJ!uG5-ju4eK;YVwdSt7-7wtHWDD7N!(Q$B)BjKuL&SS<c$vbSfhaSa z4Kjp^u*k2fPsj6_g}y<PxnEQFnVUdOxp8dbWVrS|r0#531pX#j(ij?>F)6l5%8NeJ zP}n%_fhgYRM%2scFXr(%*VH>shUD&ed<cRPzS{mmJ%(=HuzxL~rA&|2&mX@<U9}p3 zOu0o8&aC=2TE(4MgHa#Y{ePIwBsH|<(A~7h$nJR9wO}MmS$>Q`qCz4DVN~j{hT*+u zLKz=9*5e)-(xFq_W2jY@Y=Y$zv|YAcy66-kRSg|xtR8}Q_lng;!$LQS^D_&-(32Wu zy?#72yY&<^RFPL64`-(z8#Ew>M=o+|Srd(ocJeHmg(Yha^)mfjGj)$4iP><)n%Z}} zGrZ1VSC`e*xV;S*8eH%?TTJSDN{^zt*sCk*iqPGq55+1S;>giCuSeSb<L<z9`ouF* zO9$06B$S_hwoWML55nwJ_Z=JQ*b~eyn1voZ+U1k94A*(nA)Vi*ILfKTdY44M;Fny! zQ?+?y2p~p*H(Y6=S0Vbt-X9U0lqjHDO+9UEP^o_tW6>zedXnCLCKMg@7*c8v2K~!$ zi7ty9L*0=T>dRoUG~PxLi|;Z0ga3|2(Djz5MtRkateo|@$5B1gLsnigaHXn<2ll4Z zX^bYDpT@_~SG1>gjOUGh^W~^To|&6v`ler<yOgm%!rE)<Da6^WO-K&3m(-kCo3+l2 zs;y5ybqmZNC+JyHQ$N_h#ntDx)Dch!jH{i9dZvc+M?^XCKI*{DU~9z8NCjCRy8D!R zEQ{AJ6MYB#gaq@u*gfj;u|QFl?V#@e`mNBT^kB7SO&rs(P&&|AU2gSiYGEv8Y}`a@ zXR_^7ClVTiJ$o+{>G>Lo1bl@ZH)wl9xx3z~RH@E6*>~6<E@9$nICMAcs@~|1-*A<q zHEDA-pED$st`Vr|QWqgqr5zK>gd~<k@t(v6|7XH|;>s7)-C(dgNFGx!A!%>yoZ}la zw>ruWtErzwR=8bg_ExVwb>{V;ryc5^7Cnf|WAxpB0{me>h({5RwPaS19`v=X%3KZg z-miq(a*V;ccc=2$K?;d-3Xb`3Ae1Mo4?cCX<*MqoqR)|SckZx$sFJ_*5#dnT_uR7M zbRM7{0i`)6q&_AYJZ2F_a!j}|^<Lxr@2ZE*Yz!f%?sWDZL{~AJG+oFj>5X}S6DS&S za1I%CcIw-Wp)k13ynDRocdD16!*M7b>8dw04E23i8D!oNFL_cQ4YS$(^qzsH>FQm3 zH<00v^f#q$&iWjsBkXaGU;F~^@I3VP`Wg*mPnSkt_<+oz_!>xq>YM9;5Vv54SQeLl zJ!BS>-p-o(Nz}et9Lf|Ue$G_PO+Mr^xbYl{I{zCO3fjk@R<jg)Yjdodb6)+}PG9m8 z9{9isc*9LePD##i2JF(e%2G>0)IUUYV4EA?={Yo9);n*+*Ub|^m7daSV2`Zd@t_A? z8ITD=aytJ0?f2SyFM(Inx#@N~_QxvlnaRKGRNqJjOLNw?lD7K47i4b|R$=tTM~ahZ z$>m><;XY8?6VA6h-wlnSTPBegIx9G?y8@t1cUk#i;j?S%UMY|hhIeIvrMxb}weUO* zz0*sL&SLwKjBkP}SCDmGQ;&{U%8EwvM^ap(VHwZ-C}C=w@oge?>KhviVYN<b9}K+L z3ys=T8I`HnS&b`Em$|3e40=6%<H;R}YVyt4x@TpC3S3i%08FN(w)$?ATonn$cmz^i z`q@y_WIaP>ks!3ub6x#3dH<vD3>I}~f5tgK`$zHjrVGS_REX6V4|T2!mdRVlP8H7J zb(!vjC*u63)$*C-_iNvQdKcxJl9XfgYxT@130q{Rdgc8#O99jgb^CgFup<qY4Ksvu zSZk?Nmwh1PXgL$JyBy~9Mi{OexD^Shj>m^&yTQ9{DhV(5K+4UW5(rfwKVz>673zcX zgOJFG;1n6T@`J2))G&Fqx;zXr2>*9g*oE(H!K6Let*<ba`gFQ;DBGBkkw>NhjJv7u z#6OlE=f)Au)jKQda;{fv^7cctLcC|^U#9O|PaXQ-(7Px>Dmm_gGb)X$u)DiS9iiA5 zC#ZTmI~kIRoP1#FVfO+K)LE*j+ealr>RF_OL|$LJ|MWCdpZWrIBLw;eiESeI$Mut) zpLrEI$IFnquCV&0M44H{!{UOhran(%rbDk&FJak&^kKWVi8G`T!O9rw4gD1Iu2g~^ zyvol1;tX>$MzT@%7yi<u5veyva>Tqqo7u@yJ#~+$KTg6KZ)boE(gvbY{eiEGyh&-d zr>5?_9OkmC+eD>biG^o-_XjvoR_PrVd+92x#oEc{kAmMPLcz>B*YKj)!JVi1ZNpq! zdN5D@bb&)vjw2Om>&0#HX$fCprT?N`2>KG{ZECm1N|bfG!(<m+zD>;^UOw3d<7uxg zhQ2nc1U7W&<MF$P&TzzJ9?1o`a~?jgs{?y*gI+Y<ovj?<KqbkPM8leDlbyboT-h); z{mdjfHZpj-k>q<pi8~OSFoZHFxIUiD2G@nVpTu9=UN#_-?*m$GY*pvR3V$RdmAb3A zE%lAkP72qC09F*#m#l`J>b}^i&i^#s*V<j(C0YG#x+0S99Sakw26}v82fWpFQnh%i zrl#&m<kjm7eev?{v#l#S*$)oG<Iy<$L*ePUOE_Lpu?_^Z)4&w&BNRl}Y9=#3G<_vy z&wV8XpF&sa6&GcsmpFvO`~S6o-+QG4c9d-WjL8SBkqTPGPm_ij#QuON2~IyJI>b6% ze)UT<<rGClz5Lmm^+sE>_3wY6l+N@~n+U`BUIz8BKeY{1)osYe(Oy#Z5|UEayizsu zo1wX;Qy4N0!oTtm81OHi!0n-h<4_5)@hK+1f?2wbN*aePN1YiiM~~Fua!BM0*M&Q0 zIB`NT8A4x~oBUFe-lX5Txv%d_@PoLzR#X4+MIn=u!q~+bY43&o;naW|A~Pa0h@$@I zR~<;YF5`czL}m2+eG_XUtvC0El9(Cp=g1qrVUB|wB4qr-9=RN6$Rq?yc%<2^&V7@> zN{**DLZaSy+W|(6HS41Qxw_f+yaX%f6x0k7aE8hThTd*kN}1Tjq&7=+Uc{R`IZbJR zQeWl2&1whL9F1Ej^-%u96>;lr$|w%2T3?-;BWC4(P3o{`^Q`+DNXxy>GU_d<L$5nS zsS8imyB2;KBwwX=nBd6hLGR%W>h$0v%rr!PRFClfRZzdr^OEZEM1ERm=&M*t<Xqut z^+NvJte&#GP5tv`rQXbcRwuIe)ufB5SMz}#;}pM2#pvH}5}|Wi5OZF^AQ$t6cB8%6 z?w?lg<Poj8sH1$M0lb2i&M8&@!MB_fTIVr8h9@4}?X0e--;-}u6<%pIKfhEcR@;1} z)H7}-Gra2hZR)vqS8Chcm?2RvDXc8<Z@U_E0n^RqPs>-bV7=5)`Bap4Z-@|CUw!5- ztW2<9)C+L}>wv>+_{AJqRb6&#y&AG)7m+@+d*d@bnEoG!+wYl}0}&2X&CfDO1P}-O zi0!bqTYSp&CQV(XhxBpDEt#Y11)%<r)An#b?sx};nhvX|t5}O8N=H9G`X!%!-Xzn% zR-fGY+e=5)l)t<}h5ThU%aXy}w@O3Po-~vp+~T3MEy_mKo7bTpH-q_JzuphjC7k09 z&P+X@!@W}X4|J_pzXM5L7&KOoNy@5vVDx#`iCG}FyR&NjJ);PI7vW9Pj`QqjZBpHx z>$d+mT6$;cLYm_4#=nF2G@Q8JVCSM?uVWQdODt6%bGR0iU$?B-<zGEHH<#Skw{8j7 zIjR-v4MKnxkncgs2@6qujP2b^u3%r?^-hEz+#Cdt^{XDS7^Cw!chtwySv(OOIbQFp z*Rf5GR(fjoOh*k8SyPLUmcg}ES8+meKvyMaK+w0QcJp9t9d5|03rE#sSpb#ff54kG z*=y&QdXBpa`qEr?E2VU<i8gW{D=(|6^OEn<AKr_TG|c0pJZ6a{ix_I^Bou5OiaJs* zG4MDy@Yk7Z{H*7-$=ARyfm;A8Gdy`q&?kgCn!2u#rQbTbqH<@|xr~P^@hXo9vKR1s zvbW**-m8GM(VXWjO(5*eQFTau)iHkce15%fQ8#c=O&P-DUtzl6UD(Tr-!JeLfxA{a zWs70qw~NR}2<^i%x}b)gmJ8iIwyIGVpBE!KnUPRlk5`H+p7Pdp#7KU7bXT)B@SN?* zPm*k)rhfb@EKDa?oy!v4hCuBPV<Q~PFs)3U!~?PgAlk-BC`&}-ZN73xIiqX6?Mk|L zkE#=zOIFpJ_-PBZf5vqV+Zfzit`v0jWjQCAk4H6WXwBdA?mmc62l%?^121KGP3?9v zUS0Sr!fOgSeAe3>wN2hFv@QSlmu${v_0?x=Qy2e@QlE!fbSFNikJ(D_&3v{))7xJx z*i}%+^dw$kRDoN`=ULmTw%kUz-by=YS*LqXsu&1gNyeJ?#eI&w(ahx?PzgFkD1|>* z<#qLLkGItsB_;t3-1{APwUgmTZ|fL{6}TlguOwlen4+hI85g`zPv+iDzTwHu8=@i2 z9w)3~J^e>9eJe}vht#vO^l=OvA)f9}PG7F+E=2kWwrFMKyKWyoX&gyv_pr6?TRu@= zY`4^d(YRtx&KuAJ^uC+j`_W&Amq;J)d&BAP&fc=Ydn(&$UkQYacZTLI7eu4#$vZ)< z^BD9oKyTJ-^z|1oK|A|0BYAS@EATj5IH3PJ@eIGrS=epY=$m!U4<Ytk`Jpx0XYd=h z^HlVlS;$2<M>UBfngm=TH+x-L_2B5F48`Q}XxG%cd8Iyr?{Xx<(XY8(G)YM1t$gm- zT~)pREG|P3TqjLi+@%t&M_<R9dSmom4TJx%F?KF<Yr_M6H&xehR(pU=h@GSQV|c?} z1XNFbg^4o>^*pZfz81b#^(6TV+xsnk3Kx5hqe;0E`&hmkT)jY^bgXKpwjR#C=w@pA zTBTlnQN$^XcKzyyhC4KbH><PwvfD`H#=TK!eYP^vxe-RorFca$_f>FD%qJH^w|`aJ zm`yfI{0g61b!{)dYTkEmnZGbmHf!qF!%2>ukmJ?bL+oDvOmBN+TPyp0%jAa~n7sgI z?>-{$HcF7UcTRCY;=J#2pG&@zP4g_1rGwFMTJd9xUApM)6Z<QZIhVKjO!guA-!hY< z>btDm^3uoh)rf&Ug%45<+F#;>d#bN72g`Wx8LiIp%EvML$TIme1fX#;*3_T6PmJyH zrYoE!3_DWOiMi{$r1m)-ewmMrbutYFq#nba*$HheEng{#N1oST@6$H<SQGdkM{^#o zS^y`chdSK|Xc@lT?(ZH+Ady!+B-x{^)17Wl{j*OjVjO;tkG0R(zCurSmVM?I^)WdJ z`_eG-E61uB#<nq+f4(=|OZ7&5z^RmVRGrHvpn3mAa)%~a*A2f4VN&f88R2(i7M=`w z>@GRIlSJ~c$6s@pW7A5AEc!36VSQC~WZ=-{!`H}%S~l!t`7p0vNt}Y%qsOCLq!0Dt z<WT0a@mDh?yF%vT#ro9?d6i>ORdqMU6mjrINNnIB)lcOt%)T;;XZ5PzO>U=5@J<Y- zh0MD!5}gF(s6Hd-;~h_Eb=)^P(vioJWPt#|+=Dwg%Ax-(4#<%rjHb?t?CQsUqk0Kj z>&8;gkVOqw)4$0h8*ln_9GRKp-?tq%*<z<rUsNCFs6{sZ4}TK&ZQFV|CjMGEU1;qr zrYVB*+nj04<MwNAWVvtG%X*;#s0(M{PSNWdFTR=jmp|C7zW;c9pyqu25d4w)btu+z zZ%<eH@9_?p08XK{$nlG=cX9IF>?waZN*nL<HaQ|PWBYlj`|$c9%^xQ(7DM&iL!_vR zb4VK9zozKqM?Yw(4>AFH2mMQ0?Iup9@KqjV@9P~o-tL3QhAWCn?0ZOYbg#Y;=%Agg zR=(Yn!ez=kBNQy%q*I;yTkMG7fZwo%oci{PDd{Yh)eD}O`aO7AlS47Vt3N+?$YKxc z#m<1VXi3+0k<~jT{<od#n!9Y$yykLJkL0v&b<pky_1EgQf<hGf{qFxe;dHbc)KPR# zy?sjSS$(y1k7zWrNlU@f+}u(fu`s`?<${g+ISwu<5BHMONSJAj)%GF)IXFi4*IRp9 z^%eM`S@Gi`oU<hm2gH~9;j2Q@+lLIeBU)ObH=dke&uR9W8OdK94w*gy)R14>6w|h} zM1AUyXme-$j}KxC2lwu?9NazCPwo?*fEDY{`CZndNq*;ro46VK>!%kx^_DvGx5Ewe z$sJatDc+(YJ@(m~tTXP#taL}X)UOYv26Y>G*s>K(@C%FmVk;n(2o1P@RK0Y&IT~v^ zf9utd`l2*<U6x$Ox=TERmLbr(*>HA$tli`qiQBimyc&cRV{wY-2|(5EDZ65<X+tHc zZuOe_t*K2ac2eqR;BaYD5x(<up&Oho=Wj1gO&wM5mhF|e!3WO?Ph^k*92RfmcarBF zQC}W{{qhqwYn9{R(|DtKMRMPUI~E@I8ngSuc6VUoGKtvVc6HXSA&cL~4c`T!Sa#s; zPK;XA_bK7T3n)`Ksvfavla3x-*6H<5t7AhqS9Fp)TtL1o4)J!Ay;jc)|Fuu+DZj&2 z+TqyIPPO^oiJRx>y{6t1e)F*Y=7FbY?lu!`FVD^Gl^@pbOdiOBA$DAz=9fgGC2F!M zRWy4tu=!F6oqp1>f!F^)Yw8c~AD$>0S54hFycJdwsQX!RN?zuUj)RB~WW?g!+6I@c z?gXQ-!hIjd`H;J9P8bZ3)HD7C^91Pk9xXoD0d+4}n3E3bb$n=KqV@tD>KsHD_!MgS z#V|$VUeOMU-g~rh=7g-;;TTp#5x@4FXk2u%A3r4|h=GZ#_uk#|JEPsaG5e|}&P+QR z4@rmI<$AvZv;vnPJbW!cyrtIEYsbFITIRSN&yq;<(b|%foS5(4p#m<(8~*F=G4({7 zPv^x|7WgVPF~13a<FI$#*6yKb2FoJV%oRw~3#c#Sc^P9?mTYV429DSX0(r$27`k&c z{7m>nYQp$`i8|%$3*uhBx-QYZeM>8gYBs5E?XC9$rniDMvk&p6ZYkW&ti(gi7=olx zEITBPM-GUtL0MZ<Pf9X1O+#uqVrWRIcO%NIN8w#h4kwiR%BrW!GBdpF|M@?tE^)Qu z)5t7s^0$eC+tq90L-w;NaL=Ji^@GzSrX9v+BA)29TY!47tOaQ2-RbH|EK~9uJZnXP zklVY_q(-tT^`(do^POIVgL27!tK1%1U7?Nj<wFexVYR=kH92WqG$ZPjp_x==Mg0!S zdoB|C%$N+r-j)o85#FVW$ETsLZ}@~N988@Palnx2^wgEnF=<L>|F!Q(v*i5+gtLSr zgvS_{(naHH*f9olAgOzd*0$7pcq8xsUntm5N4w!<oVtycuaOr`*kYAq2v0yC%-fT< z(FnO0hz4xJkS`|UV?8N``FwlxQ2LB6NhLC=4p-H)5dm5v>fA?j0W|sS>+R_^+il<a z{i*O(t2DkmVJwEOn}<Div+?!Zg<r&j^mlT{<obU+i{o!Uw`O&(G_y&)I=LA`t|_<( zaTzE@{GU%BAdR!Xjw5ShRja#3`)k~<!onjfLbF6qCO!SdI(a09__80x$af#8x3Fg$ z@Af%>)oN(u*d@-^?{`<5ef6|GPH`7o`qH>!pqniG#3@zY7CS}n>H;ma-)3AUJ$0DV z6&KQf{cMwqG~b-{CZf2VF7Z}NPCg}_EnEo?)7LKEq)3&m3naMu{Vc(Cupd@SXa(R+ zSq~;+WY?tX0mjSla(y^gbov)9t&neaX41vAS$2_`tG7qmhRYK5<2ITmoZyJ!;6!I4 zoqcRmL|x!<cXRc3S<j0dD~)#dUqP3E`tovzjw0HJxo>&@B5o`7%@qGj<o3C{^TQ=| zVzuLq;<O$XKz{=iZR1Hd*DhP!WY^(Zt47+bQ+OP+(j*})E8!-qsRvahTGDJU;i3F@ z(K28juM?hOw>OPBSf9#g-zQfs!LZa*cZNLDY~r6X>JCv}9>g_whvtKWV|4r!-EQ<; z_a|*MLsj=V)0ommmfqU<FT}Xj$#5^jv#H7LiXdpApOl4%+PtlwJqyz(>{A+Oy~JF? zq%wZS0eh=W=;-&HLr-VFUF|V<?)d3!lX^n4HkWa8di|YGP7iWwl21YIGxgPo!EwmX zkF@TjiN&`=e}Xx=UxlYQuL;Ddw!`1r?BL&sT5S#@e&=w#;iQF%Az6NDsi(`6+Rxh( z>WXAV4jt%PzTv6*Ill2{+|9@&ORf)Sd31iuD{R_JPATs;SaWS{(eLXyHW@dQlSV(4 z6hiPOTy+VuC+XR}6Y5Kv#WzC!f7A0e^wbM6eM|u1m#zQac@RBKRDD-8CGXfcts*Wk z>Dq|8s}D`{nVbJD+1c%t_)dutY5x*)gd+jN-SJY1G;g7de5j{hw=jyGncm<roe{71 z>^^lDZSlb*9~;TJG!bRC!Ly}^K|~hs%V7~`<0&xy_HW}EFmSLCKMj5hm7VI0Y$g(? zGl>KmDl@OtEA%y>X#3<*kFM0axd1wvqCS%_W3)3y{WS8Cd8g`vQs{VBh_+c(k4&g~ z!`J??h+FQfsz8R&p2%%b586rKJXG3gasX~^IfPaWZl81l=%-%(RN|%WW7Sh7Rf`PS zgb+*<Jpd8>LyDYEi<78tAnt~5wE8BOBhBE?IvMq^TDcczd-<sP>J}ZTa#W%&Vr!fs zUsXSSeE2VR=@rg?GmP}CpKns0VtgXn;=}Odzg~aIU_A~YZTXVHeWqsa8%p(z&A(p; zb5gG!Lzf99Q9B16MkZNvyHm_BkT_va)D%(^+NhqANqVi;6U@n_Iwy{*mvets#cp|V z_GO(&;@cI4d`~X!Uhx*_MnB<tSF>g9M6cB$+l-g$&%!vAx{vIZ*_;fJV6m~U$T>k= z?3VSrJ3G>2Ra5WRdL^9rFUIG@5f!{(nC2Po^m8#>3{QMq8Mi^g^?9}DB@%M@Y?i6y z>!A-1)g~MQw|)_x`xSLM;&wv_PrVP8B_^%ro9mdiee51_Pqv89Z`@zo2U^)GL>nC! zY{o@LaQ$XZ2}3H}Kl@Vr!s$>iN~~N264l|GAae0j-ZtV!Nu@7ZiWa<bOGgIA_k=F% zeUR^qQx83I0H_C{ig^im&-KhyLnWg%SL{5|TST{h)`LYyB->%%@<K;lg>`f=Vd?La zLo_4DwQq@et6O@n*TVPKezJoEIzA8?@17G|eR4-64Tfgw)YP$r{vRrmiRjiF-;zU- zOeXAyGRx0Qx9a4Rt#%v6%kCR-urw{tGdL2?shaxI(3r7o)Z>l7cg#qg9{LT50>3{Y z;nKvaxQuR-(9%s#%-v(=fqGVGPRHU0CnD#yk?N$1o(N<YwFnY0BJD2y0sPm*m5`SE zF11O)(Fv(HdRmCE#m6TlYDD8l)wktCLv*1G=m$$yESQOSHV3jrHcwZneHq0pVKb>m zGdYC$!#ra3IBN7_0>MW%8N1QcKRwr*G?(*&1S^*<*hh5{h<)nw5?L8K$E}fC?G|;V zt)fFZo<R9=)~|NZ4Dq%6E6++6#wvPWT>m#V(R$dK>J~AovBFP1T&}ZdMBDM0dq<!? z4ev-e|L&W#7z}jZ|Igl;z-c+PfBdP4l9aNQ7$IdH+lx0cb`k~&Nv0GbOiIc+l(i_? zvJZ)rW!_|qh|0bUS+b9PXY6bG&vd@me|j!+=6=rH&;302GjsZU-oDOt|E}fy&bgnN zlHT1<J!R?dHdeh9`!D^&vo-%V<mu|_)xT_)t6cNjd5N{Ee;?|IfBg}mBNLNr`5n`L zz2=F6|NjbG_3Ml)YrYq){?25aevzt2So(4HTFqzuvL6uDNxf>m=~?>0D8CX~`pcK^ zt3K3apNYOzf6A%w<l!T#elcGCU!o<ZB>(<+b+NB%K3UY=Fc-C!E8i~pt5nsQRQ(4S z$(5@<;d><BouU7P{$aIkmlq=WU-VY}d)68QLVU6N|8JeTpSJYZW?OGHYMcDTDOJB1 zPrkk(e))PsZJVmLcIGl~z5F|%9*Noie;p2~`ZCzL`twHa+_JwLIXuy~=Fgs4kK&rD zYrD+v9WDEH?$E056_@>(sQwe0c~$>wn%I2nmWe}8OeBUKyYvqq?@$%wkHS^`Q=&=r zPgOrsrBT=XoNAuvYBJ3~Njz0%I^VUQt6uNhHNUaxy<f>EuKm#KWOeX+?y7I-{apQU z)#sXjVdo8-ul=1;^_8vq$29mdd<&YVH9tRclKJOX;CnD}vWc$%w}U<4a9C5x{FBt1 zN1YGgXHe?3w&ZI+T-SP@u=(Sd^A>nFEQfEx6^c#g)^Ind=aG6>kasV9K-GJnwa$0l zkJg8+r}O`2pSun-PxgmJQ0w(Pdad>C&3{~z*a;TE-C-YiG}QSWh<A@zzqMoiT-Env zp9jLKzXE^hk7B6(ch&PBQzb@I?@Tz(Qa@Ar)6_gAmU*TVzZcGgb1eG##J`1=@MqY3 zxN)={)c!t)?(2y4A3N61RsEmrvk88$1@kQayXw1AXA8IkyxvlOC*no$On6b6^gXF_ zFzf@RpT2Le@%%0LF8my3TCcx;=(V0lKiBK9`akhu32ZjPRBR1({iyYNe?e<KpVu2l z#0T$BvLE7$(EC%jKjM?n)i22tW;)-spVu1)<h(TF=1<u9ay>t8=i%qct@kHx=N0yS z)cfhp_pwL9A~?+Q{jKh=*SfxbuGhJ)*Za|H*Zt{yz0P($*Zy8_9MI<|YwgcHymz~v zYM%6l=RvK16#ZlHNw`*u`J#W5ydNz211$ZU5pM<CK<TgN?ZorWa6>5j&6Yk-&C`vw zo=48jMz1#x<f=bcbMCjmsc^dGK18jz`6zLJ-{N)O=5tS8gyrx<%l+v!(#(G{90#v~ z`g~pWhf`-D91NwOuKyU%=fmgVrd5C7thOJn`j@Ep16-N9Ygy{M>ffR6C-8ICPwzqA zBOATmIFPIU^x$5NhSTA*miy+a-`%nP-sn$&GS35+d0h2}P^Ui}0HvS4&lmChQg}JM z8fIGm0ezc~GM(GPji8?AOY}d&UsS%<+wQT%z1}z=erS4s-2BPs-gbvO!`&_SIcmK= zPrYtv=Q|XiC&MXlw#EO`iI0I7LdkDv{^;}9YrWt3`0*{Qgg?XPqfJITsPmsg_jSbj zj~(mhs{T***#y7Wf_WDIUnc$<d=q|T(f>{SywlA|PJpwaKHvK4J5a9&91W%4R7<~h z#Os^y+AnJTZtUk6wg2la`*+nBQs;2k4@y6Mp6l>j?_2JJ)^|p~5!_hipT#=v`5Q8) z%v-`*?{_}&XW@%*QI_<HGt7i7VLNy#)bp=F{J*dd9GE8k2GrRM=0oYH=h0t(^xEr< z1KJl^=ej?#4;x+gXR9OeY}a$`@Abw3IX_MBkN2nA0l63cKKT2v?0t}XVWaDPvDJ}y zw(Gg}_j==ioS&xmr*40=UwZB8U$*mI=goD!_FJ!A_owsq+O?k78wa$HvTkht$i8iK z^}|+2;;!{_T`&7i7hU~GS6`_UxBhSN`(b~;#F=Kou5e>`6dVArhk8HnQ|D(@Z+-Mq zudk|ibwIt(sMi!-3srAROTPGCU+VqUw~pk6t*7(vV&4azZJzXpBVoGqv*^?6EK{*P z)b&NT82#4hy2DDimSw)j$di20x6G2hCG+Zi>wVpZPWvHo*@x^~&MRH|ua&R=vG^tP zOhbPc%v8R-2lb`)tG;z4FKj)Xe*wPV3CrLj_%>YS9Fy4=?hAFj%h2BjrQSkSucfND zXF$EH$)5=yR`ot)t>+n5Vj`cypWu4unz;TsuKFh(=O2mw44CfxwJiS0J+)E$ZPQ6S zYQ6Lky7rSiVW#t4`+2=_K+a1uYJVDfzo`9-y1qUiy^gwn)b+#eN9PBvUH21IPd^V^ z-!(sKz20BY+I60wdiuF*{iyYso=^7+TD$H)sGfeF?)qWth0Tw8f4aV2r+fae^<C$Q zn?CIRvz;F|Km9z$0evrQ>!|(GeWUJ|>-Du?dfm|W=ei&5N6<R%^<C$SS|8-6e(pMt z&JS9<){k1R=go9K-CwU==h68=>vY!-TQ6+B-fz0=>H2ydbwAhoT7T%dCNc;f2QP(_ z;3M!U_yg4S!sbiAYp8!6oNDP8G`F75Ro{dHHtPB|oy6m=zy3TkVJW-~-V5VCzxZrp z)bs1UuKnVcujkS0u=~^X^xCz4-1WW2nh6KOGhhkS^SkPYtGW|dPlMmX_UG$PW^K#A zDoy#iYfwL}U!dm5XCHf5_T#F5&ar+GeLG%cCfy7UzC=%M)}sIJ!g%OMGyjJv&LjH8 z<lS_!*~br1?|Ov`Oyn+jAi5LbX85$D#jlPr$seocKRU(vk0oy?90t#U+ArxNen}tk zOY23qNS)tl+{0N=d~b!%?cmPvV2l4!|8eG>NFV8!Yx&nY&VQ3dzpuqFSN#m?KMtQ% z{q%XuIXuaEoPho$sP*rl`w)Ht+gkKn5Z?ukffrfyqU*`?(=B<ISn>}iF8h$r&+gn? zy`QM{(s!Wc{n7K-^gmkWPnZ4$$NIUV7vEOk^K~sKpI_R4o4z}FS}&iAGx2XN-s3#W z`z)Wk*HZ5{*xaHoCO!#X2S2drC4Rs-GwEUQM5yN%eI@mNhwU1u-nP%x*l!28F6;*P zfI)udy1tlwPJ-9L58%J<5Ag%WbKl^J(59~>?|0a)f$DAhT#fy9fa}6;a1VGGwE3Cq z`eODs30?=^hx-2Pa;b^z2M>aW!c6Pu)3+SH4&S!S6ScmAzLoH2_?u-OuQxX)UH*LQ z=)XRvzsO(zGBekva2KfWci8;Jj{Tz6H)Wrx?qC1@o?dIe^mDzAS|7Gw*nGXeLj1l6 zwwq`ad&6fgH|sZHs`(p`pDq1pwV#dw^Q5ZZ%+a4I%<(?_2>u4OKX+$I|D)qPuKI5r z>!({koBq!$e{KG!su$f;)RptK%`fM^82u#f)039_x!nXa;n7gu%YhdCf6?uiqW&;+ z{onv7{j@)>dZ}|9b!F~}micF)djY-$zk+(6`s(L9){k2MgyTG^>h;%)ptbhb>y0Dg zgZC%d5Aj9l{YkGs;;XQs`Mbj;v!ff}h%3$dS*Z8hBTf2qE%p0a>f7{#(4V5_Kh09# zRevXSzlY7K+XKD~->~$1i@cBE`YK=hD}4rDVV;};&xX=>H%mXsUol1fO6c;S?x*K- z)!X)Q2mK1!$06`t_?cyYx}MJ0^On))cQ}x`$6D%({@E1uTU=#24uQkq1o#Ym9_sma zAfD~~qnShIzl3$F^GB6$^UKyRUHXHRA7fbC>Zhs~oy;$F#cy4|AAP-EJ7d=3i@ZPL zqr87QtG@bUI0vbJspUS%97B07b6n0^J_lM~ttT^U`98x&on_NW-0SQ1)%%lM{>Z&f zm9FQTYF*L!`suwt;;S&MznRW=?H9FPd=xgceo^ly*Xzr<3v+!xetzSCoTsMu$NN+5 zfZU5*zYnqxq3eDmPnhZaO!t$03L9I0*Zq3EaX{{iruQee{PE|Pd}FmAdY!DU`MRlf zvTkg8*>|dR^(WQ3qVx5Q1LB8fSbuUY-*w)o^<mG$b-qmZbDhuYjRX3eWbOU&{!}~A zSnq@ETj=^eNS-j$`L6xqrWfCYahosfJYD$r>?=+-l{&y@psp|agUB0!?t%dQ&JpR0 zsCzU#=o&NeAyCgh7~M&*8*^`EnO}6H(2H)r9MP9B_x*4lzI+Dd-2P|T&&470=a9bu z9zow@Ea&5@m%1-eU+SJ{sW19xl>Ru2{v&ifc|IDBf$QR%+@ph74}^oDyeIlT#<hOG z6z3nIe38!&@kQPf@kQ@nK38pY)!XVw+_j#oUi#SR>lp`Z{shI-?Vs+K?)t9vyxusV z&qdaa%^%sf&~^WkCv?q^n_l)26<zlm)f`gS&tn`AKQvwaan)zKpX+>HZyeC)B<r~O zBXbE|=aW2Prt@{bKlyb+-|NhiF>ns-e!Yp0gSPx@u1(Irfc#$M^$W-^B0or<K-Uy* z2lvmB{1$5N16j-dwZE=<sbf12U0?LWm_yEA&M&O~P3nFI<v#Va+=sa7W$w1zXSv5i zE%Vn`pKz=nm3}AY*cI*xdqaI6<a6UBp6kzz%kiny;@3;$$-M~D%jagQ)bpmACpy=B zSH1KR=32h%yt%HIbF$HOf4WX%%Xi&xuIqFCyj}foZ2NWfCvN(%=N0vS;yz#0`;S}w zu;-EO{J8lU^*q`3J8b``{qgmU1Nxj~?fvooR6F4BL*4hFzWzv_&~&N!S>ma(CNr9O zef_$9_5OH&svVH`)!&D@?}PYcqpN?mIuegtJ=b|$^|EiF&rfzhe6cZEUGrXhy>`Z| zZNAvzx{6I_i@WB#>UCe&e6KeSXdi8B?^oS^d4Ie=)egw}<L`sN5B@&Xyan=J*jS^i z``$=?ruCcOU^<R~f5Y`}H1R#*{!q^+`CF0qpA6U2^T<A44%kO;%YH_a_jpY6^?v2v zq{>X^yY};X<ACivy+6_Vb1t6?Tis;(91hQd+JDi1O5O<(=^t^dpX>VT9QPZQ{y&^& zcepd`3H5!5T5tPYkhq>l;x>A{alredZ$jO^h+jHO;x>AH-M)H%((8}Dhq>-=*!_gf zkJ`Vm^M%cidVjvYaX_DwZ5_2=x^L9|T<eFOFWdR9`}KO`fIc@_dw;w?)eiXkQ1?9$ ze}ZVL)chQz4|-lxDLeDI_V@a_&&m7a{i$|9-g|!^{C)8Eq2?`+_rk^+W!?8i@?G_k zCv?sC`nu00ZvMzQ3!|P-`Us=$=j$5>#BWXSkN2nA0l63cKKT3K??cU7An%2ZHOjj0 zjpTcM-9CALa?2mN*TT4+pUfq6olo+FuK8YX91#CBy+7WcY6s+A`1|1RL!9q}+*6_J zeU&_+YrfYT2gE<k#_rDo{v7r5^5>~<Hjb<SwLhYJ6}{+IMt}1yCSx|#`I7eq`R|d} zvD7GA-D=nw#y$T_$N9gr=sQ^U>#F~U`YYk*Dp35@e#*IZB5zN)50rD9XF1Qd=yEk* z=H5c>dk$;um-uoO&u7B>v!w4&-$C$LI1*k8uYh_#Hl6HG>m{!DZS(7C`o0BsEj1N; zLS0{U@1WliozClJ$sa<zBlmRyd=vf%m$STYlK(1oqS8-ute@-pa~<~^m3{}#e}Bup zNT?szb5DMN!=@O)weWY?<~Ehc(w09y!}(t@f6%-)qpPnzfe$u6ex-g(_Wz#pLA&^; zqrN@$_JudXc~IB4>F+>48_tPoemCaY0`3U){-;>x-$CVxPWG?;lK5TZi7#_4^_x&2 zRqB4J=83Mc=Zg<Ey84srdYcat&-ML9J-_&5W7PfQR$u$zI$zxK(>+hz>bagzuIt14 zpX>W~onQN<*RJ)v-Z-Frly%hpNFSkVKgknjI^VUQt6ugcbj^3wOCO=nPj*0ju`yX) z^Y1-vdL7Sney00nd%t1(yZRM({nk^>gge4r;Qmn0AGQAV+fB#!;m7bNsOO1VukTCH zTF)1x*Ux=^vIE*5y-rpKf8Iu|kNbSC`}g}Xj%gocooPR%uQ1p8yUrW6UVId~_LDrJ zYkt&vnM>%}Px6GB&UfwS^~M1?FU`35qvz9W*LiimUdO#&)bmDNKW_fUZJx0HyY44$ z`o_NhxSfZe$2g$xrL4U_-k)j*{C%kV9(aGeKg+%+{yzBo;O~RE1Izv_?}d%aYHRaP z=Xt$xK>H$V?@w;|Bj;wL>v`JhNZi+}`+kT|HoE#3H@$6N5_g?f@@#aim+N}%L$2?~ z&u<*i=PK*C`6F`)UFVZLVW#t4`+2=_K+a3k`;%UOw7+`o>bK8NJ|9>A;-=5`dB)8T zKaX)h-wRncHh*N_Lf8FEo-o()UFY?B<A9vErmH_XU$4W~^ZCgRXn*xOSzYt*9kou@ zu6oH6`ut=E#1|Wr)#*PUU*9;8F8^(HB;MHkmVMjk>W8l5^OGIW{^)hGI{lv~neONJ zlk9-@U$2wZ!RH?~Khyof&YSIgSHHsQ^Y1hjww_@)0NxE>fbT%v?>O>T<+<b!XMGx! zdOH6a@++pBC!)WMyz5~pwB^sIj^tmQW__7s{kZ5CGWP)d6<@?(?WgF!AumWTb>;km z&P(*CGf$9S?&bEJ=brE=ct4yE^?vmGtk+&|9MHbV+WX`Esdm8Mhq~{9_s9FQ?0Zt* z`yhEj<7&;%5>J&indYBT%@bW?%Xi&x)OtAwVbuLx>&sliT+4Tz*XxY~a^9NWAMa1K z19C6?een0e--nvFK;8=*Ym{~08_CbKe!06$$4+o_xC_+txay^DH&u6UOZ_8>54+oR z9s?)9=inmv5A1%A(GQ0IgL?k^sNa`7(O(>(Ulsjn=+dqKjJZ;+pX>S;9QPZQ{zA@G z?w7t#<2mo!EcYXB`ew}81<L%BE%UqT+fZjMxHgo2`hC;y@fG+T^d9%N%p3Q5BiWyP zZcSGEeUG)=n*#Q^uVuee&_4pdR{7fR`s(j<tRJ<$%yFJn^&jH%^7k6&F8!b3EU5hy z{Ws+O0h^Go^-}j(>YWF5pKWLAOtWr7-L2rO@N+10zHFIS@;9$%{+i^~H-7__A2hG4 zzN=&X-sn$&;@hVd|Dx6pRP(&a9JYB@Dl_+Df4DC9#&&<A*0*<@NA%mN`8ToLe^>o_ z)ZG|v2Bn{V%Z}jrI4HjVW4RBaKQBf75Ok^PM?|bY)3JU#eCP=CU_XmLn-kv-c87ad z^q(_NCHxuw1NC{yuZwJqTCe-M_RIBr*Zq3EaX_EDtX=()JR2KYJ=gtsy>TF2_rujs z-Ph+QJD~juyH2iN^ZW9)y1A~m?MvdW`;$Byvt7@%zt<ZF(siDV%}?!HW7~h+_8ay* z!sdHFj04(7S;x(vsOOP=3#0BAb$!`~(6yiB34MOD1LBK~$?EKX|7x34;!)2leS}f> z^Yx7b;<u*vr*413`jzYX{(jVbKV1FM_d&0Hy}JF@e(80#{d4UfwO;!Zw9fWCQTNaF z`q@6eT=y^P`Stlk-Osgt*!g_Eaa?@x{wF&izNE_J?BHJ?>$;iFckSo(#sPh9viAOX zf2tku_o424;QfilAMrI+nkj024$7-hMl-*!U$?Ju^GDy8xXqXA^Jstd+I4?AU#}Zl zJ=gtsy>UR_3t4-A((8}-YNPi%y?$#yNATaVjDw5e2KQ;DS&w$qOWkkD+lacoE%k3k zm#Y4Di+(3d{h2Y-Kgc|9L-A*8%lxkT`P6+8maBgHlx^>!Egm*s*LAHIwLa{8Ve_Nj zU)<`4^($<C-2909Jh$>WRd~Od^ayy)1A20^7JZjlX8j?|SNZ3%-kv%=;Zg9UfclRz z*Rj+&8S1HIo>cYosM|@+zmb|>`nt|9^<Siq`11w*^!%=R@%>fh`<~3d2EJ|!4}yoo zVbFHI`P97#>U=%_HRxm>-9PU78<_ubDD$t6PkMe={hidE3GY|^bbbB#r`N7}ov+uf z^`h46`Sd#K{;u^K`g~#cm+gGl^Nd=r{m^UI{yJZ;!`5@nchzTm-fZ`G^($`rT=Os6 z^M>v3dj7hfUdOGT>pZUdbnidc`n%2>cl{K;Prn_00l$W4K4^Au4%GW8M^^#6qU#G^ zddOsa3*(-@x#Rp>TlDW(_Uo$Oh59|={;Hq$b0wZ{0560S;nnbFsPiSSOF-T&mi*(1 z%e^@tA0}G-h+6*w^9)sU%(BcQ`t^B!D@?b3F>|F_KiBo2I_@_rz5e<YwASxOkX}D; zZ27MH&2@d)^Un4C`}vIn`X0zS?*24;*i6_Q7Qo%$8neyw4p8qWU*$c;dNCaOh{?DF z#y$UK$N68g=to)h>#F~d`rpAHR6p%!f1VG5$HL2@)|U}~5^l;lZ)rJi(alHS1)a{@ z+LFIKak*D{__Vpjuc-9{n5Vg#;~>jCqJNaU0(9xtPjalE>-y6j_ZyX7KDSe)exFj! zOI7Du-&L>YaLxC6<AC;2*504G{Slvpu6{|LFxT>3=Z%|Qd>6)TK0l9fK+Z?AvHSBC z-@je@sBxn89K)@k_DA%4pwEj)-_fytuIrmQ?l&s^bmsU4Zp--|V!00w#7zGP^SrO- z-^DV&tNt14z5-uU{q*~yKX3Hf>x~227g=k6rgDxy!B&qM#rja|XT?na5c7PX=I>yc z-&Ow%bzgz6tA5&_Q|UVoz6*b{%riD-`iq$7UMTZ_WtrbqKbbnWz^PFBX+P!O+UWJh z0q>8#33dA-e(5ZU+vxRm`|ADi{!}}VuJ=dR@%O9l`xVx&u=%d%6SiO6^25&K>Yvxw z{XWFapG@D6Z1>as^*V0n<LAll`{eIO@(t8}=ykH%{(YC^d3|>8x2ykhZZ^8sbJgp< zVe`Y*bM5c-#sTfStmEd7%#|u#=ht;z^S$0Upna5e-29Qbgs$^Rp3vtfJ0QNK%H-_e z?^jZ-E4r}tUGu%(I3WH9(bcb@dalpI_HS(YuKSHzug^Q`e!jkOK>IH1sQr;XHoEq= z)seWb7w_|ybE+?0&(~G2=gM}zo+sVwu=`8*Ji1=o=hO41d+qn1>_EEx_4SOu-iOqD zNWP8f|Mjmwht$r&`=oE8_pRCie=ow_1Cw3zv-dNcpXv6m=49eESGxC^YCZ2q!@39l zJpFlAJCN%8?{%5IFQ!|~&*}ERrgAj<%Jup|en-8(sQbIlpX++<r|W*wogZ~QU0<)m z?qAo_YhT|upnZ{b)c#1HOwsSB?(@#nImD$;L%R<_zDB*@sOtyq&-J;V*ErznTdMl7 z{$@L0?=$Q?Ve7f}kDEU1{(ZhVQSrg`d?nAuY}a$`@Abw3+j;7^t6yRBUHj#_Ui+oj zuKUyZdL6c2W6w{wpHbJ-_2ae<d!ORApP+df`hMfSzf8}U>3%`?FX*|S*EkU5Q+=Pi z`s=FKbLDz|y7$xA>bahOuItl%zPav4+~(Kkqt~wU>U_O!Z1tkvf2Ql}esNo;`+mi3 ze?jv!^!>+uf0>>y)BS?(U(j<uuW=yAr}{p3^*7h`K|Z<eFWvQA`+L1{z;+Ie%^&SU zW7~h!`_=yHb=3WRedB=kUDl1wAKACib^nql%yhnMKUcl%%f_(vT=S#W>wQMu&(}8& zXy0Y+{qg=(JK*m_-S@!z6OBLOtI%|*`B~zrvL-XNd39aae6O$D=cxT@Xy+GpKVkD- z&ns-du=#%8y5B$VZ?yiT+uuzeH}h@_cZY>=I4p<y{!4y7&-a3oKa%xzDdwLYpx=3} zncx^$3~z)9^}|(vDs|3*<Dsp7-1Pc>=(V!v|Gy8{I$3M|Cr_A2t0xWDhU>sH=b8A~ z@EQ0VwAK5Ax?$_B&Kw<JKllJ_#T=vHW$+GoH!OpCUR(Xa)YtlxiQfv_QFn8=Jv`Xb z?~IW7=Vm!y_O1O7@}VDo90iZI_>=4PuVi1>z@Yml?^$oobsl^VehQaBc@M`@U*5x4 zEPi$&FV*_`zDxeb)Y%+v1+`w{_3gJ!$a%x&SKwpc`DSM$;F(bG_b2qLr>K{@N1`8U z$$Nf*=~VEP;l8jBybS7jbp58(Ssu=TbD_?+&2t`ePKDpYJnBq`LGuOG|4h~2kh)vI z^WlwfDwO`N`$<)Q4s&UJy5~)IJvp!Un7;tO&V+Ja{kTu3z)_a_CG}oZ^@fJ5H=BBM z;1jTrx_zPce*wB@;B!#s8${l*@HklCc^i5^@lEcF_$2p5`|qlkx^mB@uDsW_duaQ- zi+jBvxsU(AySaZ4L;d-#{mpj%Uuymb)ckthsP%8qe*-?B^w&i_PaAZr#za4ZIcC8J z;Ulp8X|sccQ12((`Fk^0FL*HQYnj)kJJO<;U#Hrr{jljI-q7^F;M?zT|L4sP4}^NZ zuKJUnF%^cvG4KMY>)%a$CVT+ShEKycVBGTmVy@QDn#nrA&ERox7#ss{g!jT{q26CB z;!)L4_q^$@w;%gI1pWfsJZGHh26u<rzg*9keak(v?R!7V{<EEbG;^H*e}t|0yy*b9 zv3&mIdcN%YboTv4iayBavcAu8uXhILIPL{A`LA%*7xhle`fT)%Lec+Cp3V~ej1=`# z(A^HF!Cc7~UluU8_+s-jYW*|JQ3?Nny)5S?`nQyRtu*O7QfD351#WJsZ_{mQ(O*ma zHuyD^d#dke)Oz{8w7%5y*0+x2xz>wXFLR|z*LhN{E4p;o&vrf6{$6h!ko%zN>W|M) z_S4lruTS<b?0sr%eunj{vFFF_zJxuGxa}uy^Mv&`Y<}GQ$n|-`o=3Lxz5m7mIR{ri zBv0s?A2+@1L+Co6<OwsK@7gbJdht!@I-leTGoA0+FKWH`Aav~~c|xC`?11=UW3syD zziZ4Dy`Ix`Ke?Xoy5G3zbKU>2^T+Kx{5-}1eXgmlUH#K_GoA0+&+Cl?`rKsg{qg=( zJK*m_-S@!z<NaCoJ*n?~kUXJrwdQAur^=d4^G~VfiOx0O>+AN}`;%RN<X+d8uIE?Z zK9ZMf{ld<h>HJLhlXDejx__qo$v%a-*57qruQv|Jd271*qw`(YzF)NG5!PSVd{@1` zFS(YVYx8E?Z&$y(-Z-GoP1dgdNS@F&-|N$R9^TLF`YG>$(4R+k&%^s)xBqfag|2={ zo-ot-uKjXdFFp$!+J0nT!d%~9)boo^!l?T-w)*0$u(9nw?)x3Uf9F039t%%|tG;Y@ zuo=|*5#5(BnJ2$P$=jB^K9>9h`ugUtKz=JY7rqFk|IU{FXA>VI&&$m|X2ME1^%WEE z@v7mW@C<kfoB?M;qptaRH|q6*+flaw)+o(CMXevh9GAc`%yEfj9?@T<^cPw5E1}yA z4uxmKC2&3Ri{L3R$Zzde*nYWMZ$0Jj2<7i;%HJWZZTn4ky>-<*?E?Czs&~B~2P&WT zP`+qC;-)`B&3{0^{F%}hF_+BK+j71#PpbNX)D`xju27%Xc=Yo5Js!P$e#c#ZotppZ zfcZ0}znQsYp6e~=EAynPpGsZfjnozD^D5)(^eianI?FPTt9}l3UxIU}`=X_O)cVi) zKH_WGY@u<aIn@4iB%TKkfJ5Mqu*qvW)2!wDbQ^V+O(*fF_0mV^+E4O?na+3Z7dO55 zCXCyBxjv8hYNPA^be&wwcb(VkjRX4JW!>2Pk$nqY_b+)u*ZipUGM6ywevPfZ_-do8 zAG%Ji<-5-7^~M2x?y_#|{v5=wO9sK~;R~?zb>q-XsQnWCtQ7Tcpxc#td&48)XefPW zvwj@v{uR{gVabn5KiM+Rn#4Q8PH;VoUVI-G;LDH<<;ywP`pKMEGVfc=RcV>;OmyeN zOQ7WI^I7=~6B+QP;c)mP)cSVlH-ekN9ii5Lu*gIvylXfa-U7dcN4=*r%{pxUpCSA2 z@RpgQ7=HS;S<igOa0K&T2u-x+=R9;9!mZ(UutsVA>3iz`2oFTp8{Q0WjVS+q>gs*T z`RRGzNB=oo0#~&7p?zGAbMJ0B|GV+M0;XF(hq|xA_f$W<Uzy`0bf3ZR;D0%{E8q<H zAbcJ!f|;)0gTA}Lz2Lr<d2G6aE&9WW_lE=FF&4c|cf3U}@nW8fzyGu7Uwq#<{0+RW z!mOu3v#R;oRWEhFqrTLgZmBQd2iaINiTNj+PU2o)w@=<5?@zS@{(Y(Y9yC;chJR@G zeGa?~KK!wX>z}p$Ui8h-uLq;bpGUtpV9Srpgdf8_0{ZLxw?pQ;_RF?@IQu;v&Vr9X zecrF*=UZ^+PmE%BsP#<<*yyU)buyjr+Ry8a1Nz)#?fvooR68K|A&9Q`C8%E5=dSZK zHhoxsgYsSd45}CQx$8WxdOcs*d|fZ>+I61Brg!x>YJc=RuKjd=&^p)ZyUrW6KFDAF z+;twEAGD6TzV4syey;VR)`#7%>wLPOUdO$jo>#BaJ%6U_hwT^j{=?3v^Yz+wepkKj z7qoV*A2+?;pX+=&KWH7d`mXcDO&{cU(DS(M$IoLNu$^13`=j?2c0XnOKJ(M?v`<aN zo1m_rAl?$ThO5C(V2jWGm1zPzx8?sU%Td2J`i<ZwFdyprQS0}k@8M8<U0|7~Kk*_c zx(bVa5b+bB=;R#qexufp;M`w=r+#iGm<8X0e?vWAP`*unDgCCx=`gJRN>%qh*0%lW zezyF1)DeHKv-lB|@7ho6uVIes;RA3s)Oyj~q;zvEdhzK5_NVW`Kg0)qp*xxNC)5qf zU!MGya22>CwAEjU{<iv(zb|$4lpB!0gJpkOUx033cmV7TGp!f@ZT{(b;-)|5D>LC4 zaNDoVdI8k)+w_kH=ucGjcTAIB=Dw2p|9oR6Zu704Jb7PxqdOFigug<mqpQ5k+?&NT zU(dS&bGC%7U>m6Qh4?lAUIs6>_*qPR6#VaZrs8w(eb}*5cQR{NeNV^w2cjRU=IQr+ z?em<5?rJyy-MbcjIs1MKz7Iczzrnv@SA5vY;>YXgbiEIW>#1G!GRG3?HDRC2LtQ`d zgNfwBf*;NLRCpo08m5|mV3zgksr~F7Fi)!bzSK$8pKY0=H<Y}yEc5h?nSOuAd7{=& zVxAA+-*7wpycXVT@%PP;`L6w<);D3F8>szHwd~(j-<mpWzz$IQ>Cc0Y@%LwSF7mmO zE&Ug2o*gaz$o#45_3t+Xt@ZwMO|R#5-A~y3u>Ev@y>_kd^~M41qpaiRkIW@>olo+F zuK8YX91#D)()(GrpPBaON4~D^{FCXtFT4O=4)29}zU_$DH{Z2i)cQj9GaSnPZ?x>+ zRevOPj)BKP>8Je-df&X>IAHV1`{Vtoc0le&*!!^MFQ&r5@O}6_)b%r^-`{bbRP_U> z`<B{g|6lb^&06$Bl>S%NI?GjmlbWYJa}-$SndzuMfjT4LRll2w%b=dW4Bc}u?>D2^ z5oSxjK+UsRz&x({M^yby0_vx#e}lU3!Ck0Z1mzrNTh1eDeILhpqSp6yoF{7iV&-Ye z`796f;N$QGsNWA)eP`-)gS)^(E%gTzzW}}rKe6bi{$VDpgv0+b>#<PJ|G${&A7GyM z)cogK=6BUUMctR-Le)?EGwDwgX-faA;Z(~!@^#xrUEijYctg`a_qW;635yLE!jGWd zujt<-?`^m~`i)?!^=$e7rB2X1<Ivp&AAv7IJ-_HnQ`A?YyZRqf=^i)->iU17Z_e{p zFx7m~4<Rq8-wI321na~9!d_6%C;GKh)L)A3A-DvtYWa>hQ~KK-=Sfw+4g0zfJ_-jk zsr?hcRWDU+)aPZ>Nj$86SW{DJ94u*W*4IH@-&HSlZ)lcWch(AK{V6<SMYGoZZe*^B z^~}GW{37xnW?#C0k)^-Peb;hkzNeVC0_u4;K{qu;eIdHDBGSv;&r@IaE&I^($5p?; zasH_E9hc`G!+YS5Q2XhsKax5ZsQNEh>SsznlKv%@`4$AsSKoY{Cw**wT*n-DLOGWW zET3of)lXIR7hCo(^>0!7KhmTxU|%P|$$XC8ZTUPaj9C9a`aTC2!nZ8*$ftg))bCeN zp4S@(Y(C|>KYCxT`^oiu*ZoGV*M91?Yk!@u*J10q=6k(yK%axGy+7&oM|>5!`YU<D zOy|4yi<@42voUV-#%&($TioXJ^B4#8Imz1l<Nc|2z~6_u?}7Kn`?KtO;_rjM5B@%w zJFx7}@?O}uthP4)bY8CO!|o^B`MK`DpWis3?~$y%Ki;2e2jY4kWG<oWeU&_6rt@9< zdA)H!&P&t#<Nc|2K<<UV5B@&*`%v>1$a`U9jk4~0Bl&UD%UnV~U$O(@i;c<Zn$OW} z>2=?@&FAMa4(M}|wfD#SQ|*Ai4|U%I?@w;}Bj+YGyQukD;;FJGGc`YSUDtfCuiIzu zkN2nA0eR2-een0e--nvFK;8=*Ym{~08_D<jx_$Egcz>!L@b63A_rUw({aN-s@%O>s z2Y(;T9a#2fc`s~SR$H5YI<K+m_5StR)eoJo*RJ(k^}3&4$E}|0Jg)k5??2c2yUy$N z#sPhAY-{gV-F`*wkL_F}?%H4SgpDoV@7FjW=dbDNkJr2T`TWYp@fNKO_l7;;A@ESB z{oRdtP~I8n9)a&#>U}}H*(zq9LO2rY{-Xbfyg}%OS@fdQ^$$^bwtkY|MCnIZ`bnRi zczzaa-Nx*%7rY!UgzrPWU#Ztp)f*eoKUMw3)VT!?V~%l_c_v%*qb>Sb==J`GTJ-bK zKLf?D-WI)awdVKx^jiDbrL9ps1ADG&)_tK(KR!kMrsy_@N5j)|B!62q_gSoE|Jol{ zz0|ppx;Mi+p|0<$*XJL!*8RNRI3hlHf0F$WUxeNt?@zS@4dp(_K7_9KTk?cHKiL8C zB~>P8*W9zH@?HDox?cO3>-)*|`Tcn$pP=?buanimpAW8j-7np1KaX+1=4)7gT=TuY z?(@*+<o&AKFIRuOzsZhiKlD0T9sKzpHs7_M*Bb}4@3Qv()a{S>lqy~Q)OB+$-*w)o z^<n*VoiEe<T<7z8<A6RVS;x&EnXA5Z-A_=TxYcu=CvJM}chvJ`x?j}$ajhTs{p<Pk zI@9~jc7NCXdcAQ#pPQ_`Ki;2e2mF1g`yP0Iyg$pnCz-kr(nn}cq2_0a+gPJC|76oi zJZio45r*ye0)H;<4LH1=sXP|y`f<~L$=pkz%zeLQe(}vly<eM7;;wqh6XsgJ>%3lX z9FX(Y^!|8%svVGf;qOCk-3K{0p+CR$o}c(CY;69@zJ;#)mpq|se$;xIOX%89@`Rbr zckSo(#sN7m&0P0K?<dpisQt_IeuDZ%z297~ul;k~kIr{p`+mj&n{TfE<how_(Af7A z){n6Hx$eK8-#DP}fvn@^kIW@>olo+FuKBKd=_7Q_kDFfhA&lF6xjv8hnl8Hfk*>b! zsuOnpT+4Tz*XxY~w)^JlkF8F&;*D+ou={n*chzV59=Oie*z~UF5w$;h9@l<4KWH8I z`mXautq<~3KX;u+=LfB$uCM#2yPs>lsP$p@>pGwAr`K_>r{~q{bkCpZ`eFM;z5lTD z>HMIz>waAILH+e}*ZOhOhux3P4_dqKKd7F5?pnXG>9t?3YgfNq>xb3HeLlUv#y+p> z{=MEfpzo2aUHy?fVXo!7&Kozq_%4jwd~uscd=k3OCwW4jpX`A6k}8w4YyKQ}RQay` zyxurqJC9uVNAJsZKR!SCez^J<H@!a3pmp5lcb!M?FW2&OZQihcyY4q``b_UXY`<*h z$L;*0p2z!b92Os<_S@G__FH@xdVjn>)edCpK1d&->;02FVW#t4`+2=_K+a3k`%||+ z+Ar6&_qT3;y+7WcY6s-KiramVxrDCsNuDs<`7%d+8FqfxzOMbE)(6cWb$?&qIAA*m z?@z<_$9C?i#$E46s&#ET*M45_c7GT0_XsX%Z%&}cYK8~E>tLVN<%E(Qj!XWx>_g_? zlev?pO(bOARP{eAe}eoF{qp!J`X?;&Y>#d?xEDMCHpBO>7XO3t_5NM;eVAha91M?# zx_;F93+X!<imzW-{JjC)T~Ku5tDawOxs6_L9Ps|=n^3ne;+M{nxQ$+4x3AtG?@zS@ z^8Wby;O~RK4>fOrycagsDC@pAlJE6(`xN9)-cY011d6Z1eB#|<0o>Q3mpox1y2De{ zOJ2HIMBn?e)IVMOsBfLQ?7Q8Gb>EXz>*rBtI4prb)w6!$Br{hVnCcvjRVO~Jk6-z4 z2Ur02frW4i)V`GwKmFv|??(yop2f94FC;#}@_Zukmo3lrJYm=6^m#qSeii6Gg_W>q zSnd0j_$fRufuF%j_ybIw!u?h(W-T1gdLq0Umcqy2T$ne!_W2}!J<m(w6Bd0r@h>dT zD~Yc%qV|4mh_43oU^k0CpZHFe=V8ykfVz|FS-+IL@u$|l->~ydr0$G*)-NNk=}7Js z+z{r&>97oLdRl7x$w&7rEQcG7N-aOgpM2`<VX0S0ypQF%u3v<1wnaaec;09;zpxAI ze7FbH_4T?C-7r`JCo2Ar^<4Nd)b%Qf&pzGEHy6GIwZ4LQ;tZn~p2}M5^|}PzRVnIq ze%N&>edkBiznr=^o>}{SEhRqk?Ao7~5Z~_{^SlsFf~D{ysQsuUzEw%>^$UpaZF#Qi z6{0%~7Qyw-O)UM94|jt)U#|<%H9ybf>*spi2Hh}=zJ&N{V`{ILM|?ZW^8(_9ibWQ^ z#D`m+>-od3OX%~5rC(yK+4rVU_sb{V?|h>xf`czH>tcA~IM(pQ@vPyom$HT*zzVp_ zW#+l=AN9JBzHKMfuYVqSORhBeiK`4-UtPa?QSUcy_1oanGn3=tS2=T(ULTKn;&xuy zo=47QhUI+9h~H;<9yI@4^5$9c%ZV?774RpRxWU|;b}*=)e;)2V%fsgrZVXqap`1f8 zKAd%v_oLc@hH|ccAO1f3`|RK6s6Piv_`0#pt>%3zfNgHe&if~QSI<&^?ROq?d_C3p zQ3;Et)z2TvJB|DjcnvIt55T$bO;`at+*!Z=dVfLdJo;>up?*R0MEyLUeZDgzGyYc4 z=ec`KzjAos%*^zU+E3T|MeMuxeYNkui1@`1)c)MHU)1`E%=zs@wa;5g{E|m%e?F1; z&^fg~FDAb2W9E4QT>kOe^-=HF*Z00xJK*nuzX$#v`1inn4*1Uj|2g142h#O9&_=$m zeIm8@stvkDDeBWTr_`yS?<@1nycO`Wr_6dHeCO%Z_9JzpVg+-o`eHohiE5v|Zo@p^ zJnrq*{{AjKV1Lgud(R8FcYFK$my`FekaO$vvbi@!aQ3UU-=n$2*L<z^=l=c6Eno6D z$I91hpIhQTzG<E(78z~>3*gB2OuPh^zHipTDXh!jPZj2Q*!z<B(9{|CNqXu9%`=fc zQzPnEM%@EHGy5rmqra$qe<j2p`Lg!sbBQ1Dt$AJu_o-wJuY{%WH<<Xr=$`tq_WD77 zMg6>-x$gbR%vT0qhUIY0pUv|;*ahapc~H+=PQ2YOsqH@xU8_Hgz73rESMB*_#Gkf2 zFDJh8-_(P%;9U68V)MKb&iTiz=fX<GUQ5jLLU;l!hHo}8PG~=Z))nLxHZ@A&-7D6w zp6*vhoww3dPuH)YZm$;UnOD~jyDns|%9in*FYNw&zIiXb51H{n-lL6HGLGlN+g3Jf ze-4>B2k*1@x!M7L55nDpGCsFfZd?23R~zDeSFQcI_dlHfuKpEq4)^o-M!M#EeP++g z)$h5SYcYQxr)z$YUh2L@{R+6}8YVL+zo9)ZWZzf8Qg~-0^&{wf&D&G+^Vj&)W=)g1 z3EUpmD9t~)>i?jAQ|dK`(ofg_jpvJ{|5|3Q6=56L4(j|piT8qq@Gw{ekA^ybTnE$d zZTJ=Z8`|`xDe6z@XzFjVw&5l4%}!?h4Q#fKS?hkkhRm;^-xshF{tR`$)0yXNI1x^U zrSLYW^UFB@N8w!f0xXBGzzW!t^Dl(Q!eUsWxB~vSf&E|+{QvXAztvzK+!W@+9bo}H z$#NcYN;YagY&wa%>LstfEM{M4L0!jnp0N5?nBxt&2>t|h{bB2xiO+y%!3&|*>;36< zru8>7=M(FhNnU{;Lp{&0c}Dj;Tnw9{ZwY%^^7Vf8TKCh>^*Yz}nch!Ozr~!}64<P> z$!Gz!-x6=l^Y(CSi~d>SufezAN1|Wf^lJ%qzo0y=pGlp$@CEqNMyAh4aB??sCb@z{ zZA?}N|9*nj=WT2%cY_6R8k`5;hTp@*P}jSb_$@Kf+k8tkuJ;#|mudaUo0^HPf!l0m z*4x8_U>~UG)4I3OeGZq~+|*kE>iiz)q>s)ItN+b1$I8sp7M^ICFKoW}b}Vxo4~N5% z^c@2)fD<h997dkh)A`yjSH0BLbIQ5c=Df)=Z>H*<g)gr21-*|!&rA5e>I$g!rNkeE zbKw)P9RC0JXM8_%5-f%nLtS65C!&+@fAsUP>q@?^?#b6XU9XV%@vs;Uhb8a=I1z5i z*R=vDU(ZVUx^^ej{q(vF-EZ>sP<_48`otzC(ge1FPr`Dz6Q7R-Q0{vv_x?fnulo9h z{L?6!|7ExiJRWNKn&|%n{|lGEz5)4p=(@lja2GfhUIt%;3*p=FeW>S)y8gBFodSdQ z>#7$Y^?CHPoX4%i?}4Af$^iWxO8=EbFLfW{c~O(5OD!MP)bObmhHpT99y))bWB#A$ zmrJpqtNtzOe+IXuPj}c89su?J!sd@#Y~H))Vd5XNUJ>ekuKKGS>x=%u6z7q-KSKXF z_dxE2p5Ik}3_e^4C&Nxlj89v_?(hKE50=7*pq?k{`u}6z2jFb@7}WFFbWd3H<-}iy zi{QH!y-oLlMKAGBcrJeb$Kq!tx?kY$@NcO1YtuEc)Ytc*GrCP-0qhBj;k8iruW!9; za<txd3G;cq3+w}rgU$FHYzx0{X7s;9?O$W7r+pi;yz%EssQn46KP904T0GwazQgD5 zr<SkBuKMBJi>u)~+=CA+_rX<vu48@Ck0)=EW4`R;PV!FY>-x*^T70|%E{Bh8Eq<oE z-gV3|1>O#)Lw&z&y1OlUiO=M@?Dr=2tLtyW=YV|Qm*Cu&vz))Hepko(qTi3apm{!I zpI^am#TT`Y4K4c#oByX{Kbd1I=GhK*hXrsT)aR9I{y~;}se2C3pWt4+2H$}dmiv<H z`Lgee*ngK5%;)<SQ2U)L`fiT%r%V5>+>_?U#}!~JsQrwael6zQ6mAW-x6B_m{T|GD z7(5CNvdkYh{V?Vn3&+8UmignRzm_?t!F%B>%lvWE&tc9N;6k{_GJo9kpEKug@E_R3 z@_86H{SM4I2o8nCmib-vdpXuGa@5P5SCKajHeb<vJ?I3x!ku9+sJ}j>yPnK*KXW|{ z=Rn=xrdwdqKTo_IE`)Dd^fukw7QMtj;JNtO+2Y@)=)QvA!XKdCuTA%>MSmS}@pUEU zSQBmr{|k%YF;MqUcfA++zE1x-_G`=c!>;<3mNWNyEx0ypDc=XF4Q5K;nmPV~O)T?> zPS4+!yzSwwa2A{kUxJ@QwcSLz>c11S`gxXl`V&7I9t%&f=xw@FEP9EL;<=p1Y>WPE z;$z?i@DhvOrkiBZZ%kb7$sMfkfeYXZQ0~butmR(X-j}HB%fC1KgMZ)E;&1cs8J>gs zK8MwJqVATK`Xh;-0ndi#S@bsD`4+vzFX8!}@E(g^e0YQB1NeQhGcCVAwln`;=ty`j zx^ZdJpG4iWq12siso$!l`Ft)~$?zQb#>!^>H(UbGY;EGNLw){hS?axHsdsxoy-w8Y z0=I$NLES&s^*gh#gW#d?1b80&82%2I=iEBLjo~3s&R3tO_Ajpe2eD7r{fJ*zk$)|` z5$gThbW<(*>BR4aGvNaky-oM9MKAHkc>b5@I9EOYJf1%TpNB6?o=ULkUbE<niHoma zu>KXcWUe(~0hDu7?GyE_x0hxA>8`hYEAx5R8n%V2LA{?Xi0=sdz<z1c&!f)M@F%z} zpRYlmr}FuIE}y%X!>cTx=kmER3cuy+!f)#9!Y<?=0*}d1y_Tz(^H~|ThigE6KCXJH z+g8<Gi}l*Dv!!3y{2p!0{!WGav^DEOsQ2fpe}%g5z{N0OsedBz;cz4zohJRQ)R_<S z+nfDf0v}z?tQSGO|5Wpzw&Y8{JypN?7QM{5gn1{CR|#d#iiq+*pl^Nq%e>Q4oOiWV zjsIJ~gW*6pW_9y?BGl(2`5RjDwZ0R&Ja`1`55wxEZf8|j_M_{&>TN!qLBFwZJiH3F zZD)Mc{R?<5zKg!OMPG`3Cj1jNwdkeqUOfMud(nsc+k|s%Z#mzv`J2)=sDCR<f0?(n znzw~Te<}SI!pZ2qOOyUS$NJL$cKUx7FptdLf^+K6zU6ar8}j$E>?dsgckC~y|IU{F zGVciHmU(xy=+{`oyceBd9^3%x_r+B|lse<#s%x2k!{A{Z%z7}?{Y2kY=?7T!U(#o# zHBH^SVN3G6lP7(3zf|-0vh<gJ^XM!6cDLyB(DjF-nDY%-Ox`7y{O&2{pKi&QeiKx` z(=2+K^Gf=@r+oc|yj40H|FyrP$qUL~V(Bmaex|SV``e<IK2zx{b9J`NXVbU0=&zyf zb*lcVY0^twnP2MK=5f{U&723pVmQt+zfFIZMc<2fAshimrAaS!Wqzr9x~0CW{!;GM z&F}^4F0|B7tZnXnYq%%e59;^fdg714(oQD7$vTEDVH=og{u1hFz0|*#=Rd>0E&8vS z>pS>6{0p`uZ#?YCoCTJ7Q?0jQ$ay+h@_RYX>#7g(NuS4F>zZ@k4;I4SFs%MU>XgGz zJDYyHuWxwp28PE#-S5&I&!3gz{QWKa7r*|-H}UHTi(Y(wjlSaR@oCaa-4CcQbw^n0 zi>_0iIp?<QV;G#lJ@^Xh^Z$}QLHW;H^1sh={!c0Pf50-o_|+c2R)?D@|L$|l-++AW z_ePx4sjwGy<(%%=(46BVQ0H%!<N3Xr|CE6J&$R4c{5l%n#IJiTdg&v6KNR4vt9}vt z*nK^7Ztqe5Q_DP}f0w)+$di11-an#ikz)P0>H9JFKsXp45A}Xs_4iU|F+8-3Ifwh8 zu77{b^zSmypKAVlEc46$j^X(fIK!fsy5dh6I-5VP`t`ZzTf%Rt|GQ<LF?=pw4xc6O zWy||AcO!G2^WanPS*Xv~rhCz%|CxBluBJ~RoC0<IKO@#l|D)(X8J1e+`Gfcp*tDD3 zM{}s>ch&E=v8i`DJbVkYeh7Bk(yX_Ey5GTB&X;+M)x29;=AFg7Kf<n?oBdr3e}G$2 zPw)4!6!Y6!^5<tc|Cto~|BVlN|KissJl_oN4#mGe9P_(d^#9q!oX>S|SA0DXJ^|Ou zH@eZB`!skzyk{%(eD!S%w}pCt1@xH!ZS^m<+^;>eoPQ$y#|O+m)-u2B_f32iKhL%3 zrH}Y^0XmyMu6ljme^9><=Xoof4)u9PmA{xd_NTARqx-kxc^4QoZ`|}>u+LxNne5|y zsP`-Sua*8Bi(cOA#oX7+)#u2Oyw~I5)$l#|EtIcQw{LCU?`NT&?>74U7|`!T>gxRI zS<Zij{@(}8Kg2S>_<ILFi@$>{dg&v69goiDkE{ME>XpOh+?!RP_FweRDt!x!ew|It zeYgb5*NJZA>-wVajQ$)r25SBG#1DW$_2Z^rkN0E?coH0Gd4JC1>*f^r4gA&e_4EQq z{Y4qlUqzpw`NyN12rJ>wP~Qhvz0{qg>e~Et)t7E-?*E<eyY0-n#rB4J{^jL4JPIBQ zwLXvd)=GDBj_8m4kMUtJoB$`of9)6F)`wkSH;bP(-DVd3{=~<^pJ2Zo%$(1|Hvg^t z{0>Vo|7+^#{q@gs{=gLbzhRkQ{Q8wT33O{f@o%AHert=qzpA@7=hDq`KB6B;-dvTh z&to*tC&Hlmanm1$50l_--Oat-59<AjzMs<Xl_tH^m3gGDZJzg;<9j%QInK1q^9u3T z;G6Jmi{7St-=beae5W0akKe%kcQWfK1%{tM?QaY8LHYA6`Kx3(zg>#`@3G7;etl1! z1irOX{>^aAZ%MxPdpv!n!6J13%Q5{`j`L4Y`lH$JD0l{(2(N(C;0$Q<GphPhSN1D& zpTIma_ZZeP_w{OS+xbRaU;19$!+Z`*g15otcQ)~Bx!+B8G3)iA_FL-hPkvnV590Up z@C|62KUMuI>@(H<y6RWP|4m^}cr+}AAHhFi3(hMK=373WGF5*K=92jjX081nMf@x{ z23}~<+jN&(^w$$Fg;U|37QIb(w?!}U`*^+>HnaFYhv!eir{VKZ`(x9UTl8{ow&uCM zH(wI}4Ypy<bzlKJ$uhsx-GO}3U2M_!<a49P9_Dl8^8NXIfvX>2*7rlb|A8U%?<arJ zuBOi#%&|3;{+;N5JS?%ylTV#(;cjp*sOSHN{=dL>=+?IATM}Ox4uFH;lW+ml{lez& zyL;_E$@v|EFa6+UaJt2>(bPK+UI(W@J-?jO-aOxoy3$wc*VxU>yBAEiego?60C!jY z^gJ@hKIry?hrk=*udp@y>;N~1-C?Hd-@;tC!|CuIsOPci9<b;iCH@3l0H3w!ZMqjN zdWkROx%k`O;^*Fc4x9}yg5#jxZ+-QLP_HlS508ef{e$YAO5HP5eZ3#)I~JYn`<6Y; zdli-be)_!z|3kk6VLx~p91ByOC+hkWnEP6IH`McqpQ67r&3f_gQ|f*RzqQO`)BR%6 z|0Qw!Zw6PeoJYc<YiZF-d=;L{`S-EtS0mm5c7p3!^fp}=i+(oy6<@of>jekEQ{Y5s zdtcIB?@{`_2|wZM<JXq2zpi@O$4u(K4F~r$p9h_K8J-8*?`PH<!YO=THxn*W-{<M~ zL;BsJ`ZeFn)YbLkmM?RQUo!WG%&+H-TEF_<#<zT^&r8nZGtT8NxT59$q`Tg3+?!tT z0C+Iee%W+=Ec(NV_lL6I_t>Yde=NFUI2@h^wce&X-J&1FIh+K?!V96U@2bC+IxFmB z&b<@d6z&TTgSubX{CntsAAAr#0(C!|Zk|Q|Eb*7%tMCnr-lluoqL+9D&-3u9i^Z?c z(0vWRgFiyOUz_eXi~dyN=fYOZ(E<Jk?rxdyIO3<ki{TY;IX=f*!On1VsOOh@Lsh*? zRlOBey)Kq|GS^r&*WavLlh*;}!=18Ruax<;KX(wn3zorI7QIdPphZ8A_%rYYSZ>kV zbPFwdi7(=LTYO&K;`h7gK7^mbFQN9wru)vKm+v#S-q(DdodH+m^Hsj@Si-uJuUjh= z8oloS0=lU5Qn#u4KBy~eJ<pNEFM&_M_4)eL1MUrvhQ%;b^#(B4NH_-C`iuUYH0#Bm z*Qxs!e9tnEP4}rq{}u7?;g9fFi{7UD!=jh?KRlQ7-OX~I&4{lESAwfp^fq04i+%!g zh_7AI?Ev?K{b31|-?!E0A631pnDeeQ&wC@E6XkFb>~>)7pC9IL@2vU%5ib41L~em) z@HJQge}@VFfBxkE53yMOfAd<He!6}oaryfqD_R?!{QXtJzgK78H4Kkl+prkQf1fRE zyRLbj2j}qLvB-a4^ITW+yd27(e=p$AoyngEYr~(Lkw3qZ&!2mk#h*Kv3+3Mz=JWgB zYvOYr91ct1#c(2&^U(h2`=_7lwbvU5v@f#u{?zS{_#|}oOY($a^QDf^*K<2R@y*6; z`x&;sYrfYT2hw#P8k?Us-z4tphveDV*y?E?vc3PX{ay3D-Z-G|fvmkh-k)j*>U$p~ z&qja0(tE$O&#wMvJKuF)uTSs&arIN*7uU7#SNHj8KVALu`nvs%+8=#>dhOa@=j(Mt zuNSxdxy}<eecbO)L-#9g`-^&>bl*4Ed3FDwb=>Q_&gb>U0o%Dp?T@Xm#9jMKo{eGa zx#oMlaUfmi;r(pbe(HPTdfsu%Pxm~&Uh<95e&}_wy5{$7wNBP?)5}~!*ZCw*=<|~u z5MNSda(3{2(sdhKe%SqL|Mc3|Hx6iDZ0o4~(tR`CFY5m3-cQ`>g`LMW-|LM7`rgXg z`%||+;*&7f{gQnM8~c952cfGUk|)fy{9Kz?d=|RSpX++rw~em*({)_)b6v0ZANO@W z|6S7#FzR^==+iGl{i5Da-0K(N^C>a$yP?0|uKRPnKk2UT>lp`J&mk&(*z?GAzH2|P zHxAhDkN2l;f3$Djue$wm^~d|0?3ngLuanim|9&NEec1W3ogcM7ajUQW*6X;<>*p~J z=yQ^__or@u#3vhF{j=3cS3KSGq`O|&eTJPU+xdF`uJgoA-_Z9Hc7HlQ>b2|r(DS(F z$4#&Iqt~wU>inqJuJh%(Ui;~~ADtidI_!L|`Ce}vu$^mT^GEyOy8mqFyUy$N#sPh9 zviANoY=7jOg}Hv-vJau_ek3nbbe*rU>Ge6d?myl6Ve7fhAGJR0etf<;A?<^#UC&SQ zGR3g-x#q`BALO&^yg~KS{oHlFT-OKr=ej>#ud(N++mE={3wz!TZGU0?$aa3%^KhL% zYQ5f%UPs+O>iT*=L2K7}g6gIFx$AshZyd0lgZIb#Q|*A<k6gbGvJau_ek9Mvbl0=> zsc$^&e3{O7?dPi3KDy?|O|SQ(*RJ#G{B*Bf=ka>ufbATj_DA=1?U(I**Ll6(IH1o> z)~^0Yp3pVl>!UpnITxX;-;$Rq<5u5w9#?&kFJbGs=6k(yz;-TC`(x`X@u>Uz`gNbb zoP*H&RkvSp^GD9j#<<NJw|Q*7Nj&O#rH?S`ey;UpE*o9zMXlF!Hne`O`_X>rwQIeo z^|>}*+~<w@yy8~hpGWeEXg~BiSzYt*L9|ZRQR}6TjZyda^^F5I|8?B^RkvTR{)F{6 zY`*KfUSIe5H?;H6`_b#hb|3Wq^}4b75x4#N^GH4s?T20`tJDAeV5a*;y`Q+(e}lh= z^lg|psOi#?JHTG>T&VXWy3RZw1IJ}azbSpUf|tX|mU*JqSK{j*uz)%Cu*{?Hzg}zq z^>e-UdgFlhMb=^c*`c?2U#7t(hnRIYsOv|qmwiP=y`P{yuKJ*QVV~#vJbM0o?pYx` z5cY#d!qedya5|g;XTkg7WAJhK415;82=zRf?&o?R^t?g&T3>dUdA}cn%?>x~b)eQK zh>LD<U!!012*X~m2xdB8_j{H3D&Y=l&anD{_;DZgx1_%G(e>-AA4;F;^tl__>Zhs~ z-8|}l4kxC#pXuoDh4;gUpq|fFzbA7PrZ`X3`q9jBHXI8tgnGZO`cd4U(_txG;Yjm- z>H6~gc64{byP(!jA)cy!pMJd8@IZJo)b(BUCG2YqybxY$+3%mk7sICg&3uPIJ&&ut z;3!jXPq+`<7wY=EIqIjPp9b%S|3F>eRqy)w-@C}{w+}oVj)Zz1*ZN*>926ho=BLb+ zD&sc4pC|c#rFxDwo%geDKjY?)?Hq0KxX<r8pWbJt^IiMpx?cMow2s?;^}Me0Wjo(> z-dxvfzk}AfzTc?l*Z#To%XYr&ysmn^zo4~i{l=!({<-cy+xf2Z#!avN3tGp0e%JZ* zelwl#+Rs(5_ZPHwtsk{s&+FPR>ilv1KG-er9{37;3$_?wejlwZ+!N~kNWCk_D}xWJ zdKIj7{_WI#4!#2agnz@W2AX-cfhR*<?;iB?q15|X)!S6nJ1(H!1LQA+Z>xIEEcqoz zo4GHBQwEv!T~N>Os-HpK>!~+wu&Mtt)b&L_hr9~d*)q>J#D9SK)ZNxn-&NnAIs@Rz z@DxjZSN$r-7(d#<Jz;OC{aKCpuJA^<>9M9xs`?q^eG0#Xzry9Imj}C9>OYA7Nw@&M z1Yd{mL+SGq>-N;`WU1em_&B)v5VOxyq2BLerF#e6D#z9C&)3AihZ~$=bY0<tCz|ym zQ1=U)-~4z}e-*d}T#x>`pH06bd4;eHJ_XC+NANG$l0FTs-}mgVU555o-+t>e=Qb(M zE9ZL%`orOoP~R7uZiq!cl=v`sDjaRm+jJ!sy~Hozx!lheEc#1`Pk>jzYb<)3?q-XA zbM8kaTmqX8t^M;t^n=jd0cXGm;gj$~_!SJQe;T?m@B%miUJXm3^qs}}HTXW%_d)j6 zmHqXFUt0F7^#jlig;U|3@P0TKRzO?*(|CR!JRe>LuYxy0=`)k{Yw$g&_p85O)oWM1 z&Uam>yPs>lsP)<p*M1ExU+>3t9o9eBep>I^-|LM7+DBPyf5x6{zRp|<ACh%(?O%Vi zegXP(Bi6r8pZDPBQ19mz;;HJT&M)Ns3IDOwx9M6~_TQR#JGchyXwlnr>ss`kiFbuX z@ED7JGvZspZQ%|Uy-l~HMSnZ-$6($m<{oVf^?Aij|Dw!2%*?%LxM7PCwZ9Lp`lG1( zAv_9SKC}4asy|cJKRclQi%S1;fW8v_UvMw<2U+Id8UK!eCGY~M@52myUhP!l_gU}< z7*@YP)t?klzbVgUo_7ND`8@9q2g72h=ihIn+2=TT6Kr`}?e|UehoBn_PgME0v)29O z>wt}oUEdeqkAj2Y5X*VE>VKoo64+yuIp<zb`yaJ_HTtdv*M*%e^SJ75_e|n?zY@36 z>x~0(@n`C2bAQX=PjKG3Ccf8shWA5#emeiw(~W-PGYqx<X`Vj^S46iG+z@t+D1Te( z_JAeqYm8-oQR{bSjw9e@%yENd9#{PZ)SU=Non_AD@^flGpKR$DFxL^xH5!hE7s2t+ zHh;6T&A#@4r^0jL`S4lz4cw5rJ)q2?`|A6g>3%!m)1L4S?#Xn^eTiD%i#d*hGw^RN zpC8(<Z0Ubyu5rwDE4&Xr2p@sA`L`}H_v=(R75)$25C4E`Q|}OX5|lY~U+q_>`)wqj z-*5;#0bT$vhI-zx`MaFY`wMS{x5F|x3s%5Spq{6()w6wHA#v@G#BGdPulq*b&(}8& zXy0Y+{qg=(JK*m_-S@!z6Hk9`xWs(_@GyKFz7EaQH9z+rXY`}tIdB53QJR06MEn}~ z0GtCC!XD#I-E`-_NBxiB=kRN&``L6qTJ%kryE$wLTU+*H)3vwg#kZOC7oU1r^zxqB zsP}8r+2TGw*#VnRws>-O&DRZ^J}B;5&+Cl?HeVZ?KQ<pE?&^o+*%-HauJd@kalm%I zI_~OM-17B2dL4Fux}ILgt-k9#UT+-G=PGMge<UweHn#e%`*qc8-^1qnddUuIKU~+z z)%^F@+P|>=WIErqpQ}EsKd$|v);F~MMD3TaZyeC~#<p&3erX@#w*R=#mubIlyv+PQ z@_7>s-<@dqA=LA{fc_(xZhby;YzOy&2SYuN=(kBxFLjPXe=<DHQeW$b2k0;3`9S>p z2L532a}N52Fx~n*`fdbwfV)}d5&Z@!>ZMLE^asJdmik)XCqS>?SH0HvK|j}PuQv{8 zUu5n5$*w<g4nlt(**y>MzxTh|frj!v%07gy_gnIWVe_Sq(6ye|8wbQc&8Yp+{esr6 z^90pP_jA|zyxurqJBO(K(S2R}`TV-iPy6G#4tpL!{aow2>UIBI&u?h^340#e5511M zzU~*acAY2J_1ceI-;eA3VfP=md_7OlI;>wo_4RYtesR<5{phvpygFa6vt7@%zt<ZF z^f}7f`%||+;*-$TFUb>TI^VUQt6ugcbj|mA<AC_5>HYEkR68K|!rupfAN+l&c?;yd zu(3v2_q~z)sP)n(RYpCJuV44QaP=qEbG7L*-Oo0M#9il!n_l)|qwBo3IuduS7dO4^ zL+Co6<Oy><U-n^R*!|h+);AvYJg)U!^?KhvKiL88PtZC!yXMysL3#2#Y`)Y<m6`6R z=W^}e*z{rj%65L-&P)5D*RJ#Ge7z1^FKoV^Cukk_ey;OHt<SWduKP*%e6Iby-Z)@8 z2k%ea{%GG^{mOQ}>%6Xdy+6Hnt>>!GwSIbDy$-wopn6+hZvOkf%itt<11yDi!n@&v zP|r7-_!;mVc%DVC=hJIlUq5$UyVi5n>v_WFhpp$@-&L>Y(`(myuKKY3!sffq>#EoD z>9uRUsP%q6<FNKY)~^0bp3pTvYQ4-Q%yz%4Cz-Ej1FkUK;7Y^ep`OoGFZ;An*SF~; z?)An2@k3Mlb1moC{3>&<tzk!~^%dy9f!Wq~W6rDLO>l-~{$k>1#ze2rN3XU2`ng_v zy>USMB5UuD_ovzce;>>}c$m+@E?1k+|IJ}{XjIGmOuSW0^!qT!1Mo5UJX~h-rT;jQ z_zf}9%RRJF&u`O7-0O`4;)ka8=WXu6KG&H0e<17+wSIl#Tf{_vJafDSKZM^wJ^y{g zACHM%pO0Sa`So+X_Il%h_C?m-AMa1K1NFTRk|&J%K1m;8)ct&Y<AC_B>HW#BKbby{ zhThNhK4;pGT$}H`8_f67r8gQ*gU`ZT+mAkPy>{J?*Bb}4kFw6RKW}p{pSsE1*M)HH zo6ULyxFyu{eM5d{mA`tL^x}(+dLEn37I)2e)$6`t^V3}~>^zyyckSn@59@EH`-Po1 zY`*J$UG;iCy$)M1*Ym^r;ky5*^?E-+Yu9;#>gng{t{=8uuIFoi^*Y!0m+kqrpP62V z-G8R%)&2bZ#sTe1s_Sg~7q)+{<>%VG`W|I^e%F3pZyeC)CTmxJBv0t`lN}IWQe|>> z&A-=*DnHZx^gc4(KWslezh1|^e%Sdko$uPOvFX!&|6KhG+dtF&!p<8uKkR<P_SgA( z-O%R?yT7pc+HbuMTR+?RdOu;;VfPcZzs~pb7zea3vJUG{rt>r1Pka*QT7TDhz1}z= z=dJ1LkIzr`Gt>TMx?kAy&b4{N?l)|HSif}tptbL390>9$)#t8$y6W{Dna+3Z=k>+` zeQvUjn?Ev_&~-k^6Q(<Vms0cR2={{r!qebrcq!EVFDHH<d=UN)|Ad`yF@1Et>?>6^ z_WV?Rib@yO|ET6lwXUAO<Un&T&w~@;<uKK{UT2*3K6oFh9cV1~pp?&v)ebhFBbnZJ z9(_v{XJl!fp#7II*K?Nn%87qvc^*_h=y@e|yB(69^V0L>GsjCYnMcp3*X7K)Z6D)b z0bBsf;UZW8KZTX>7pUte4mEX`gZjDax(#(Mho$g)SP73k%=9gWQ=slwM!e_<qZh7l zq*-fy8{&t<A~>nP(U-zik232#xLuK17r_0Yu3t!eq~*ER$9-KQ`yF8RUkE3_iSSxj z3Wp6e`V#mgEQjyF3b^{w_zhnkY}V!Q^y8=pUxwxI;}gyEAU`WbcaqV!f&0Lq{B%Dr zr0?OD{zb%(gT-((EP-W;-?FZRT~1ETpL}$?q^J+_qmVi+M&LK>4D;c}BhB-CxaMi8 z&6|g=*Qna{g~XqM<#6xOMqdbr!l3===f&jRf1ar~7d{Qk;hV4m9&iEu;fM=spI`SY zK{pmogxA7SxZNeG)zkIEt_$cp2o}SOFU!t6VfWL}@+Wc*Yh3QnqcQ!usG;3szaRhm z8vgxt|9zc2KKD2DpZ`l=pnQCIBt<{wqC1Aa=h}Y``OhK$IpqF1<lh_r-sIwYQ_Sc7 z`B$d)>!*q6<nPDNyUOIr-!~uidr(F{`TLm*t~UMU?>i3aUyfe>e%qpJOuqbmu|fH+ z&nu~a*5uUuEkQT!TB9$6Z(LV<eg*O7{JmqY^Lc%4e{Qwm+}DiB`R6gmLus04E_KS& zR4?84UFMR%-!I+u8(Y2d8_nmO{C#tcZU1rGZvlUg-@!0$^F=*R5&Pb;wDzyRQTLB~ z{Q`WEKfgJVwfuR^xX<tB%kA%f{Q2e9`I%{Jehxan8f858={k?s*L`le?oZJDP51L$ z_bb=uPxpE1db#dT*!kDL(|n&j9G(fsKwbYz;vd6r;LjGl_FJ!Yef?aoz1}#WeUY{I zC%yiNufn+bD{~1O`g}#x&F9r^@OC&I>iv%(ekPm*C&RG$x}ThbjjnoK$2C7{eY)p+ zm~;6J{s9+5y`SfZzY0HvU&FBZx}V;!Ugx^Lq3tK?^T@Ve%g->MhwH#~;YLvJe_P^v z!+qev7QNn|UhDdUsWS?WhUccKzV08i*7IdsulxJ?k{!_g1g(>^6NxqNG4I31us<w@ z)8K5V^Mm>|^yfvl82`?`)vyFknPS#q_g_Yx>9?7BW$>P<snst-xBKm>=?l^QV$mn= zFm;ZG#qd|C_nVkz^dn&jT#H}-YJJ#s9(BjUiSU<*`h}f0+xZE;?>h`;dLH@piTrvb zsDBxA%J;WHdi^}X*VV32KhG!L+w#1K_<5G+x?a@liOew>mcj*=`O1m!e{X7^2T{-O z>zl8r-UshPwFCYhH12y~cAxUk&8jX;vH2uV%4wEpniyYeyjkL|TI0(l%4>};pQx-g z-aPS8%cPb|7tInYBs#RIExux6ZmsbaiSo9!>02gNET}EMQliZ+wZ&T{@@tK+oT#id z-a1jZYi)H_NzCU<<FZeiCE6s)YmK)}l>GE>gPJ8)O$=$)Y}pb^|G8PBU1Ix#Ym2u} z6b)a$7X50L`09z`TJ>urM%5Z$GjZ63wbfrMG5O-!;vEu+iM7Q$Cbq9NzV^RnuMRXz zbh5<PvBcN4#Pcli^(^tumiWK-R4r_l*ubLS&=T+RuXvNH$a0Avmgonqssc?DtrI2c zzO^PkSH-J$RIP8bTXLoCs+LU>HU3xktNyWP)&H6#{(T=#tcq9HDO7bvFV(M>7^3dU z<f?dW^FKtLBI>MJwXXirv1)+o`bE2&^-%_itBB7f-hn~eSG^|H`ieb_a1i=_#0#r8 zQuX5$gGBXznNY1SC%zi-g~Tg~A3?lrGxoce3H(BQABpd60>g+;Bwj&$W#aD<FWJWg zW)knXoT*>X(*)$>uOIP3;uFx{SQW3$&pGHT(C>@>8{+u{t|7kB^7ugfY~q87PwZs^ z-HBg8yiK7Aw5al{`p10Yc?X%b+@IB&*FNWes^ZoDPed<o?1dKnw5oWbme04@)G0jJ z^gYKQ@e}cK;#J#U`eXAIYM)2y@2x&R52(^Fy;szcFEgWvCwiN@?@_<hQvV4{{3GhL z>0=6PLY@2-YoGJLs(7^zhp9P_u8LRBSxTLyvMS}p#1n^_!YdghUL#&ke1GC?TbMd| zhnYb2=S%gEu~qTf?%Qou@#=X7sd*ltPCj+^sg_m!_=b4l;bwg<7o}^}g<tA(UlYgH z#Qww!coAh^r&h&lo98O@6VZ<{<r41@Z*!yx^d#P;%8=^5Ma0F2VO8<k>R-Opz;=ld zYQIycQ_Kg|9n^o{Qb+FFSXJjA>R+kiZK@8Uwt2+=+mt@PN?*ONvcYDMCir|R@wvwk zXU?ZA^*^hMSD){ERbS?ONX7r4e*Uqh@J`g<rs@N5>HQ?W3h_b2D~QYaUP-*o5F?b& zhcAie6Yor&9#voPs_RcAE?-BcRK;uaZ65l{<4ggrUE)XLWyH6oe)p<@YpZiaRlK@y z@$p934gF2T3r;YB0^+|BFCi}T53TxOS$bZ?d!YZWDqdUPe=PB~OTXW3mzX=K>I=;> zKe`ZqO~tztUv6-+zL0pHiVr5<OT|woK19VQ5Fe}Jw-GN@@rQ{&s^TvZuTb%ii7$6d z^8CLOUt7gjUbWhkc8LNN?@YX(if>1}M8$g%zfHvl5PwL;M-ner@o~f}RJ@e<?<#&j z@ePhm-tTk7+w@M3zfXL7rT>X|FBM<0o$;qg#XAu%R`IQf-=^Yw5r0U<`w?GT%~?$R z1*Jcqc!i2zNBn0MznA!mLy~=%Pke0^e~Wm&ihoCZcNK5e-uN?C#n&W0S;aRaK261U zB|cZh4<-JtiVr3JyNaJne8uCE_j@(*$tpgB_$(ElOZ+tzf1P+&bzWZ*uT=Vfh!-87 zJWso&-(a^(j8gHg#BWpaorup>@q>t$tN5|Rw^wtXL40==pFq4&#itPOr{WJ1AEM&V z6Ca`C9}q85@t=r~SMe2AH}`6?igzS_mx^ye{2>+Jjre>OKa_Zdil0FIZxug>c&kH_ z&+!W4YpeJj#J5-RM~IJ7@t28@SMiUDm#X-0#P3q^mDVu6J*wjC68}cUw<f-6pX7b* zMZA}aA3?lG#ZM+aS;fZ?pQhs15Pwa@XAu8F#UCfW_o2yiE+jre#Xl#0k&6FCe42`{ zvh*9Ic8NtQzCQ79RD3()D;}0S&%VU-RQxF7o2vM5;@hkEg~WTQ`1QnxsQA6a$Ex@| z;^pf5(l>~gD*ac)XQ}u<#9vVHRo622?Ohe`Li}eH|1a^i4^Q@Of8xDVd?4{bDn63< zC>6hi_+2V~6Y;q!K9hL4ia$ksxxUGBzD;}s75|R-_A1`A>bLf)zrQL}@zseBQSpt5 zU!>wah?lAOLB!{(_%X!GRs3|~6)Jui@xN94R^nZcNcQ0Y;ybGNbHsb8`1{2BsrZk? zN2z%8j>fl(RJ;T6+f;mW;)_&#SK=G=OP;?E@d6b;o_KE+Kb!a<6`w?Wgo@uze5{Jk zCVr)gzeK!D#XlncjEetCyi&zmF8!_Hs_*BIOy2K0#D}W*R>ZGV@jZ!8Q}MpUpHcCX zh<~Bt=Mi7AfATz66Yr|x(}@?T_+!L-tN5$Lhp6~x#LramKZ#$d;;lQG`&Opnory0} z@&6DXa#ZrZdJ?}u#rqR~M#WDd{*8)XKs-^DT>m=a?N$69;$2nzN#fh9_#4D~srXmK zi&Xp{;zLz@)uq1?(Jt|cigzLYyNdsp_;Lf1_q9Lq4ODy}@e1|z>r~?TN`Eo&0u{fJ z_&2If8Sx^epHF<KiZ3F5k&1sq{81H8tZVMoYbxHJc!i30CH}jbvpeyhmHq(YiGj&} z9!<Qxil0V2U&Y4}-&@6RCSIiC_YohV;!hJFtK#nve?i5+C*J1h<oTQB8Q=0%d=28g zReTfTXR7$l#3!rx!NljQ__4$nsrVVhe^&7c#J5quk2Hn&AQgX*_$U>Bp7=#7{sHmH zD*hAk<<zfJny;6r`q3_No6>ividX-BTHgPa_a@MCUDcWJwE<%{F+AHblL;1}0AZ-y zc?f}Mda{LO>7l_kCQ!PgURm$GD%YUFNr)f@5;H_(U`PN9Ok)BGsDaR=vj}35xZx)x zf+TeQhBWFx7`jbR0wF*G^taF6r|Q<dx89Rvu~x7DFR*UCug-MOu+KhwI!pAsVJNXG zp8EthEBHGE-%!Et2TppiH;7*Hsj4)?crpZcs{FrZ;M7I@+y|V}pOo~MO8VcG^e4W= zz*{B#4}o7|{J3#k(uMNe`6Mp?<kuMZb(t=227Zz8SmV)BzSc+llcZnxI;a2c#r)j1 zp37M{!+&q#hw)Oujela`K55TM!H-M&n<f1>fzx|^r}AD;|4A<2_*+isO8Qp_e)R7c zSSRIwQSc3t-hT-H{=z47IVb)H|Gin-e;hc~d!|zFKT7)Jl3u#Uc+OKe{l_J}9<Muq zQ$Op^I{9)6IE~}64>BM(NEkm9{LF_Kmq=qq3k9n5f6Vyj<-J}g_|bPVu8v*!`Z>Xm z3$Bi_z;{AWOy%sWr2m-UCoA}~p2q1<3;r`)jq!fq^j`bq@2AT1TY|5v;NH`@e-@>G zO!@sb;MAU@Z(-mA(xE2=KmI6w(aR+LKS((re=Q~+K9>sq%x7>pC$Hl4CuAHC3ceua z%uD+B09Wg)QjYOVF6YGMT#jb5T*2qAVEnoKFk->?UCF>+!Cw!Y%0DjU>;Cz)q(Ac? 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 Qf93t0{|_n|Dt{XP2cJC)3;+NC literal 0 HcmV?d00001 diff --git a/tests/ui/macro_use_import.rs b/tests/ui/macro_use_import.rs new file mode 100644 index 00000000000..6490a2107d5 --- /dev/null +++ b/tests/ui/macro_use_import.rs @@ -0,0 +1,12 @@ +// compile-flags: --edition 2018 +#![warn(clippy::macro_use_import)] + +use std::collections::HashMap; +#[macro_use] +use std::prelude; + +fn main() { + let _ = HashMap::<u8, u8>::new(); + serde_if_integer128!(""); + println!(); +} diff --git a/tests/ui/macro_use_import.stderr b/tests/ui/macro_use_import.stderr new file mode 100644 index 00000000000..1d86ba58441 --- /dev/null +++ b/tests/ui/macro_use_import.stderr @@ -0,0 +1,10 @@ +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_import.rs:5:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use std::prelude::<macro name>` + | + = note: `-D clippy::macro-use-import` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/macro_use_import.stdout b/tests/ui/macro_use_import.stdout new file mode 100644 index 00000000000..e69de29bb2d From ede366be637657280ca506c5bad0f41f96c47340 Mon Sep 17 00:00:00 2001 From: Devin R <devin.ragotzy@gmail.com> Date: Wed, 4 Mar 2020 07:59:10 -0500 Subject: [PATCH 189/526] collected all the imports and names how to compare macro to import path add more imports to test --- clippy_lints/src/lib.rs | 6 +- clippy_lints/src/macro_use.rs | 252 +++++++++++++++++++------ macro_use_import | Bin 2816064 -> 0 bytes tests/ui/auxiliary/macro_use_helper.rs | 55 ++++++ tests/ui/macro_use_import.rs | 12 -- tests/ui/macro_use_import.stderr | 10 - tests/ui/macro_use_imports.rs | 37 +++- 7 files changed, 290 insertions(+), 82 deletions(-) delete mode 100755 macro_use_import create mode 100644 tests/ui/auxiliary/macro_use_helper.rs delete mode 100644 tests/ui/macro_use_import.rs delete mode 100644 tests/ui/macro_use_import.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index cd258c7b506..89f55986f63 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -60,6 +60,7 @@ extern crate rustc_trait_selection; #[allow(unused_extern_crates)] extern crate rustc_typeck; +use rustc::session::Session; use rustc_data_structures::fx::FxHashSet; use rustc_lint::LintId; use rustc_session::Session; @@ -1060,9 +1061,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let max_struct_bools = conf.max_struct_bools; store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools)); store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); - let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports; - store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)); - store.register_early_pass(|| box macro_use::MacroUseImports); + store.register_late_pass(|| box wildcard_imports::WildcardImports); store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default()); store.register_late_pass(|| box unnamed_address::UnnamedAddress); @@ -1080,6 +1079,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: single_char_binding_names_threshold, }); store.register_early_pass(|| box unnested_or_patterns::UnnestedOrPatterns); + store.register_late_pass(|| box macro_use::MacroUseImports::default()); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index cf526409374..4c89647a574 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -1,10 +1,12 @@ -use crate::utils::{snippet, span_lint_and_sugg, in_macro}; +use crate::utils::{in_macro, snippet, span_lint_and_sugg}; +use hir::def::{DefKind, Res}; use if_chain::if_chain; use rustc_ast::ast; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{impl_lint_pass, declare_tool_lint}; +use rustc_hir as hir; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{edition::Edition, Span}; declare_clippy_lint! { @@ -20,82 +22,226 @@ declare_clippy_lint! { /// #[macro_use] /// use lazy_static; /// ``` - pub MACRO_USE_IMPORT, + pub MACRO_USE_IMPORTS, pedantic, "#[macro_use] is no longer needed" } -#[derive(Default)] -pub struct MacroUseImport { - collected: FxHashSet<Span>, +const BRACKETS: &[char] = &['<', '>']; + +/// MacroRefData includes the name of the macro +/// and the path from `SourceMap::span_to_filename`. +#[derive(Debug, Clone)] +pub struct MacroRefData { + name: String, + path: String, } -impl_lint_pass!(MacroUseImport => [MACRO_USE_IMPORT]); +impl MacroRefData { + pub fn new(name: String, span: Span, ecx: &LateContext<'_, '_>) -> Self { + let mut path = ecx.sess().source_map().span_to_filename(span).to_string(); -impl EarlyLintPass for MacroUseImport { + // std lib paths are <::std::module::file type> + // so remove brackets and space + if path.contains('<') { + path = path.replace(BRACKETS, ""); + } + if path.contains(' ') { + path = path.split(' ').next().unwrap().to_string(); + } + Self { + name: name.to_string(), + path, + } + } +} - fn check_item(&mut self, ecx: &EarlyContext<'_>, item: &ast::Item) { +#[derive(Default)] +pub struct MacroUseImports { + /// the actual import path used and the span of the attribute above it. + imports: Vec<(String, Span)>, + /// the span of the macro reference and the `MacroRefData` + /// for the use of the macro. + /// TODO make this FxHashSet<Span> to guard against inserting already found macros + collected: FxHashMap<Span, MacroRefData>, + mac_refs: Vec<(Span, MacroRefData)>, +} + +impl_lint_pass!(MacroUseImports => [MACRO_USE_IMPORTS]); + +impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { + fn check_item(&mut self, lcx: &LateContext<'_, '_>, item: &hir::Item<'_>) { if_chain! { - if ecx.sess.opts.edition == Edition::Edition2018; - if let ast::ItemKind::Use(use_tree) = &item.kind; + if lcx.sess().opts.edition == Edition::Edition2018; + if let hir::ItemKind::Use(path, _kind) = &item.kind; if let Some(mac_attr) = item .attrs .iter() .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string())); + if let Res::Def(DefKind::Mod, id) = path.res; then { - let import_path = snippet(ecx, use_tree.span, "_"); - let mac_names = find_used_macros(ecx, &import_path); - let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition"; - let help = format!("use {}::<macro name>", import_path); - span_lint_and_sugg( - ecx, - MACRO_USE_IMPORT, - mac_attr.span, - msg, - // "remove the attribute and import the macro directly, try", - "", - help, - Applicability::HasPlaceholders, - ); - } - } - } + // println!("{:#?}", lcx.tcx.def_path_str(id)); + for kid in lcx.tcx.item_children(id).iter() { + // println!("{:#?}", kid); + if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { + let span = mac_attr.span.clone(); - fn check_expr(&mut self, ecx: &EarlyContext<'_>, expr: &ast::Expr) { - if in_macro(expr.span) { - let name = snippet(ecx, ecx.sess.source_map().span_until_char(expr.span.source_callsite(), '!'), "_"); - if let Some(callee) = expr.span.source_callee() { - if self.collected.insert(callee.def_site) { - println!("EXPR {:#?}", name); + // println!("{:#?}", lcx.tcx.def_path_str(mac_id)); + + self.imports.push((lcx.tcx.def_path_str(mac_id), span)); + } + } + } else { + if in_macro(item.span) { + let call_site = item.span.source_callsite(); + let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + if let Some(callee) = item.span.source_callee() { + if !self.collected.contains_key(&call_site) { + let mac = MacroRefData::new(name.to_string(), callee.def_site, lcx); + self.mac_refs.push((call_site, mac.clone())); + self.collected.insert(call_site, mac); + } + } } } } } - fn check_stmt(&mut self, ecx: &EarlyContext<'_>, stmt: &ast::Stmt) { - if in_macro(stmt.span) { - let name = snippet(ecx, ecx.sess.source_map().span_until_char(stmt.span.source_callsite(), '!'), "_"); - if let Some(callee) = stmt.span.source_callee() { - println!("EXPR {:#?}", name); + fn check_attribute(&mut self, lcx: &LateContext<'_, '_>, attr: &ast::Attribute) { + if in_macro(attr.span) { + let call_site = attr.span.source_callsite(); + let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + if let Some(callee) = attr.span.source_callee() { + if !self.collected.contains_key(&call_site) { + println!("{:?}\n{:#?}", call_site, attr); + + let name = if name.contains("::") { + name.split("::").last().unwrap().to_string() + } else { + name.to_string() + }; + + let mac = MacroRefData::new(name, callee.def_site, lcx); + self.mac_refs.push((call_site, mac.clone())); + self.collected.insert(call_site, mac); + } } } } - fn check_pat(&mut self, ecx: &EarlyContext<'_>, pat: &ast::Pat) { - if in_macro(pat.span) { - let name = snippet(ecx, ecx.sess.source_map().span_until_char(pat.span.source_callsite(), '!'), "_"); - if let Some(callee) = pat.span.source_callee() { - println!("EXPR {:#?}", name); + fn check_expr(&mut self, lcx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { + if in_macro(expr.span) { + let call_site = expr.span.source_callsite(); + let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + if let Some(callee) = expr.span.source_callee() { + if !self.collected.contains_key(&call_site) { + let name = if name.contains("::") { + name.split("::").last().unwrap().to_string() + } else { + name.to_string() + }; + + let mac = MacroRefData::new(name, callee.def_site, lcx); + self.mac_refs.push((call_site, mac.clone())); + self.collected.insert(call_site, mac); + } } } } + fn check_stmt(&mut self, lcx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>) { + if in_macro(stmt.span) { + let call_site = stmt.span.source_callsite(); + let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + if let Some(callee) = stmt.span.source_callee() { + if !self.collected.contains_key(&call_site) { + let name = if name.contains("::") { + name.split("::").last().unwrap().to_string() + } else { + name.to_string() + }; + + let mac = MacroRefData::new(name, callee.def_site, lcx); + self.mac_refs.push((call_site, mac.clone())); + self.collected.insert(call_site, mac); + } + } + } + } + fn check_pat(&mut self, lcx: &LateContext<'_, '_>, pat: &hir::Pat<'_>) { + if in_macro(pat.span) { + let call_site = pat.span.source_callsite(); + let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + if let Some(callee) = pat.span.source_callee() { + if !self.collected.contains_key(&call_site) { + let mac = MacroRefData::new(name.to_string(), callee.def_site, lcx); + self.mac_refs.push((call_site, mac.clone())); + self.collected.insert(call_site, mac); + } + } + } + } + fn check_ty(&mut self, lcx: &LateContext<'_, '_>, ty: &hir::Ty<'_>) { + if in_macro(ty.span) { + let call_site = ty.span.source_callsite(); + let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + if let Some(callee) = ty.span.source_callee() { + if !self.collected.contains_key(&call_site) { + let mac = MacroRefData::new(name.to_string(), callee.def_site, lcx); + self.mac_refs.push((call_site, mac.clone())); + self.collected.insert(call_site, mac); + } + } + } + } + + fn check_crate_post(&mut self, lcx: &LateContext<'_, '_>, _krate: &hir::Crate<'_>) { + for (import, span) in self.imports.iter() { + let matched = self + .mac_refs + .iter() + .find(|(_span, mac)| import.ends_with(&mac.name)) + .is_some(); + + if matched { + self.mac_refs.retain(|(_span, mac)| !import.ends_with(&mac.name)); + let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition"; + let help = format!("use {}", import); + span_lint_and_sugg( + lcx, + MACRO_USE_IMPORTS, + *span, + msg, + "remove the attribute and import the macro directly, try", + help, + Applicability::HasPlaceholders, + ) + } + } + if !self.mac_refs.is_empty() { + // TODO if not empty we found one we could not make a suggestion for + // such as std::prelude::v1 or something else I haven't thought of. + // println!("{:#?}", self.mac_refs); + } + } } -fn find_used_macros(ecx: &EarlyContext<'_>, path: &str) { - for it in ecx.krate.module.items.iter() { - if in_macro(it.span) { - // println!("{:#?}", it) - } +const PRELUDE: &[&str] = &[ + "marker", "ops", "convert", "iter", "option", "result", "borrow", "boxed", "string", "vec", "macros", +]; + +/// This is somewhat of a fallback for imports from `std::prelude` because they +/// are not recognized by `LateLintPass::check_item` `lcx.tcx.item_children(id)` +fn make_path(mac: &MacroRefData, use_path: &str) -> String { + let segs = mac.path.split("::").filter(|s| *s != "").collect::<Vec<_>>(); + + if segs.starts_with(&["std"]) && PRELUDE.iter().any(|m| segs.contains(m)) { + return format!( + "std::prelude::{} is imported by default, remove `use` statement", + mac.name + ); } - for x in ecx.sess.imported_macro_spans.borrow().iter() { - // println!("{:?}", x); + + if use_path.split("::").count() == 1 { + return format!("{}::{}", use_path, mac.name); } + + mac.path.clone() } diff --git a/macro_use_import b/macro_use_import deleted file mode 100755 index 61d3a827f1f77ecf6d8dd69590a42eb2cfb26354..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2816064 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⩔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	(UOi+EP#LB+>D>qS+b9*V>({78Nf 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%0AhSlC;CgebPN>=q(i7ypxj=jKxsZ23rEl< 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%0D9Ndr`=Uzm& z=1myN->{IpvfhG$;llm1Mv~k<?y91C88TFpkhVLzFUo5G#8R|0X|C2%N+5{CATqC( zCvIiR>>BI-AUOj(U(**Y(ACFS7?omvYAlUE7w@v2(ZmCq5_jJ(u~Mv+!#FD0wE=d6 zy$n?ANuet}#^*u(k^(sSb_BCGj@fd$u>~-bu21{g9n6#tL{^_K12Z$7uKPns8`cYE zXLZ1=GAaU`4>Mw%+#8NqI1j9U79(T%Z-C+~<gadCfDXAY47_bY{ga8}F3jgilo&+d z&A11Tq0r_)G^dJk+nHwsVzF1-j7<^g(=KTh|BPZ$kHPN861|?qQ^md76LV8~G#dD$ z5x|n}w0<?-A3AnlT@ekkbV~<m24CEQXpkrUAXgO}WO+2mxm!BOiyGv@Xpr0eAa@rW z<W&Yiz|LT7-yCej6u1454%1AI5S&a+O6%s)uH6)%vzWu+hZ8^QU!bdtOW~w4g_x7; z8RXZ}0M0}&GgM^vA+no-Hi~TH*GH6e$?`+lS4IZ|R@iA=(x=_WF~v6U{-~=nqplWj zx~sbjcJ*}B)thKeL@Liu))ZLQx~SRGu-Ov@o1M}>T;u%dKFr}M=7r~I$$AuLWU5Hb zwJ~OwR2C36u82N9i&|jjSG{Ut4e}6%eKdKa(8<mq<jhie`as!@*04>5fwD#q7xqUV z_ViIrjz9FjdJU_16u1}ej3&}PslY^ra<1@1VIg#J_vDIXxq7n9u5PEzpVB>=(sHKK z7m7|!d(Q~m-52LrJ>BR8pNl5A`rkOg7d64lI#2KgO;AraI>8T^AW~(<EzURJ4u8m> zICp+oQF2(Yf5x4NZ;YhRlP1*`K#0aNNuOhqdtd>Wb5t##?Csv~6UOGp4#WaFv;%wt z%{GJmF;=o-vzWEp6Wt0&w?v~}_LYzNSofpe5siA`S3c^K-H&=ddr_FKtzte?*y$tj z+an^~XjwBRCeMhJg?UC}+w}>bm{hrx1Q;6?SG%RYZbKsRqp%ogtnb+aLR46FWEWKE zzPHc1>FxCaLcuT{Kx~}#yvd~l*fHO6_BLWOa#>wtZ|>&JRvF^l(`7;bWkK12LHghz zIN8(NSj&ejzGI$IzdtlvT-7_+2Sf}T>T0_Ey(0vCX<dzHEMgt5vJRI~A&OKNKMsbb zUk%a+@ZX6+`bXSlBL;bkRqUGv3pfoIAA8f%?VFkA<yz>Qb8sX6rf9<7QP)m&?J%~3 z++(iF^{-88-Y@q+k2wfp&{)@y7%I*vHsrY}?Zg_p7v3RmWS}W+Kb+bi&G(!nX$P<m z6Y4zPI>SY=z=E!~K2};EPpFUa)J18t4_@q{a*ZYKk?9TUiDyIsU7LW53exX-+7z3P z_dp@I+=BU{zVH%oO9?3&fGen{kc+0bCU^8#7r}98#PFF!JLu-Zle>q}0rKodwEIJR z8iz;7!I6x|rQt=;8$R%B3in<@?7_~i4Wk+gaCav*pbBzX;5N?D^PkfBD7T153YUA- z=d**e@Rt+>U3X}1B5`!8Hb7jTRQMh>c(7ZcY;Byxe_V7QPE`hYyXrz~LJS;F8)QQV z^Vl1?y%atTuXg)pPE^(M3I)7-0>Os3zhH08J{jzk_}W0zcU=+|y{yu9xeM?y&+baV z@Hyc1N@01B_|+iK|Hh^ylc<hvstc06AHK2l)v<3br7lz9Z?3R62YPi>?3+cr$q|p( zn-$oJ5W+I<v5BBL$bVf_qd3;=C9BEQKRL~zx2SNhPp-GdC#S;tld;Ad=(8f&I^#Y- zZ#|72B!<sW?IX&<4kmzPE*EGTcL{U}6(n9za{RuC&;Ie>?Xh;c1!jvWk)fg&DxU(h zX*s48gljau6Pp<zO%4Wc7+g%rqm3s)KoZ`Zj1jTK?~3TSs;E8qTKZfLi{W~TB7_!& z)J@#pI0MtIc4}DBo#R`WSC}oq^LsJKJ#Mw0s7(}xHN;;2lhq<^k=&&S|7)uyfEzv9 zE*T6T&QuvKz8o`Rc&aVy+2GV~f*of;LUd4J@gE@%Pv>LZxY1*c$j`y1hj78Z2L`dz z4a-=i6OO-I4~xXt5w}fy7vqPH?*}A?2#;@KL>D|iA0q(s&A9oK$cl*v5uZR^FjrO} zPp+Pbq`Av1TpN^z0YUSj=}pRxP)#BMtrPk3X6|`RjsClZX;ca4)wU?e4fihcwB!Z# zX<plMDf!G5Yiq-AHXyt1h$w3bH`mru_ZWLxaite_VjFN9bF~e)y9Y^fHnIUbqF9<o zqTa!B_cQ@{AMIEZ6QFqK52}USw=>e#gm)Gr>o2dZQ4IlvWx|VtzVq-&+6OSGz@!_< zlQMTiB^n$=_e#IA2bJAOOY207$3T2;WwXlM;V5bR2N*(7_9kiySh(Sk+~+u;hqgKy z@3zP`CTqDYgsRP*cJ~lY{UCZc>B(*^VX~plz`c98dhX{UGu~KhK09Gv#JQ#;DTL)N zn<Rx)v3n5*CH%?U<+$9+zKK*rA{h*2xSf{>kM|HhC*9LMYOJ$Ml;DEf#C=HO{vFlw z1rVJ8n!8oJ<Mudw-;Kjpu22SF`4Q*fJA5<XYaeuiudHH`2f>$xuQ#=Jz!z;q2Y{uB z3{wwv2Joy9z!t**fPK@A1Gs*(0bCyexH4HPd~StZ8Vm3#&((vJKAwH}fyFE8A=yo1 z&-S6-y7)%IFJQmO^5MQ&HO78d)!NTJ`6+T*gS%{Rs7{FEmBw!<CzR(mO5K<m(KNT6 z4W$%{zpkJ}YhO}OrpE+*XYpayJyn#JH+hMBU<N$LT6m69b5Vp?l|4+##5%OpMsnUL zuHY5%D7ARSjljLExFU4~-DTC?_<y;(&pWykh`29$P)KGLb7;`yp$57>MAK>*9)x|v z*uS)!Nl_{MMR3^>5FfJST?N0>wE0fyXodF|)xpl4P?V@C;={qXs#o#82bx}=u1LRk z#L(N+%PTf6#Xka)iJRMwqBf5~3`MjDH}HG7I~2E6`dnID&yVn3%5CSX&yXst6=W}V z+i}ulKQ^J@E&K*#LB6T3-hMyOLl$Hjg+}JEk&-_63OIIJFRVk3m-eC^y1H3973K%| zd^5vt6{paGrSUrN;g-}=EnO7+iDHVSr`$F2ps~DR8;XT&EavoD9PGwuv1d6JAPw`Q z{q2dn_9*Ce^gv)ZZ9ES~nxBzMyW9<a4-{2J<7s8A@?R+nblCCysgVy}N6(!{66m&f zPtxOPcLOSRX5`+R-X1+gSB{3A`|Tnnym-~LYgqc<?5P<fb}CgGr5%cbU#T1{e>d`f zyD}m1e~V>A+EK{0Le%fpT1|_UUr3UE9=q$)SO{+H{B(()s%@xGX~u_~3>irb%_kJq zgRZFl$sETe{6uj}V!JLk`6*cFlbOB8c8DnZMp~8?yy_i=cE+yMr?52l<DHu`DfF(7 zy*|<Ei}d#eO=skbwnN4FVe4<_X6Vh<oGhNmy@p>mx7|rNv<bcbPKHCz=Is@1jaXNW zV?=-VSP5r-FLrkYel|03Wq58<1$~se_Y)1l&&l*e=+Y<TfFW5fe(H$^^xV@42ipq3 zyNAeyuouI9f=q%nkK!yN1d-<w^`5(r&2f80l5ESETe}bY*`@!|pKBQr^w|+(=<ZaM zw0T@ZJ(L+t^a+HD;Ba5)G1d_lM7%jN?#g~7bahLQQ*-hMPX{x;XO8T5B3_m3qDF2Z zBdJYQ)P^C7381X7wLb{%Yw3TRC|C?~_hqymszVwm0{7Ackl=PQ3nxMLLTkFWM>v<u z`ay3xCUZT0e;Vk++(1>~K(*mOHQ_*P)4U0d$!!JQXA>Cef&sIPj$eiOi3}LqGCd`- z`x#{KuSn89BVDpi`1}uCR0#-mmnxS11lF*vo?e#V-X2QMbY@fnrwA-l?heG~l06M1 z^ZJp5HV2Z9nKp$WiDudvBsNo_2=wG(BwSreVn{tt$!Uyont4=tX9_1WM3yi;8QiF{ zlg$v0JRHGuW>G#O{~a~OPMKHeG?dfZKs}-9Q-nDc-m0SHOvE|2ZgTzJLGf&J*nVhQ z6%XAFIPr*HPt%R>o>7e9Sg(DE5BeN~7H7uVr+47$!>4!g=}>&Xp}#O(%lyOpd6*r2 zqDdI%r|aQ2j8&{h++qs2BlG}W&Yf1{-gFhoKWNN(id31vaj|nTo0?oDq7)~@)_kWq z^MtCI_^TFP<&;_RSC8;2OHCjaxMUoqUCm|{Z}PM?DZ|8tvgB)Ctd6(9Nr?Ujde4ja zt94=j6=Q>)(!;!T7H{!k)cp#&|E-s^>tib;5mHXhj=y=Fg9A;<d>&GyA7~xqc}#v= zU>hXoE6TwAWyx*HAF#KdpkfmRySxr2$dfSILC~s`Ki)Ta07qjj_p1CxFRE)v9>7M_ zC+mycPnEv*1Cc7X0Y0L>NQ2zKM|$!Q(Jy*p4-ODY&MD%w@+j?o9_~|o&R;O+ABf66 zO=sU`hA+T=g8^<0=QE_bHOXRTvr636Ik>r*w1YWN{5V$Ln>p!1<|QRH9Kma$T+&jt zl9tAXy>N0(Q2yfpc8!WJ#h9tN$iJC79IJAb`v{Kc2b$$$4i-*C^kJea58(3)j<0uf z$*J;VW^@7}ytFb001b3jpDNn0>PyIbUMa`hb1-P+4O;3hWzcV?YJ$>w#;8bsU(|w1 zO~tU9hTU&N<Ne~AqO~yq)s1Lc?B1GQZ!5YPPbb!pbvF=8BDcd8<=O%sG#{!d^mCWv zr>H5O!`TFi?ju|QzVBY023h$XOT%psmZ{@G1UYMaJ9Ne%egaO8^h#zHBpvm-#QD0K zO%8@<Abe_H3Lgdo#RMp&f$i&qMd?<5?&AA-uGi&)Xbr)>?r_Bga^s}P+wJY^2jml` znH*aotUIWl$*X)l8wE#D%@{(z);Ri6VB4_l{vMF#8_2Kar!uD~wEM>TK9TVAewqFT zo|~ps`hyy4aZO%}a|*V&E~%RcEz`Q*8q3fEIQ6a#`t9UP2*f&Up~KwKjJ;8cxo9$f zkB0g|J}AzGT$V?=_gS$6e+M8Hy)r$Wy*eo3dgdgGf*mtTy3gK&J#4W1oSRC&>nB#) z_TGY`st;gY(WCtud$1fvxD391p9Uk&e<fj0nLCw=DCNqO+AG~U3nqkwt%0u3Z)wLz zaw{!Ea~*(cEl267CtU^DGh65S1_!TmFgbY}xi|N47oajY80ExUll^&q4rJD}?k}!E zLBt8?-XtGiz))1)-R3%*LmOKi;Hrc-WjGj$U>uMASw9nroyoYHYt7zLWd(cxqdqyS zDA)^~c9V5>^^7)M4}|l891}>h%%oFpegAsiYSxWZ$@2u)K=|K}gyy+fPJ7%x<6h{) zM|8=-zLW?YDCS9WbNQHyjya#~+U!g|(+Bn@YGuj$Pv(eKGWWBI4B|zZ`v?anhEzVs zt(647*p*o3$S_LqX$V3=c9M@v3GPCOInFwKsZX0aOuMU(v!W2o2#hZ`L$1x_DFSS} zyS&9}-ZHt-vzqDzjX5E!o_ayD+;#Y3S>JonC-nMdcq_eqs&8wjP9vTQwqxFe7JX#U zXw};A+R);3$a9O!QEg~Y9<R)I|JKD}PT8E*bq_LqU7zMk(F)xHm|MT84SJwWZ4X8r z6%2lsLxC8uw?VCeQ^MPTJTcOsO=&~+o~CHfe5QUDkUPzBcfDt?LS8=Qu9$Ay3pB5A zhy%|}BRLz+Oc6U1rvcBnJknyX?tDB%;Foxn&72*K<hYna_UYVD%&Ncp;5eaiqhc~| z#wn0z2mlI{I1^0TUl=~jBeNb?23w7`gL*naX?aW-Uk!EdhH_0?Z$q2D?ytv-qb(+Y zu*TrtJ=0(0Aw+nZ9nUkT!LW*X6IfnzwPBLcM->)0tH@njL@Hk5@2DgX5d$8x1)ERF z0j=3{8eJ$c#KCj5QQi)vb~2x|uH=?M6v(*0aJC9%w5~`(Bgiq?XzceB<OJ!$e(UPn z-pj%v8xtGiMA8RsD=uaTcqlPJ@wD~omdV3_sVK@5J*pF1iBXMxd13fv`g;2gg0lgF zQv$P56%5eryUZqcR$b^s68rd?XxQT!b_6#-qcuLiE*%!&jJ3YcS_20{j=KZHV0XAl zJdn{QKcS9=+(rRz$tRx?#L*3av{2zb*p5Kk2vhVcDHOszi_NBu*>Fu|P$mzTi)}R= z&QPv(@_BC?>`hsAWXIiuVjL#8Q0&zgsL!?yM!H$GNDR9KKRDbLOO}5FZ*4^Z=)M^Z za(%+brJdVT%d_tJ8dCpr^+^JgJ@8-DSm87}kM$c`r`?U{z2QN$n}04e+=ghlt7B_= zBwW*a)>JI{ry}?PaZ5tFrHM){&OM2)Ol$jK9Hxf6wdoX;xjz;f?2~A)%UN3zn)L!w zo%(vbmj@xk`8DpVzTuSb#aO}M9-60RyN;+8;_T&D_+Nzvoy~1&h<<UMd@F_On1Mr7 zKg}k4a3M55E&5Isk4Gf-Eu$8$0pP_R=@xGXiDAce)*f74M0v6tvdXT+@DkqrnQaB* zg_3i-M@iFP6*{wzM^k!DnRte}g%pthA?6W4Y3Ft|l-MH4ViS8Wn%JuppXp{|mUmvc zM1T}fCvS9q_f@|851pU-Lj=!tK1~gt)Ap)2&t=CZ@fnk_vqP2;+wwfL7E0$Mbl1a^ za#eO@Qf?(8wXkqcAq;u3rw!MsQc0%<Z0}_&!<UJoE@TVt+RxwuW}u_-I!wEeuLZ)b z0|xS?$UiTP=on`oQyqLbbvR8njgOkgOzx#{9{YrL;20#%iRN)i(U+nkF8~Rhw0mb1 z!upG&QR<7n3NrEvzzq-C@`B^dkH-6`NB*idLPuVJ2^ILSf`REuNAy;!`&+@$7DuDC z_wa<|EVApXv&%d7l0D{ZYyly8g^df>cum1kuV+-FB$v#HQ-oKG3Q~kOqANa3Hy1;L zc3$RGI<Yq&F$|sn8FxFD{-nDnftjC7Q{K{lVoc7e3{m<C>=%*d!FX6Ng-GMjURj$w zk?%43)z*5IalDWFP-oc5d?2qAW2@GtD`3U=820AD+FG>ZKsge~Rb(Oe%Fpej*xb-X z&yhaO9fNF<y~czlVi0*&Dm&%RIDuF8tk)i$OyWWw_aRjYwUv8P7;6#w3*9<yo2ukV zD9{~NbA50o;oN-i03m+iJgW31THo5Xl>1ea8Z+673QvIoc&g#6LZ*{&SVXxDMGjja zAOk)QdaBY_GLrDNHJ3@)#ujA761P)R(DNs}HS<l%9UNA9k#+U-I{48GWl(y|N<m8r z5NKM`TVe9We9aXZ;PKs>a{r?kMF_{)B%o7>1W1Z2ajA}O)}48n95M<Tmk$dLM&C}k z3+jrv2ZmH8dEjpPlYD=&m<q#aym|N})A=fLKKd~0t=vkK{kxF}(7SxRjss_Cjpn;d zwIVcqtmxkSet>`x{QTV8u*8aM{2xWOXWi?G7L&Rcph^y~1oUo__?#}co>nHC6||?+ z3zE2{LVJ~rf?l~XQvC15z4-ac1in?34`}L5b#0P8BnQ?f28l4I@|j&60&Qc+4c<F? z`OfNa*S<}XhfI1~A}xBs-7&eA1b`RA$w+6R#7Y65n>i>$F@WBW301$FkyGSL(=JV3 ziY=QvLuZJx6&Scs72Je<Q{Vp`rnelw=hD=exxo(e$f%V}j2^-Z3NHpdQ`Iooq;gG> z!&z2y^L6HO?7{Y<@L@F-GW7%hoE6WMlbHHa1mFB;Yw~1@#Jk^cP&9`%2qc=+126(e zH!9!}^g73cvhP-L&I<M<L~G)6fcJinW{=edyeC8WaC#{TFZL(vRu;9>G)>>QYpn5S zQjPbG8n2>pHbZ&Nl0*I6_O0Rrg2J>*S7YDUj@l*YOx4-_$p$<%+IWuxLi5zb{#0uM z1V0sizr(w%(!VtZ+nj2cj|<Z_?!lA<j=rg%*j}SgL{NM~2B`BUQe6}gDWx?JIV2c3 z7FmuZy)wCx4p9)yV`qlB$(6~UAn3o=3q@SHY|T0W^+ERXp!_h#duckNMkAqXxa57( zPi_)~m|!IOsk*wlrh<>*T~0&+*K==nt<rtWPW;pljN8oaK^e&k|3L=xJ=ODT@J{lj zxBxy3W8NG5EJ^84MefwlR}Xg%zJYixBOR2h{-V-4{RG?h6-W4dcbB1rghaR(@U`jb z1_>iABLsL=CTEk4w0Ee5irr2%bj~OE<aGWZNRl>m4(^9N32aPa0YdfrPRDWp#A}mV zG&;yhiKwVA_eOy>O0$4hP}2Rf1}KuQ4w$&lsk8zAooK<(dc5~8SwsSipYm|c@yOs# z$sXLc4Mui}e-?}tS^ZPN_=H}f-+MsWD^Q%JU7Nia?w0gaR!7k+h}@}|kJa7#N2x4< zIekn}Hi&vc!po@iI@<jy8n-q#E~A_WQKECO3?5g#F9t7;fof5ko_77+gCvjHiBmhA zekt-R)!Jx!J49)cie3IH${Y%Ix|~Dx+k9MPOIN4S650xbzWSQnh5qZ@Ts+!ZQ-n7_ zp`K2isDNpkoOFg-x;}`O-V*dBK`pEF%a!+twXN#35aDGv3(2}Hlbs!87jg8;-5n(0 zH3VOXD4P<dzSyII9Ez9(O7X!6tz(a2_7Kgv)<DEO=hZ=VjFCknF0k=z)wIN(klx^1 z>VrBB9n@szb0IZ(2m(=@dDjz%11f1;?Ea&Y1iQEs$dXU$v$4T<#wPy=Ha*vaY%JE| z+B&?kkVEkdhD$_xrgTr%Q96)k%y=~4Gu=I#g1sTNDkIkHuY<qatkY!nuTh@<a`!hl zkQB^41%EK0QLOs_d2ocHxG33W&xaHJ1g7PbqTqlG9~XHwv)*4Dz5ko(^wZx;j&jdu z8vS}c9fxB>ilcfHxL@*0&~q=l{GLy?hc2v&W^2d)*TOX0HzQ8L5y$!i<DT4|<C^eb zR5T+l6ojpQN1*BN?mv!|TnAsUhv<kZ8R`ye=Uz`CD%?vQV>aem)Hj3B3iE@%8&Ff~ z@2yDOr~6`UkHlzowiQ=_Wn6YdcWA25XX+8ybjP5v8JAm{g=0L8naGD@H1lbZYd*dW z8i@}nL#*KzHuK}DF@9}O7#g%Zi(yH#ydJ8}>^{PUTX9d?e>^WfoZ6}-&OwJps;ZtX z$y1AhUGRlTw}Su_JnO54DqMzGDt9`Bf(LHHga)-slAVGV?p@R({QRyv0~ea2vA#r4 zd^TH$vzgnMO|xjM$H@%|?NI=h%}Vr1p;_UqQ0y|W{FUf=JNLI*Z0OAB4=vm%+q5zp z-Y(B1cK6%0Zjv62aA)_Fqf^#3O>UFN`hfHb-?_Y_P_a-ILEWWYD~iyd42#@g@?Dpq zLr%TIcU<Ph&1$f<yQx-6{Qqu^)?dqGH;*ujU$aj>`v01#KIcrezQ~fAO)yHk=Q7Ya zabX?r1-kQq6zy2*yW^UrxWogYSK>#e`6qErXDfIOP2{k^`E~!r*_Up(dkv>`-OnwD zNrN#XlQmv0__%DIi_x!fZtDZ(XLf_#%f}*dNv%4sm$x?L4{DHkc|wylXzZ1nR>$Q1 z3h%}}SADQRxOAqTDzL)HCBs(OvZV{G?^s`JLC#*ua>d!#XkEw<`y%`((V8b!*OA*) zjz8l1Duwg>O-|jE+g@qN`nk#6$bZl^O$B?rGq`f?NqV^VGuS(y-zD}6t953dq%x5Y z^O}lS1F>mEneX~Hd+5`bLb5lkD0!OviMV-dIEDPPGyH7g>!kri{z!K6*cLTN<L)OF zdIP}|{OpISqmtMCx%Ja6oM=K(l{y{{9)ffv+`wI`S<s)7gDt@hW4XL_G4uL~flXX( zA4>=4PC~2Yc^U*Wch8|}Qsx@U#RFyCGo)rVuB*bhu8?cO9XJ0IrKyZQ>Ej;d6Al2J z6RGEsv+SD=&dHBb;FG-^%2XJhT4u;s`OH)I-{dh<1aQC`!c2*EYR~l~*2ywbiQ5WU zC26Ra)K$9Yqz^kX_@+Co8g{ZqFohC*I=%iHsC1JcOZiK@!35b>Aj`{pREc-_j0XOo z+9a@?MZf*r3DX*kJHAN@JZ(+NmEw|T!tu#CZK-GM?^Q<mZ%Qz%J$YbyqSE9S52cp! z`Vg?Z-Pzq*BXbt@zfupU+!1uVhi>5!6=_LRhCd#CdN|ngtq9ojH$#n2I}vNJTNwED z5xD_<T!(`DuEn$z3+{`3vnL3b0hib0A#5}t^>PqwaAZG|gh^1j!EQZ^lViXK12&O* zsi0VFLejr0tC)mw=xsc!m=|>0y(_@?^UrY@U}iS%*o%{m`3N0(^roRLJioCwQ}a9P z7XmRVO%Qu|H&BE-&A7R{kSKGioAXOCDWC2v4hthOiIAs)$6x#cS!pzD80@G95XGkd zkp~u=ZYrGx#SO{d0{x|v+N|LMOn6btjYP3e4R&?+*Am8_LV3cCLFLCD^{M)9gjQw~ zxZgJ+HX`_kfgNEsq}Z}nM9VsT7m&7NS#r}NQ!f<}I7rVTu=v$+;g4pSN6R8ml^iTB z?fH1z{F38(3oe*L*6=Ki4xrK=y*b?!Ry92QCYl1F-!FN6JC$Gt;tgli=FCX0ll<7u zdxV5Xl+>KJ?(}kQdK2O-$G8McZt0HvLO$u#9e5`K4r!!z5?^#@1<b*r%usRyGrau} zskRXZE6p=+u<r2<LAz3ax9~^0UdhXA^q1zx_*YM<)Y{xzJ!@p}B<*Y!FUs7^Iwj+< zmt7WFuedzGjpqOZ!0ff~0DVAjbye(cJ|0orou5FWc2ulR4&m1m<W*zdx6Z(m3NIZL zNJ`PG1R>!Rl};vXsAd)Z`FoJuLBV(2V_9(y@N?YUg8GM~?%lzyMjeG0B_~|(&LxyV zD_A@Yh{~U09!atW)9n3;axQR-6)qlc=lw3`71z=(>n@qrb||B5<=)DO@g0tmg!Z^E zAJ>@tjyts{oCofyIBDCDHol>not0{u$tpPq++b8cj_^Bo5`t||F)B-g_4Y!q>Szh> z6mmI6Q~Hj3peGi^a(9!t5b381<@t%RTZ06@1=RCnnA`f3lUL;>`rx#NZb`z>HAe~e z5QG~Y*3rF#uV28L@8|E`!Quth<TS4%ISua1ToYGM;ZP|P@81w_h2(>@+_&NL-RDQv zc#Y^qa@`;7?l0oV?C<VGw9tfCJ7%QokIa5m$^AcM<OAF*8SI$?{CB*1Z~f#}o_`ao zn-apP^=YUu)Zmp&3vbdmx<X&ntKY%Zt|{C>xzzYBn|zOQW8aCyj4(**^3~~Tp)O~m zi}PJ#;MMm3mHdOdJMt0f>4M@W8|beSn5I++4d`FJ94%b!>uxq3QPwTStwsv{*0Rdv ze}W6I)p!~DMUcj~1KPgXf07g5e|$c-R@Y|;oYq}_yZAFr<kKLUh)2G6dR7D#8=ycW z$xWpX)F18^a@ujGAAr@>QXj?dHe9NX2lzjo3tOFCg0LR0iX6!^$l|{WXLdNU0|APr z|E3b-FsrJhpOqRbJ9r3!5n=-bg8VsuC2P}km@F!QgyHZY_aVxPGB~2Ej;ay*J^?C& zdZ2Gp@?fc!(cd-AXycD+{%_HOmD!{wyhi9`Dpi5!agR{#BrG}H#^um#Q4n2pqcz|( zA;kT`VZbo|IN`lqKn^oBuChwyMuEPNcCoKpPI^bd_+i+t!NK?4O_O1L#st~P@O`8Y zhG3ovT}y{KcjSUDxpdBy+V2I~*-~4(hryUZ=te#(l~9*;ZO3q&ZkeW|z}NRs0!1?* zgYxUh%sNXe$tT!}ZfVnuZW#qaU+PgC%9c;D2=LN@cE4^2_B_I7eJ$AS&w$4iPua>K z>aB(!pHJnI0zWDMZ-xF4DdN&w#wvPKDpz_FSj5Fig}YG}n^(8aFuLVd<3DM14+79Z z1RJy}mA`89w4NUyVb&URXz){oJhOgG5tAXDgW>wmz_Y)vxtFHg<I`)f?ANo(OVJ?- zyWiFTc4S2i?5yjv9o&hyG4fvIdw16i()w1~d$nq$(P(8Zs-@9Ns6ls)vhHolHC#Y_ z=?Kfyj+6-pQx;hRL0y~J5uFT>Fds_Vx_#i@djXyAi|TUsy*r6R_Gyt8aL|{ZKmM!C z-_YiS62&|i+Spu9$LQftDNyJ*q}n*{*v%(EM%_**(~XTT;K(>3$kDj?nHNF4V6Z2I zEq@ZV_`W*<t3}q4a<lgXIea-U4_~g@QhYfT(R#l_QN2a@QXk>Vo5UnX__6_fIU`Ze z=3X<+-!A7-mKwx@SYsoR-`HR`3xwM1SHR^wT!T7bB^IKWd#A6@x6FBDA>XFbL~BqP z?&izd&2^B>-Q7d+?(KLioI&^M<IHY1r#f#uQI5`gv(aZ8-5ZF5J5Z5K>NHNrqbo`m zcQ4maY6ngPhu@&{EmWom1sD#84-ShgMpDB(fId{eZ^ErhEc9Wzrng3WcLUnoRC;Fm zwsa#m`X9je^g??v33i;HiOM0-&s3taG~JTEpAn(cuk?p;N^C7T@bs9nk9>+}NaCpE zIa-KAyy(_5Um_s^A%r>OR`+X3_T&&QIl49|8=L$S6MPv&NW1^TChP%EdI4Pi$e`4r zfNMzZfPv&Lf=tQTyW2HrCJ`?hX~l7!CE3_Cd1uuj5`!hDW7_B`z+levq^Xf)|Mo=5 zyhk9&G?K{YCpzEHZv}2iQ`hi^1_6;cd6LIld|d=Wozm;M)zsr!A~kk^^Fze9Kx`cU zA)&mOhZ3&y(B<Ak)q@^_d?97lnFg2PRth>Pb$9fu;&+j|=V;#kpLA)WLJ<8u(7HB~ z>`?0LE9>&zkd2)gt&*QfcPm^r<jcvtMy@2H@^K|b=OT(pCdTCNbv96E{CwA7KhS?D ze*e{c$OJbK!pCc7{9dgwak_LZxSHVhTGN)D!BAe!*Ac2?vf14v8pah3kdqTRR14Bq znY$5v-@ZiDtyO$r`FCv^Gts#-BDya>tqqtd1<8dIYTdK^ttqNVx<+~xILLojA!1s> ztwb#R9>?j6EoywA!=9f?>`-bL>Q*WgkLDPrdzxR}KsOo7=^gS)<SW!8gYc_7TzrEY z0)T2zmJNyE`rogH5;I9Hm`#Qph3tRa#bICckcFX5!*X}`lv;Bp){;qoEVESCebJV< z*KpSUJ;)}9px)TCS0Ggi1lw{QhanH<RH5Cw(3u@*EvC7jV{Am&{5?c?K3e--Mg45= zUS?+no(;Hq?aKi<gBme9-wVh(Ej8zsZrnDmg^g2>trVwVz#{w|gw_KoS<z@yUu#g+ zlM8#Ih$i?!fQBVEW$LN;8$^EBy@gYG7^28GQyg1=FUrOmZ4rvzo#2&z-3AmOCMPHO z@gb&lL(8v+Muc=e&3F&ZrRjoj^VC-A<;>T@tvnmG$gqqX+K@a`J|JXH3`*wFabs#s zG7VN<i9dfSqVjgB-F%Bxc`cY@-%6U5y2c`LY$RHs{EXsXULp5Jn%9>eV@XzVhtk&| z)mCcHV*gYlb=W;(WS8Udk4*(qoKS_NWLnkFNupuZHDfDjvj~QP9m}}$^>7()@*Pmk zxDQL%aE-i}k%zev)zP|Yqjk;Vb-{IYwAh?=S+sHfx`O0sV$qJK`=omYdZNSmCYfHt z+1M@eeQ2x&s2C7pzA0+{*OJz#`Ty?Z-S`HZ@2Y+c|L;sd&>P7y{LDDVdR_LZ{~KI# zz-<M-baKQ=bK2KW@&PO>2pEw!Pw0a~0CcO=lWUzJbLff#P(gad8YT9L&fr1oLgf7d z<OOpwt`RmC`<)KO7Yyo8OkW>fw+0swNdPz3K>)2$FzhgUaz6Q5)1b@iv`~c2+x^Un zj#3EfgeXSHa2jGe8?BJY)u*UdMrt-E)as-lZp}_qEe^j__KRZok3UCg*0*x!;p4AM z7&DAv$Y*`Ihob}54_ha*WRy9?_6dU@?$?xi%kj&R6%N;U+O>2~R&p&6u{KRs!s8bK z$;b*t$cymq`T%O^Cq-IifMv9Ww5<LqLY0LEOhCbxsqW^rzHxj4fIKl0yjE}%g~32= zw#IXg#(nHJJ{agMadHQ}<9BpWuubL=AWQIjupP$K)NCI%W{oZj8@awk=-{RIC!MY2 z{<CC@eR_K0TafERJoU2=daMueq&&QKKPajVuRtG2UV}2k0?Fwi?arHlCC@eEpswq( zd5UU@H6_2ro6m6p=tmZOImDE>n|pKdFCu9P&2)v<Y64WnnGR1@@-m)7M=Sg&mDsmb z_awZMj3<xKIopiSMQI0r(>Xeuev0zUm@<fOo)Ob}Rz1YLi?Q5M>!l;s-C`gV8la@X zxI6V%8l9^T4}*B0OYlnpF*f7KKG>+0rBZHacsn-4xbDwUc*7}Y+@pc4-%Hu_2H0;m z>-Z{v(ZriSz#UYcSt5TWcX5#wE7KWz6xa@Y4{EU#cMJI}!R9{3vjM0v`szOltRmH; zs>U&cAV`#;L{Ipa19>?hMLv>_cI0Fmzz5Qk=HBJ~8Ft5EW#^Y+Q2h59aW=oifOI@j zX&6sxR8+!X`Pg`0RpJE7qi)Ka69@N&PRt9@gsQ-bJ#~Lrw&##cLStqV476Ojq|aH2 z`IFHGxl0_XY%um-G>~CCyqm0@D5%V&v@3J-5r9ji&@tCBkP1@A3s`1e^pC8c7v<c* zc&BqvBh-Ukp`2{kt9`W2O5BAbo*#Y0c(d!8W20lqP`xq@HNd?|Wt0jgU_G8&=BuJs zqB&!L*<@<-)3yON9MNF2VhtQbByj7dqeZuK8{}R&!qdyH0HNoR?w`EwO|Gs=_~n{_ z1CHYDQMC1PzFOMfT=Jw11ld&E&!7j%Scnd*4?a<|jD#USmTE~^x4wrw3im{G%0lhU zfvdmPgGwZYv)|&wTeV%}LV!n7iNr+%3`?l^LtWng;<Ge3PerMedz`W}G-0eY1FKf~ zDEc^hT;z(>8A(x<ip?PUnVHY~yZ?u}_kgdey#M%f?{m-P<|dGkgoL3oRB#3aq-sN} zt*fC{t5$>kbs!R?1wp(Cdj;Gphyzz}3mOz_>j(~P9l<>V?iFz>#=Y?W{yfh)$vxpF zYO$~X|L^P7l6%f`p80*gd%QC@il6GB#9*1uVUdx8ee-&0*t~8FK2bfn!kX1(1o=L* zIv#*>W(=FvU9G<|OOpRHzP*jS!Xtv%cS!VM<onF(d=i+|bp(9%{bqH2lV(<z^Fymy zT|t(%sC!wPSzQI@0}n)*)k|eo@0V^?XHP+IwGqtfeQ}kxX7#s~cLcL~zmQqIMrL)1 z0hrZmty#S$FsoaT!Gv<T!CK?|oWkd*I2}^kKB{;<t^#)}u=D+Y`)1>Rl!jM2yV>Yz z)bgjl+16Wsb5zG+e`|AVR0da9*Q1CKIZO)0=SW}wYjVEv#NE-QKje;<;5Z7>gD#bq zl6iu>>G8x}x}j!qVWQxMXgBe;;gfBFs^Z=(nbMZ3u19%-{zzQUe`dq$XjU<Ery&`V zb2-aSmtDVsIKver%?1>cgl;CxImf5WS@5FS@E8jy0mQ>1vk=$3?Un(06?(2%Nh<w# znoKgiw|`kF5mJ8@3Hg(B@X};I({8BQJwdaZkYYtKt|!BJl388@hK%@9w7z(}#plfK zhbh=MSp|Z$yv8<htaTl5PYfH!Dcos|j{V`hk^PQzucdNRm!S`IZy6lNe`-3bKK7^c zXt03u^ZVHa+^z-S$%%K=N-r_QF_(4)!6$F?iHi)m5&=JVC7jHE(3Er%5MmMFb(}y_ zlKlG-xXC4ROZlVJ1+=L9exLX=`p|U`qHdV$XHU}mA;J4kT8CG*d^di7$bHA-uXO<_ zG$3?<a+7RF#t0O>IHJ}~64Kye1U0ss8P${}ez~Pziox72eV8?bb`%Tqu^ZY-SLbxK zVKNNz!PF)<%EG8$s5*yH9uHQC4;?U{G+%P`Il$5>ihghhp?0mac^`;}BTt$uA}Htr z<(mBjPhKodU|2jpYv*AUwlh#c1JuU(rZLs%<vir&E%tIwu(H@i<o)1Ho_Px`abhp} zC^0+Zm9&nh&+q~6sX4suF7Y<Y>|wcdQ3w}f1KQt(c}nif;i~ikGuzI7hlewo9*9D3 zc@$4*lyeR$zZ~uK{0I#Ae1(=+=#2Kz9Sp7SQXbg#wP4ZPY<W-?yFAJn)ON7E(H$?Z z&^!;zZP#ZGt`An2OMa+I)ROr1a`kQ?wTxZIWkisM7veOXnr**NeYm|bm@V<81+CMS z;?X9P!Q}?G<v!*Bl3qX@r7AQ3$XC1z4%Cy;OTR8N^Q8orprMbGP|q13o{YfGb_Z8j zuJ4SU*t7aW<-bbJUJ+2|J_MRL3{AlE&X^}vvr~L;kXuUH2<pauish~KTSW1P4rA5N zqIvVp8$s&3uxj2ihHt`A+sQxIz1bb)HGm9aUIWl7G4cVNqjTu<c66#mN5!@Qk|s9r zgpxH3@*i9<?~I`OhwbKvt&|Ih;%ee+YLybirYqx<?j-G!Yznm8Nz)ujN_QdAs?Wda zcP`!<{qWbO)4L<ezrm)yhlBA5{7=hxk7vwO>nHPX1ad39rj6uu!oEDL!S2LhFE#5D zXoFVrV+3N|j_c=gR{4nmSow;iS0RI6KQCVl+2vkIVzk}yEOUj-)XrkTQ7H3_YAz_} zB~!_8rDV_W!vu&}(igfwpt4th72U?)qnVIC<=Om>v!HR~%mTDfJ<Y+2`AUnAYj<~* zqUmV%U^%KP5$i{aozyJDImbXD2F;*RGv;4#9|(%Hq`J$OgA!@-THv0p+mZjJe>?7j z?ENaqCL9PyaF8M_gyYDTqDTgNQfJRY7O)HY8+mByyoN!_1ARct_c;9m3z*9+&HLwE zb!lPr<L**pyneiHAeMB@AYvxoCh1TPn&+kSRK-eLIHq;LnhFK8p)5yJ7WaxCVRf}` zre8(uU5c5L=86|lD~k=WU1x#VTIWkSB_JO<w>}cx6)dt`;)cI@BpU;f(m<gZ?AuV3 zeAbmeg!eWCm}JKg+RKoSie(g<_p9KprLJ3o3@!ZoQB}%uH0pKL*Zv8tAaPGo@^=cm z*qb%rzk+iE5co9=kvGH<;?Oky8ASX4v0p1XqyG%kP%J4u-Adut$oRIN9uI~l4TQH> z^5ocJab@q!5q^l_&qg@EbIY`l@{K>wCurO)X$DgE3HZydwBUFu-t?AgR5!`4_hr=j zf-K$a9YFA0w2}MYPwup}=A=1TYRk=6Q9m4CBdrNWddDsh=hpWKjL*T4bn5KJ*dV5e zl-U=1(xcV~LUwdrpF8dC2FQpo5zIV{+Xsl;V$5w(0&Hf>{K%_MY)4bP>^N`vdeqR- zw&tViW~(NBm0W&K!#~`Nt%&V}BB=qTM-HavQ*5foV)KHeC!2Q4!Z#^q+rVYxxBiB; zuwgI()QeI^*iV&hWyK67`2x$lf`O}p6#?Y%4UVAykhR!}xx}icBhTr+h32znlRux6 zO$4Rp!8ijTQ`Sa%1$2F5&;Uh^;5BL9An%KinWlm-mZ;6DIkNmKBsXnS)F#{95lwkL z=h3PdOk3l4S)J!0-}wVy!@&8;0gy(Lj3PqTqjl(cRvU;-2^#*B2>@J42qvsi8fRf) z8)9a?ePB{aKc0gq{%`zo6&z?W*5{B(3yO_%C~g;U9&DtAZsJHRCzWrG#`+H|A?$d$ z1i%hUEGF#BT6}TRf{_ySdYUv#{XcPEzDLyoVX5;>GfX4Nb6`E#<DqSe>64<e2<ox< zN}6dJkARTpngbj8vX@z|<Z1n@Tz7Bz-CgKsk@`osls?TjFC5oG>n`RC>NU15YQ0@l z48EUu2q&9`aKXl4$Clwj)_%k6gL;tw@j3yg8P_lfkqf44^Xd$Rfo&?^1+lcd=uQsK z`m+EgPDw;8OmKc*O$)O2hvxDX$DEri^s=j*(p4{Ci9~Ey<|G@lpV-ZdZLqi=pR5Ar z5yJ-wtnHZSQ>_A?kM*A^j=(U;@}Gq(EuI-lmQDWWhfHOx2j_R$Tycluiczcll9iZy zFfaGuzTYsHz%Cxw5zTlKFx&*eU(9bRAk8Vo+tpkfO)ZA-FXI@M@RPvhra6{Xs<$q0 z`tDR>IDmM#^wk8g_C)0G8c!6`8Gl&UG2$~A)GQ;FRuQxLZgzB3WaS%)wf5<zsC&8s zzeRFpGB%edPVN>jC%SDRKM~L3W~)l3u=PT|KGK<?M$2@APq{5~hD&FyXhMIo3fq{J z793*b0F4m@DS$J@S)|uuuaIfw9_4jQyvQ<b_<P(;X-z9;SzP5y3}At8w=<^_lB`K& z;j(IthH$yvQz7A;zzgTYYMEB4ZF9uL;k|&fikEQZ6UhrN4rlYPy`rJsc4Dk5Sb_ra ztfNA%Sr|{$qX8qTne(~}coM??81ubleKLqGYyjyZYrV)X0EPrfs`|xxD9d&&8BS3L z!rVmNJ+%J8yqlo=2e<PwrAc68>Z6T*TB%(2t%phZub(D@%=e(L;Q({Zj^bC*In>5* zHeca)sveZSw+9W5_rF|6#~|?4GTPs##70b!#q7zt4rnu4IH~EJkd=b`mV_Sx*Om$3 za#%PQsLzK|WG5TQ1+e5OFMB_t<+sPt=`biNULQ8nDZTYl%4_VLB%?T(Yv&{7AJOP= zX*9hR5hC<ip}ja`Ui6pHZu}-{oe`@m4Ob=ndv;O4)qG0Mj{t?BOI|t`Ul#mB{BQo0 z-ubPC!svBgFQ$-xB$kh03ggmSEwIZ%gxWNxl4M=@tWhGG*rjZff?M5$m5Qg#P=A&) zznW;RTS%yv+d(VYjK$`7*#~G(b|`So{+K=(LMfS@0S01W{V9juKZO!YQ;sFh@$wI3 z%B|gupqp2M-GIl#nF4J;&H8Xf`o<6R`Xr9^`X1<Q7f;l<urqzpdU)U3FWmh49zd&5 z$F0p4vKf7oY{oZi2Gt1oS5k?req~<Yvye}I>-DwQiWlWv(nY~;ghpFtyRo1$+UvW& zK&9C0d$@-6K_zx%`s@}mJMCT}CzX99yBC~PsFg}LX>&@nIY*?OXQ&m~(^!IQ#Z=i3 zAMir0o}^Vq@C>zj*3L`oIA^qum38#+vj30<^0DpG*U<<#$C7t=*`yq0lG#Ue^u;0B zK3q5PMX{>#t{?}RvP9^Qf}i-0hW7n6`44{3zkoh-Do6XUF1VVb(ii<1H(iHU(*E#5 zt(4z*ds^+WkGK8l@%kojk2ob`wm*zmhb(jV2@T#(3Y;b`-NvmANgrUKj><}hqlrd0 zgKA3&>Pal+&*>F>&fn*GJKHdw(J4Ze1|b&NPWq*HvZIE#og7g{lKGwJ<Y)231^h{@ zCNA4?3KMOAxDe41Ddw_M#!kNFw072M)#$V~aauL=ntsf`td&p8ndPQnFRRjL`IbdS zbzblGd%0_Rs~0WSbXWpVOG7rhr8iU36Ng(5i0&I<QG5C*XGsX-uVu^x9FaHDaYW&_ z4+n2YWqSK$r*EGL-e&B1eW!1q58h@R_tj3{lB&<GDC4(pcKQ~vu9I)y@AU1)PTzjq z>D$lRz1=zeBu@hm6(^g#pC?8jzfehQgy~*8ia(F5r5bVXCjP3dCAVyU#D!w>7ptWH z6otwNf{7vs%4&Lq|Fl7Mi5ns!w#8yvfcQ`6HgLO7kLdd4O5h3&{u(peRX~5~9Dx3H zh{C0Fn*4uj(|-fpG%5Fn^3aF0P)BD&BYQgr;*U5+&Ljdjx_wXmrNG)&$`JbIb-pPB zZR`n6F7?Vxs@DElu0NU5C9`Wyv#H?Uru2WkJ>%>}C5_mNJ^54Z|6<#xynSeysB|bI zG}Z@Qw9Af079Rj%ZKaW+X7_h>_--qQ;oFGS4(UgBL$<?r#kAV~2ydrWG8AfcTG9<E zLSB3XLk7euoMio0<Pxs3*oK|_oeekmx8K0rIjh3_Cx(`ER+IkaNba1)>UZKt#t)U~ zSv{NOe7K$um-8Y2^5Js#;rigi1Jjq+&F#U~?e`#@<}{$|mKcT*RVe3K1K=&f-iO{o zgk3CPD{qpK1+;3|R;dxru&cSLs>S6&427F=9I@mlqr7~mxEm%G-2vB^Kk)NhFaL1y zTJR>;u()6PutK)U<Z3T5(kr?LiKra;rifs9EI9UW?oS=+KGY9##8F`vD;$m1#ZuZ9 zU!p}tYo4UOm9L)A+kavxK*GAws&8ZDwGVtYt@2_!B#Fnf;OqBeP482-Fp{{8@;!Wa z4iN(T>B~2%?m$K}xx{ayf1Oq%H2c%p+TO`e@s}+p_}WTv_Pa`Y=xugr;f0cojE2V} z=9_=_<=<kNUKd)ir*En)bwXoCEh?ryYr7f1e4od1upcq$k8@4E#4trwwW%-3p^#yM z;)wf0eY#UNFD~2@n*P;1AOe6yFTJ_``R0-1qWeYGF-D0wX_^%q9%WHB_0!epFZa{- zJYQ93vl8%tRUONYUx!LnmA|$r^|r21DpT)Ze!<l?Me5X9AvuD$0*~0P_U9NW@$++9 zP#%XK&5fi&K_h!>B>I4zPOiC_=u@!gG9<_SS@w<O4?4)a&{vBmkM&<E!uv4Bl>d_g z<4I&ss~4~U^4+ZV0AgLcCB8ZU;jU(e5WBP|tPAKitT9X3OzpF)=T*4OX`zi1uiQP! zEK87IM@U6*2^N-pnDke3P*<<Soa#etP=}0>$?WEy-Z~3Kh6QBY978}nhUK1|A_CI% zY@%P)lr4*m(Y9ZL+JY-U>evw=+h?P7C^6`TJSlj}XE!m~L8hrHkzx${?4L;m8SjT{ z(!*8QAf%_bIV!*=p}wdHg{g}YLt@n^o1Q_7f)|X|Ybr~5)CcEFWHQc_8YuL?o<K82 zUOq-f8XlON@aeBcKt?4on(vpB<qNL>WnPV&?MiL>QhR~sV{K9?&VOS;s`dsF$jFRG zV3Ka`Qjgcu!`)QBwA{KPRcoAqE(+yd%Ae<v`oRVnzdc=*O<mQo)*yQAT5I4&1xnOn z^9A|ktC1>ip2?k-ApzYYv*bz3oaoOZm;-EgJ3_WL>yBpZ@HK4-7*S~mo!B5WtM1f$ zyu8EsgkTq^3~l$;M=eeEhW|tUROq2QELkNJlGcij{^>}4J5{xU4lXxM8h|3CC>VhW z&YMV{o*Y&^F;9IsfL)|YNl&Ke%3SS-()v}4GRZ~{TkO!AVzYf;EEFlKF?H_o;%m?X z+N9QQGj?etFJlUj0OlG4qfzJzJjE3#Orm%y;ixRgElWCuHC4LG;uV!lO-8e(jA#w! zL}-m;sn&|hK|hJaAIXb*OOAkaxcRUOw-lCrEp80M(f0UYeKFx5TKb(;+)%W>Zj4S* zCu0oJ7%vzGp+_ioKZYQ&(+k{LX|z{B8e;pZBATtZ6F2u|aYH&OJi8w)T;W;wDcy;h zkf3X&w!)l25jDS%S}(J*8f9}FWmJ0IaK2z?cSV16g&eh5l5+!T%z(pHaJV?>w2CWa z71$4`ctZ)t*qQqxHMpraY8?=3l3kG!c|Qyp2f4H*S@A{K9X7Ik+O;<@Zz@0XxwtaA zB*Wagt8+@3t2KjZTbb(*&Q`Ra)PZkAgjEwGEsnV+A}CFt;63RRe6NEEe&SE?)&Io= z32(9!^m;|NEe6kEQj14-L1TH{ocicqn-N6`KZVJ)ZE(F9JC}pG+W!iy4@v{;Z>wE> zy9?(CtltDN+N*OW&it0#oRJ~|S)kC|3f$jwffP|E+|BWi1Pn}L7S4O^pgB~ORE?A7 z*%U`ESiM$ZPy2blF$+}yhMNM}uJG?k0WVO6DsP+a$r1z^3tl}?JUjTO<bivH<yHpp z)6l8<C6*C^_}rsdBP!ZcN%z<W<U9xZ?^jlzQ{{fx_9g@P{{tB%0RLaMgZ}GKD7HfX z!VJK56wv-0yR7s3npljV9Qq%Nb^u)WlE|Ceb(;znG*Ymjb&Z+Wv<FyY2<EP5p_=oZ zRa**k!zf|qQ0dLH%OT>AkUq}B+_kU;KFsO%|0tl_45Rvx@)!}Jf|OfOkXuN>JCKC@ z+VxLK4$}_jsL-VFBX&Lk%Bl!}awEwDTDPjv0m^04v)_n`D(y`MKzRo<74VxR&8qb) z0nrPxVMI47M0!^)$N6OE@?wV)O)XMTWhZtkb$HVzR_`|D{1lbUFlLkW-8vwKXy3Pp zb$vwp`jR&Q=Z#s4QTvXS_o;O|vu{NjrP&@=Dq`1rL!vE~K2fDT!sMo=b87Q8sq(a~ z?n{oZ2Uc?mB#*cI_9Zty!*-m8vOBmpWDE$CjZ;k8#kpDxTsyL%i}R0|yEs>3IsC~l z&b6@)F3x*1?Zv6}IP{G(H@`UD(#1!dJq9WTRx_D3a<TX$FTfv7QaYg`b7G;q0b=Iy zDdm(r@(3hQghjr2y|ADCed$EsZB$)uO!_+GkB~^WN}eJo60=X4t(7#OrON(1I^`tT z-_U+Yj^BP)N!OoxiDhx~JA7xT9f6hV4bqX=LP5Lp10Tn7`{QT)Smt>c8xOFF6@2@# z^#5?Jzws@{umU*ev5w(^-D;70{f#v&^ZK{;^@!kgjeET*cwKH^?-9J7?_SThS&{kr zzy_zC(JETS|0h`Wz+_??m2;WBS9l`(b_;w_AxWEvy2fql=^U5i<K5|av%N+QXB*ph zbFN$)a?N?u>hO%G_uI&kJ(32*#pK2%25vyOUrSX$F}ey0kaFC&$GvK~h2JRE=WY?x zEm7uN_s$I|P_GJ9cYcNP@LN>6N()K)E+nOM74XwC$FB?!ZisHtH9R$F_|=?Jr*sWB ztc&{%UxU52JzfS9upzhMhL;BoUk(~xnYrOrLBkh<hSy|ncx}+|*`VQy%njGZ!%F4w z#1?e%S1``sl5PBjo)_BKXE^fKLSo@pFZi#l${_se^^RY?({YEoR2nNohhL<>IzKeS zpGU-0Ce5t|>E-;0d1!WYU_{=Q=D}o&2f%0p_3itZJPF^OD27Pcl37-xk1iB6RL1i1 z*aZ<uVQ<R!6kL5iO#5Z?>b-9FNNT5=)AtO~*zpitizi5_0PH`P6`dnnarBP`c(F!* zQK&0(H9?osF+GpMNvk579a+>pX>5Jq)DYnfItd{xN7^&!SpmhP5vMiTxY<wgZYLXp z_ge?k)mlTkvRdRuUsuN53h~-+mZ;=%!Y+}6T6FJ1CtJQp2)J)i$G}q{);c`jo0%_u z`#X@KTj5VBCOu4(#vf@n&XsKWMM?<;wN^UZ6%*|0A;V-9wy!Vip{P8m3`(^xt#5M8 z<vmJW%Ej=2O?JS8zh}6#{+^Ws{Ixj1KkJ6X2Z9(dO$ohz%8hEyCSjNyFgF#I##=I- z%Li_qlTyLJS@^2xh>(`Fz%mv*A$`GG%>ZlwWCq`v#PHUc2`RKdN^-SB3tB`<Xidb? zxCcp;?xL=AGe}6b{O{#$pWZJwXC4DwctUM!cj{A;W!hQ4R#Xvh%(PiwabAp^G$Y{_ zxNiHRLc-yM;5^ioP*!s#PPp`1M1E@JHcgmpR4ZQLC~wdxMQ71FApTUb3wNvAEQD$g zKx^Z8W&7-lA3_5ftC{4X(uYtG;yTd|*+ig~@Ku_C9!{z8wi(4ADYqwk!L;gy*`I8~ zthd%hGG&tr<VYr>aHe|K@-~DP)^MQK;H`8qDPh>4))vZJ$X#N!m0j0qgXp}sIZG-d zOg{?{FLuRO%Cc>~ctL}04Y|s8w0AgH{A66r(o!<&h+{vO6i<#>3bB=vv7M_6GWO6& zyh-Jqr62h|-38-u`nN=+5sywNv@?AsB0LzH>XP)Se&iUsj;4CCKh?$mld0YwOjSA$ z<|&xClG%Ag0=|I6ZR>c4PvSOCVyk504l9t}NCr4&evo;hT969}--ob#keslb;Bq^{ zvXhPI{l|&P^vf-~!}VltpzH-thM6a;qsLLb3V^<izInu;6m3^zuWhW+KAju=TLcdC z2WhpOP)<jvsPAGlG4BsJ>6wT5<{uyz0m(@`OOrhWBo^@9_!WUDZJ%YEe#l36V<ptR zSQDk-Y6cA3#8#F_H2Dp230BU#1oZ`jmYC*h80*onpU#0Ld;}lB9-)Lyk}0o|?{dlF zfu^(y=eWH1_3VRkfsa-{9#)4^X8{WLFdy;DQtK9Ujx@B_h~p2gQA37nMD&@vMhZd0 z1**pG%D<5w+wF>__MSN#QP$Z|!(*QljQvXcvE9A!#}3_#@Yv`0W3TFP?8`eC`)*|S zK1p2okOjT?8=1D|{qJwG9+5JUTqt#@by4iGw*?xq^&^^vRFmzLIn`KTAFW1Jok)yw z=W|6g<N3U7M=+!r(ipE3Bu&C?X+Ap@hihn^H1Af`=}r(tfdnJNjwL#tY9KrDID8zh zw+?l%K0BSl8F`Y7MiO(hC&NCJg~g%MVe9#TFOkCSn&M^yo~c$450CVn8;OVoJJQCP zQa^D$-b84rFx#Mo_;JJ3co~OTh%C+B2!?qN>BlbUBdC~NQOS>9&`Fs`IyW8=rNtK2 zzo5)s!ELfcX(4G$cZEl=L}|fHE4tGlBT-u7Iihsotp5d3y2-OdX(FoBH)jY}0~!}2 z^9j>8<K+(8bXsj+<rO}<RjjlX>EG)4NPq22AL&0rx`>0!&4E4Z9)eA`2<iXR^<-}G ze5C*2%mC@Hp>KAO$p%PYjWyc0GyhAZe+wN5=|48pD#GZ!$Xw?+EzYB4mO<UZvwTxe z)&TPWb#nrxDM2s1$fl|c$o{?=4%s)vJ3#ixix%ZxG6&v??~2WasAb6#i!C{;bu0TV ziWGlauVGt%Yn}_X^`ea13O319psUSj!%#aZ*D})^7LQITz_rk7lSu~cM*NxiXl69! zXzGPL@)dn{>kCaotO*A-zH=bbL@`*%s{C)ie_UV;WecX3sNn9(8EBEHmxAv`CTjQ< zJ||v~?LQ2D*Wp*!H7R=y8TP5W0j<Nv)*_zlWKyrOLK6N`0>fLIiQwG8*NG&$oW)Kv z5bnE?x9OZEz8>u^@%u0rt(@frSil`XWW2-=5St=kd;_!VPtRGt(IuU;yk^#BoaKqx zX;b|U&bO1PKIl*Nwg1Uf-wLLRH~BQ5vwV_`6uwzGEhA_7CMU6Vz*){GY=CneZsuE= zNc3fz%rNgDR9IH&G<4%zgk;`zJ(=%Fyvj(!%z`-qk~x*Wd6b4^)L5h4KmET%GVjxY zkj&EQ0g}l#uXS;pWz)3Hc&JV|%g5tj8<;E0T5e2a#x{#^@+qQ#k@)21sKwX&;+NnI zT3=CrYF~2_?6cj;4}6;ow&407%A(slht7qn+n$Fu^^0o1mXYG)ttJ4)#yYA8XJC6T zW^N_Oat8)n?>eHi*zOXuVh)ibmg}|ETf-Oi4n7-@OjO%7T^}6UGyb7b0+nU79$HG` zz}?v{!mMRl`l0;*Ar86YIjyV+8N!n8dr5B|kbzsUROo8g;B}ME`Et0vM38Nsz-@z= zgK8OTIwh<ZCw;20P8r0Rejw21Q%Hsk&#zmc*+56_t}=KWdDb1^n;6<Pqvul~*z_q$ zjy2WMA(l=hDYF#)vqSUuW5Z>zLi~XgU6o_<qsO=i&V}fPEq?z2+XQ-Fn{Cni7|{D; zRcuV>tNjl?ehKn#iK#uC3SwK%)NVu%oq^R{&p-o`(E&vkSk5LH7ponH+gEVIFLWE= zZg{hR<#}S%bi<pf(}CrC47%zTvGH^5Lcg=^SuL-|)u?k$)+%O%(Xd;gFK9+Ts(V`N zIQ4v{S?gt2ql2$PmD;+azPmyAQf%^f)N<7GN%^!z9QA@6pQBzHQtf_8euUk{Qx7YP zEtOPx2%(Zv7>1iEtCwxIo8RovjLq=FqY5ASMJ6aODj%3%*2GH9uU*{YQQxBsl_4sl zCr@X(P@OBzJt{%^3-d@<Yqc~tPp!a3r>l9|sHj42;FMEO#$4;D1FsT1vsF)JV{yJb z50a&0AGrx-PT8l?9?Y_7-&>nl(0UKfejnV6cXHul@~J`jP{(c%iu*OyxN|>-&CF@E zjdyajM^BN*0KkQ>K#Nzp$l7ntB%X?A{iWHh_qM{P$A((3Cg@dTe~fBcanvfp`ir>P z)XlLZY3tqLf4yESPnh?RCBy6GoCmmfJ2d=o*A?u)>{FwKJ(4RDHmGH8%jFQOx)C*k ze%GQQ>*%+tKH_j=+wDNCY^qjGv00K3qw{Z@owi&aL9N<ySpm`w+zo6tzion!6Y&d+ zT>(m<u#q`6Qo|q3{9Ethjl&maC7Nf#4Pvv+y&ST=S$9sW$#k{e<jxRHnKa)<{ZuZ0 zPB#eV%cGatz+U1ie0X<vCd0h+7TepAJkPhwh29MjIsUB^$`7&_M0JVr0(}yRxpPd` zCi+V!G{VOoq2BR)%1<8Tdf#sgbPF2bo~%qGs4CDXxE&?EZuas=akL=U(}<Mhsbbvg zFcpzC(D!<Lm~e3s$?ZJ6M{l5>_b#TH7~fHl-rF(M7nuo_v`0x@W=_Tn#pe5~!HZAD zn%*LjG!M*DbpQA~19h8FFIbKEMKQUL{-|P2ttE-Ms5oEDtv3%-?OWN~{)LfD2<_tu z!Zb>B+9dX(cBE}d^3b3aV!Ub<bImV<jn}8IbdgEE(p-VrWvDB)Xo<rHV&^S!(Am=U zb0lvVg>ynpw3#*kjZ$KE%_4=x)N=WQB}p&g?x99kPXkqbG@F0`s@K9CYrczFa2~|q zQVR2^&05$@8Co8v-l=}Cn&?az>A&|O$Y?#uv`6WLF2q$~ANk{6B*A*a%ohK#@q_b2 zU_^~1;K;E5b~RUl>#SC1os>t6T8dfl(6H`}6%?EQP!+bv^>(5!%=XhcggS1f<DLQd zUue6{bt);UZvQy=e<ve&zH4Xh-+;w<8~@kZC|!Y1Gmi0Dcz1|maig3>k{5R8_3z!A z)8}N`n{z=>+oLY+g~zewgC{qN4b1~0vmFzBBgIMEah&oL>Ta&6lCU?}X;?!W{tr6c zIe89tBfrx_I68G&Y<9$YH=2tj&U>&u)`R?a)a!Kvo=*9_^Z|7(z`bIBpO6!9hIbYn z;H;<ZyCYKRH0q%#-NlrOl8d~p2#UaZWtaMEEj0{K89Nu>i{@cShLy^o3D@*ET6*P` zxzi?5Sw#|+Jg(2n*ckhcw~Jh?^rUtRxD_8mrYcCaaVBPmJT}Sf0Glre&%8~phhUrh z@2yz(P7ch!_Qu!e$bp!Qo!K?%8|Lg@74ooc#Fk!;kq+;1<V%zT%7XDN^}ICqHDp-I z<5Jg8ao25rnj5a2<-Z)Hbui2DVcJ>R<3w!+TjS1*oJ32|y4llOF3<2_6(kLAU4^8T z{$`BTaN|R>Gu)^=a(rK((4n4+bp>Gqv2r=6&ti=&qHbr9`^1VGp;0bkl<ku}bw!-R zM1DHiRp?%;PAl~0bj%FBseMVRC36Y+HAawWsXR8A6RMwHo}s5ZXrGfL@<w?83aKUR znO-Skl~m>mwIXmsjjDVy(j4M|?T&6LN1C8S0Wl5@(1v`S@qbLC*AEY$zIV_^Gvupb zHVID6{nV@=6Rzq<_dM9%r7!V6)Uo6%z~EF|+LW(<qt{}AA-(D<+>_GiSMq`!2Mej= z5~R`JQE!%2*U<;&gvSk`_lhULyaSoYBceb+eNssSnSAn<li>3|5c_6MKs3PDKr@qr zy_=anAh}hcis<$+n<iE!UbPc?pITLd&a??Zq)(em!~%Vvod?lcF@fuY(-GPTNS)0Q z6gr3J+1DKiy6F`J-Gtu0#@htDZjb2!@}{_B%7-6+x~kl+=Wg66cMReq7%9s-DA)jo z^rCC6@etlNcvs1>e=nVy5{&H(*YKNW&I<cMf!WYSwSztL{8T2cWwaDD`^(r_U!30E zCy$!ws;<6c+cg+Hx+N38U}OJ4$_tp8UA6r+)GQuoHo=+_ZHwol{w5(rd<X_S{X{y5 zDefa--a~7XPZayzGmy&k={mAJ*c<o>Q_QE|^Jdg}T}RSIN+nWrOZ6A-2Bs@NhsVu_ zSU0vei#>jo$M+-Hyplh>VKBvhKQEEcLl>DXvda4=0L(1)n!SRvHQ~~q>-pPM%SITw zo@!J@J9~RyK@kM&rAk&cLIH#%b>8bp5(!k9mrp>?W4e+J%B)iG7gRtP1!26CfPj3= zFXzRCWOM1X4a?JU+%%I`!|&PR&8KELwcTV(hxF;K)EVkI#7<*Lu8?A1^TOo%ABLeF zcK2r)reg#M#n~P%>lrDKT(A_|$gEa^Yb^{tVWm42A_3e^o)6WtC-_bdA1AF~qc{d! z`?XcK<)L^4{>_OTmbW@?E}zL#%*$Sx4Ga%K`^$0hSl}4KMDT&EtAiO_W><D4exB^T z`f1{XIjBo#lnM1VlOV(*j8|un&lrSZL59h(x#@>p;W7zpxcu%u%)Wy~gm|o^d2<$X z+z0x<K=sal>VT{mK~JR&w0R_!5atl>1@PmmLQnA&iIvX=eK8Z799he>wlN>fXmTz% zq22nF=|jkq<|ayg<-_tUq*5L!UK0eYZ=d+s^6yv8P-3f4iWqy_LE6eDwQ?GThKtSo zZj?{6iL#~;DFd#G4wq&R)9AM<B_wA1Qu4}fL%L`i=_OHSpSU@M^fbrPx=aMSw<{TN zHO`0{@C8G-+O^z%8>$rODe?)qckM2lT`%23qo#rOHXj%gCAztaLP|R`9zv59jL)3z zstg6H4!f!=kn7d@Ua!d_L;+Z?SwsQKt<B=uXs4-TBvf^_L5Tc_8CfDh(mkfurZr)O zz0Ct8t&sqJwFKzUTdU7uAfcZ7$q7^x7h9I-Z<{Zai7eb+y-4Ap?{2{*FW)OQYw?Hb zXO6{-Yc1a@lihA!{zy<pA$F8LwnN;I9-FS50Bpm}U1SfX+ilFXm_#K$Y*0!zm7cms zReY#D#arC(pN}E2Ts^BLdVthmA+Wdwhfc76(p)klQ~X+c^k3<tf4hYrDcDfh_@<a( z6MtU0#p}UpU%Gr*o-Tz3I&44qB%&(Y1@X(Q|JLgqR=%n0Ql<-f?{xV+nKfN(Jf2xh z@iGoc5pq8#W#4P0C)A;x;~_HBdd+mzD*)n7!~iJu*Ln*3Y_9(jaP=|>cA|3|<DjfN z8HR#TT_9E#uTdn;G2!$MU|HXN^PlN0LGMnv=J$@DikSkDwwc*1UHA_sgUyNby_g0` zXj}+}uE15fUWLUSV!CSv>9j#iX0;pXHp<ZA3%XX7mLwB=Grh4hv{dVafzSay$Y7At zm0&>z>(*QscO~vGwP#XdUgu0~Bq{5=4G$j+ko6P^ObhSJ7ZKa&xf1AZrnk<phM#=% zZ{!}fnz)P3cUrp1I?4SYC%PuIb2f@)?fGfGFW8?U$n8;XL2QK1TDku_KE(8{?cHoQ zefz9c>8ZN}h+K%|#nwLF1suI<I;Wh)-<eM933plx+fJ*PEfl%E$?ic&sInG|vi8at z1QLo%>hc$xJDr@!$No__x}(0{9d%O|7ON|AZj3pFsZMPMSX$R1EL|TA@TeQ$YB#_O z0W7`!<6-GV1|#-(BsjyTFz3bK+HqYFn?Xg(m%CJ81p{Xhxkar%u9qbi1GV8q8w)GF zfe*Zp+ESHD-$ySN&f_lg@kJg-v0<ieGP=wS+;na7vKbI~>q+Bo<Za5bA~>nw#8#79 zn9YitchdL=7hLuZao4)ms>240N_Sq)AvD#baFs-a@bz5M+WY`Lm!0(8R^`o{TZ@TH zrr@`xy^m1DRR|TLa3`YF;sI%v>`s}-*cTCmSE|B+ww3ns)TxfO192&(G)MY+02!!V zUvP;R0Jx%(IYhu~Id-@2#;3{=O7UFR&XSIhpkA2PQ2t4~-?k2(l~F$IQfr4lU(S-D z@i)IR5mQU(w3f6|adYkGwY^a;U3asrBFx6Jms(<Tt*vu-iF^Aw7tYW07s69tbbzNm zw1Qv>l(-E~oz@wis*9)NsZ#?ywb92@r~LmDPi+#Os&RN~Q${@XT?ZTZmcM~Z(>9P2 zJsl(Zt3w-D6Kvq;{su1i|K|ptsEhISG>hm@Bx-GQvV0N_8<6FZLi7%+yk}|v+FWxk zY6%#V?c#4Dku^I7#apxVuDiK179}yeFx7{o@3F-DG&pB)!rRtS1eN{iWRT?dr_-85 zah4{08Dr)2Kvx6;bD_{};$)+3Sejv)7j8DqXZ>kjn?6nMs8ysq<InS!)_J}V%=1z= z&!%9Wb#9)oxp`h6%=4n}nI{c1&9gq?%R^Vs#IyK+CJ(W(8530a&IC$Ok?-xU(zUH( z(fx*a2A<}jmBFhte~D!`-=7APYR-ig(dDC*^+de`a{?7}`W=g*W9I7#el!lh(Rpxi zLVHwIQ)uNm`nFNdEFARh2`9swGjwg8`U#o*1GnpsOlwPqfQ;cQcKG~uQW$LxoFB5A zM@l?vnXUA);->e(TDo-rs!w1x)x#TM)A0sQ#L@DIEgMts<8{kyiMb=YLb_PtnY&^t z;F@b*BWq3ZV0!tP`8tNzn7ELS5S;Sih#TeQw>3NV&`gBAd~XNy62e=d#AOR*XDP}v zA5rAnNc1pw9nM2s^M&kY^b@W`?9Av@k}xE6yn)}PeR%QAsH$H;@J^1Q`uGy!)q_8+ z#~D8Cv!nmvt>X+u@yX9Z9&QLG(|fH8d1>ixJL+aD9p^nbRdJaXDBnWN-0j&s4r_4D zVCx7B#3hxgr}Gk(W>Wc|*{l(b=^N<MFTa@L)O@}rbE=;XBf7-aq{T03tJ5-fSlajm z+5Dx6L2(hSSCoQ1wYa$wUG<inn%xUHM?1**l$O=uy_3V1;EmyH%;lDmXEsp1z@48I zugDd_`RQ@^{H&9ZU_1T%uE=zL_qLuNIu;vk_Ij7--L~b<R2*-y!pr;k8nzuH#m;n$ zG}bA?e&mz(kEYtS<<nZ(y5_be`P;^t+_u?+#-G)!N9)#`gt5-Y^~RZPN-$qHCEZ-d zOgV7k)MqzRdEP>7w)p~IHtCyQhDjCIeid_<#3tU%GOMR!D9vZ=PsOx;UM-J)b9y!$ zuBmdJok$U97*`sVfbvW6WIx8Tb~HvrTuo$zj%CC2hIj+(X;t=Vs_LNCf}srnT+ZZh zHKDsXF_EMP$UU9^1%d`SL}u7Y7MW+^3j3LEsBO$tN-_6A8L+Ne>4VM9*)3#2!l})f zOs(@?44Y}AJ(%0b$E#7>nUGU#>ao5BV;`w4;p)#MrImu^*7m4?6sFL=atiNF;Ch?o z7-;ytmsy{JL1pYa=K*nI&A}KcqIjE9EPU^BJUrx$&oTen?t!jCEe&|^GN~FYJO7FL zvMI5UEp#0%Hz_|5>#AV!$IaQq^7;{1C(gjY!c+4#)dm%&nQN}<DuTa)Qei+aST&m= zm!L<eMqqhG+R4kNfuHD5!QRhPRG9Ja$mZp})y=TpYH_=`1=qx3<S}W+5R&pHf9E9* zjFB*@AvOk3IF34vBVC&N^oE9_+(f4(aiZxL8$&L4dY)vRD|(^A;CnA|L2Qgw7mt<o zerqZO#Z5M|I;zwR^h@FFnKrV)fywKUEOcg-&>MV~+TK*Be={QD?V=)h1wfWn?@F_5 z!Mz$i_dn6dvi`dfr~E6Uv;dXPc(#ta5E##@fmv#NS$^ji(f~N=w<DWbWo83tHRrQ$ zDdSFU)UbEX<MjM-!)j!!bgjmG@Uqn+TVvWvau)eAABa3;OLOj-p>;paj`U6@io7A` zv2s6I4UuoLeU*s;*S$UB=JyR4CM8Z@fuhZyhqD8x-NVf-iG&_t+^m*4=nb3z!~*uS zdi82=fEismn#<PLJnFwWq=g}Qf>n6)P4VCLH9I)mk=A%~6S8fr9sHAaa2i@Uws6@z zu{1u0l*eC#TgX-9igY-aI}q@g+R!gjC;(mjXlTDyfwZj}_%l)TVul&UoXpPfNx@<J zJA}@$6RfH)e+``QrO1c_lWHn3ntw-XG~>G{HG#(cVY~#D;OlYt>NX(T)(mz#apycO zH>_e2h;)d}tFdY97JMr$f9C+|Z?B9<=|)|`(abN<iT;ZmGfeqjmzL%Z{L=!^quO~I z?D;wy+(#>TS{WT6J!)uQDLgGon^bbJegI8x>Ip{og6m0a%O+i*Wgg07HilGC(tv+X zsjZ$E6D_EJjB|4}PR?gmV<Xlh^DR#}2zd##*auhVa2Wtcv#{EE+%?RL4r_}V{67Cz zU?Of7M^qf_6b$^9PfRNg7Fvr;(YeX>=xoq0#0g&bm|XQ3R?k)K)c5d5f)<`h3|}E8 zvX6-eg$P`XD^lTuT$LJcCo)x3n%B{kyUam^6De~L)d2jnBBK>sj=GHXjSoRDFs1u$ zQ(mPYgaYJO0U$A6^*D)i&bGC4wdB5{$N8QVjbx-Vc`c3<waj6wTS-v{TyqV9jAZvp znkz|bN0vM4JFvDrg=~0UX!cfgKNYs9a9&M)Z}CZ$sAY%7{wfm(xJ0=w7WQ$uE*`Bc zbMSBtJIG9LP#kNb$R7H6I712uf-`3u?jXW4*I;h+CZg1YpRl|5NNc`}cO&4~{mglD z$=$_8D-s-*Mf+?9r{oNFYnUHeg9u@UMQkFZTnPYnz->Oh&d%)%-yhAwEf@!j15Bue zdCxpsEep}vL`B1sbT-M|{8E11p<#b5@GWfeZ7N76hEv91Pi50;HVPy5#Wc+Dn61IB zHb!5<15oq{uB{SnJ|huy9yrn3u`}lN+uV>5r1tBM`12hGLv|OBF!N>)7?Skdb<siE zL`}3cqsd|(SX1Dd$p6w52(tJ-(YL!d&|HV_66B3!(z{b?U?oTc3a)!4=eVc1XCqkK z`$k2=rDL~(qO|h5fDtpCOaNqWgK?nsQjA`%bzt~#Vx_$mo931~yJBcBE<-ekCHE!C z>F3TBH1zgzcFLNUZj#f`X6X?(KNaU)z|1`JLY41^8tM`G5@w5}*W)t`_dGG1U6cKt zM``G@w_-9dlOW=o+$P9go@u1EhkPOjLKwzy*D6}X=_xfPN$dh8f$Z4-fK@FPn|L~f zwCKWI+P%r-q?lrkS&T)0`_X(;V3y!#h{oC6HA}^R3(Q%RItyTRgkbdvi_vq;g|o<^ zbD|fq#9;BPhS(v}Lo6gY;So&Z#W;CVZQoa%&<xws=p}0?YBOGx<6F`#XPbp2d{X#e z0~W)Do=UrcJ)Z8KD7O~!f^;|~*Ka}c;aHh@vb)Ny-iR+(0jTuEIZ%P|mD0)Y=J=YY zvnqA}3ox}^GtcL277%kFo+pi2`B9ur2aOBNb@O1{e}jS&9ztnLaM6N`5CXC+TY)ze zxF?Mu1}zqPWUHu1^dTFgxRK3-C>71amm(MXL_Vql9TPoM+z>iv)=jP?DUhsEH2L17 zkp<e8a?V_9_xDAk20~PT_k{DDV~9i`YLl{ioYDD#ulD6p6c!CUgxS9U%?s}ils?Cl z+P@FQ`CSpLDe`65prhT>4{iZK-aGlRSG>&9zJtK3&KSBo(q;pOmI9c3YZw^CwF+J_ z1o{Yv1b>h-Pi2fED(3R4=Gbr~D>N6o1Gw)2=6E%lZnd%9&2+j?7%WSk=@wnetQg~c zAq)2RWF<dL5CGuCmO1$;v<7)&ZbeCj0>sE2K}Y6-9&ntytA{5iD7Jwv9*gS<Id@1Y zUNTb6%(*>mK|gaju6r{4-J)Wn@PnKr^;SBMc2HNt@EfVJJuT@`7YE81kpUA0(Nf{@ z&=fDRQ>2bMbA&@oEMr!`FfVqMzj9Zzs!Mq=U3oRw>1vA-=1H8526Fvdx`;g1h_0j8 zDzL8A=B#5ov^X8>9gdEg)U~@HW<A)uEXD(K%Q(@ST*7Ou=?Y$dR;9D<paC#<;cVB( ztR?f+ZsvA;x5Ns)JxjKy?&eYydva{}7c~&|yk@3GmislK<M`H$;_WV`g|B*gI~wvr z@;leO4Wp3*t^0p@=9*ze>kL`NZFsM1o@0V(HnP{AISX*q;;y4)sJ}RODjR0XGY`1B zp;*By+nd`bHFFj^Zd|paLpD3@<(&2a+=D5%WT7eXYfI~%hB69GbP8L71bp7J0Ir2j zE)M~c%IN|S#H@9()uifwa*)7zMh3qh01_ECRtwy0V{e<Tj3Y5yi#326@<@~Pl6=~@ z<6KC^&w-+Q7ias{l+co?!xHP6G=FZeJF~5G<az`zeQnguXq<>{w*IG~ukbO}S4X+8 z2Dz`+`d{7J(O1v8ua0nE?d-m~&;M$5M_;|fd0S4wFD4P1$ZK>ti|Qw4y@HYwDCx*+ zg-hs_v6fgbpz#*UKY2yJ;ig;?E06W&CO$PwDkG}@QR)-~n5DmKXv?{LV*RjOqw-h@ z8}KP**JhdTCRfBt%v;0;&q5&la+W;h{>IxEhzZh@t5gtbAjIXF!WM53vQr-JB0_cS z`l91e(a&PsYq{;Njf%c1c*wq05AG!o%(M7K{vW?@SESD@)b}3}Z=R1$+M>;KVN=nK zV4se+C5zVC%QZ^pwFy5Pjd4Z+x;$NmHIvX!QKVE9%Kr}KUOm*sb|}eF&Nb>UsDY@@ z+B}+UH}b-uAL@CkZO2VD^l624-ml>XY-vSv>ZG6+?LcpcIVsOYX4Ot|AbW;-Rc>oe z3Rg>I1!{j(oI;U#vn!a?Ts%uyy3E{)<`zxsD+;i|rP4ms4ZxRyn2=ebFY1%y!y|`i zObB=DCqkM2C+74SWTPi*mWl32)~r$9R!h8{NCRdbHPV)ne+)la(mnU)BECDTOb{Xm zP7db+N-^b_x98OO@WhVZPPi4|B=3|Cz)91(o$h=<gGl=wqgO?w>_rtFb2jBT5ZO_; zYaK=AH2G$TGMt9j^a%Woeadp`@y*gTKLxi3E1vGUs0O%l(9rHfTIP7TsljlakEI%H zk1wK&SC2Z;Ugm}4F)2ZuwTrDT!@k+9*8i@VF7wUda8!bjv&n>o*2960@91aI&=t5| z^kNQQWg${ohmvI!F+WVl(~IlYdnIoZHfcT2%)4{Y<o*lk&|iNOEfd(1YMD+0WPu|* ztEWpA#;sjZ$qpmltbzB+QIWe+bNBB{`2^M8V_Av=BC&SQMn?aJ>|?ed(TYmzG>C66 zN_V$~)+hhe;{`X=6SrnW>WRZQnD0RPC5XvIWoE&&3g%>Sg8Y2XnAr$+(Cip$#Y{m% zk$JC6Wo&<jya2E}jNkL;Q8&ogml;=Rdn>be<^HbhydbK9TH+-f`P!}y!fu`FAWVRo z24N0*1Rc~whI$Ch0NY@Savu%QmU_K`h=vkW{7>Y{3z7<^_`_@4zd+46$UFmMl2Gvr z`|iA`TgCPA>6fK+8J5ysH2Z8C_c5Vjo$cFMFLK%mZRS$?rMZgH`k42Uu+J175VqpD zR~}D0%BBL0J<VshY1$vnd{fBwCYo^u=L*@TFC$a=^J9CbAy>R&vjfD;c^EeLG7nnI zQ%`ftbZR!b-+O8C8XUkb(e_+Dtx=ca4${01P@NWB;Yu(8CgK%l<wOCPz3WJVqr9D# zvab70tv7VAmy?)f+nhdwjh7EVCHNc2cxGk|%7|=Oar;~3fHi%P1Q<4v+Yf7iqTEm@ z_99C)I<EcA8jDq9<{873cyF%8)*0LX3x+<>ype>+Xm|H=+|frfns~lDrW6j<wm#hz zQlw=gZxZHJbTGD8p<wk|Z-MRl*)pZNF6&*7qBJ|2j}*$UE;lGZ#df)fstg*F!Bh6* z%d5&_L(NS0-PJilyvPmJEmpN#3qN%@znclZ=>?qK8dso8uDPC+e$sd~6_v&Q!0)#z z%Wb<?01Vd-)v;^#2gGLg@dZe?n?FNTx80?;3qO;N`5WRZ+(c3gkZU$#i7&-8fJ-8x zU*ahKs5Q5dW`ryIV0MFD>f;ok^_MCf3y@P((=O{0O2GKb66I@w`yvT28FG<gH2rr$ z44PGW%*{$|U!i!2zXbz=El8j9Pqj9QLdZpc(koHnff9V8!FJ&E<r6Cf!A}9rB*6rN z>to0qPooAcF*g<H66Kq#C_gI?vx4}s7DUR+;|{BU$+AeBn2*JV%EbV{qsV8yykD7H zW)R>&uEdjh_ms^(UaznD^);an6c(A8I@!y;!y@uWDO65*N%L)iQ*<^@2J~+u_clWl z(&IVrwn6yMK)wW_Yl&(WIs}opg4WB>uK0*V{6-AlN(Y9taHr*35O|6kf4(`g%=_8j z?0i=Nit6g}s`Pe6U|P0;=bL6R7iz<ni<M>!xPB}EXdzY;CeU>;e}Mpy|F4h16e19k z+tu=XZlcfNHEVGZvuZ<3wOW`tV>XQ~>gC6m2yLUrd%vSM>4b<Bo55ebFc+N}tz{QD zIW!ed&Z#svB8&|(mqN&N@juW2toQ01C$fDsLsxo`IT3erZ4f&<)HDENu8}CJ?ys)n zU@1O`8a8XWyB#&kH6P4PnWZEn5l{+L69yD_xcP*TGj>CJ!%v<9Fxsb5{?N5>`}9j> zf6T1E(k20VA5Txznr|Xnz#$#Y9~}Mz79b*%E4S)K3poq&oGJ~-v6DGtt_2<tOKln+ z5ax%c`r-J(BBKR_d}*-j{vN)!uoLyLyHBI^vT%AUzWC`lM~G}`FNeSy$7$<+Wfs8I z<(eGaRc~m8ob%HmhZ^ud5^_#Mb+zAka?J#ggM+$*oOdHW<iO8-0_2=YR>7fWCBB#f zg7Z<GvDctkOe=sQ)MX){_46axqVtuaJ`H{9a&9Ed3CJ|s;$EcryM>U2GXGp()49G6 zvKwk133t!N#mzNy>0W)D)!{KoTP5r-D09d%d`z7_>-3nw6y~=|#G$hfW8i?eh~j3O z+5(7autH1cZ<{UE7`)Wek{7~$v*Ju2%&M2j!-<Kon?a}&%v}*#ElFv}ZtRZ#%B3js zb~9yQA!%@~>fLDHZm5*rh1>HC1;{ObEgz;3SByNZx<UhxEL64O*4Yi}A#U#5iX7A2 z_%n|2BX61*hn~cMbFR3q6Hq1z4LAON7?<;+ds^nrJc&<Wx>Q>EJyNMUMT`&%ep-2m z5#_WIaIw1Ql6ftciAm9R`wB9XMF$!kN1iKSr%J$Y_hd(pM5>0+T$-|=joV{PjPB_w zedBL$L%ZG8hu=^>5ObJ56A*1c-7W0%l~M&sKC)DSp|d1j3F+f4k}Y{ztv)1rYb$ej zqvWhSv#Tt7Zg<TRJWAB!OY&H#8`<1^0s0-PLj)gh4TkdaM#jyn#ECHc1<2MSEHBM2 z$1ZKx4&_TR{!c2i`6mcNp(AXW1yRWchvfr*J>#T?QjUiEOC(AKIU4YnNYBy0UEg3` z(k<AE)}ary0P`-AyM?(n?|S!w3Sc@24zJaRUA-tijD=t2l`UkjKh^L9$Aa{+Dub~A z%PSe>V5a;GQZhZA0%zx+EymqW=b)kd2!SV%r7}ze9PZ|Ul-J8#lY{ofyj1OIT2rjX zZpypF4YqBHfHW;}MR=k$|K&tEl0oKdxjpLsEk~$nH&;M`+C>ZfS&GZiEQdmG9Yg*G zW$R=(Iyu$E)3%~&)@T<)DyQ7LcFioG=g^JQT}aN=)AuQ@f&Q_~8s!mwn$5*?T9_0H zjSHecj5N>}6g6AOc^kn2^`iMEu1loc9wB{mE0oxi3pT_Gs5&_x(a4U1+;c1{al2Bf znK9}=-)bQbl*+h*NP9e5Zd1UL55!UiwknTd5+xtKUtQ|va>iDUVt>ExyIj*j_g(7i zzU6R{N%t*j_AYW*THUujqATFEoz@#=7Eos0IWemtzX$3|rrqSGZTTl*&tTeCVUc52 zPp6I@7*A*x6ob+ID0IxX%(L2_ixkxdQpG(C1)aj^R?j73bbew0t+NuB=+P$(hKBSF z;=@r%*HD6}2Hxvt=!4q7MOF|UTzxUDjMGWuXjZRxadR<2jEP2G9L?q>9=9LhL>P~j z6=Zs3bB!QyN)65(l)9ToMA7&*jSYxn82VX_X#uIvt_zkFoyuTO&VfiX&%$~Jo(Pl! zkT+1bPH!r-ZvCr%Z=x7Ib^BDl1oPNOh0*{K12U05sY%j%GcEeN&Sr9zrF`2E0e)(v ziL61j{=cFZg=UPa+|gG#g;G2jWM1@L8a~O^diF7ARI?2EIBddG(k{>@NJT98ETSwA zn3j4sKmc*EP^*u#wY>dsknunJmd`}B$pY9QvfY}{+A1EEU8&tuJI2fST0m4kkD#z& z3`{F_j6yp`i$BI$!5H7PjRA#w48GfUzzU7gyxCJ`x}$j@tI11Tt{pycZu9_~_~Dxf zT>l~pg2u!)^B239{ztUeX1l!!HMR9LcuH!q|Cy7$f{x|F-OD@xdJ(a@L9v~}jE`H) zXv4flXf<i7!2thpBp^T=Gbsg~S2kD`B%S5$V)~VKkQ_B~<tQ_o@Ilh+0)_!jmyyCo z5v=RvI4v(r90e30PP9BKwqoEwwF7PR>^2~zEG*Z`MzFPaMBKcqn3?mY3&0ovem8>^ z@@DJH^dJtV)XjTP8O{N*MkcvO;8|bKvFDkaQ@SI7?uEQ#nQL%!*$Ibpay<(ER#+(A z1AkkXUp=@vyH?iUmKfOLnOL34v!C}d?-M<PL#jES_%OKzTxlx213sZ=ww4Ui`t*Wq zF_Xj0+kU~em2+zN^%ROL-lEk-r{!OWdN*0_0yDaeW(@XVR9OrtNh#?6fUMath(FA- zy}Let-@1U+&%uy|g*+;q=Xh}><86N*qMEVk6u&2tAc}GjDl>3Nm>b16_e0NLrpqnz zPF=^%t=g~K^dd#hJ0oO`p@uei6Kl*(g>cI2CnzosLU=vuhY^B7?5#=`_3SRvd1zzd zS`Sr~3izURyP}npE+#&V!4u|^Kfv4!R;32~T}4rINyH@uV=0K3L12suMHLFn!YTFk zi^mbW`=axpF(y7W9YoWCD#HB@x=M}wqP6r|r8*-{uC!W)Pnp*4=0&U<JDQhzNMm62 z$AY43l+KD7ATZb&G}A~kYS6xEO7~}>jw4+}t*PN$Ig15kequYnlU~xgbUafWgx!>; zy9VIXQJ9Pl>SbqM2i++(&Gyt{W>0Yz_NI0a*dRHu<D#P|Lfl(3wib^#6=sp&zS3tv z8Kv~i!a+!PQC9Ltx-wBcx_PSj7@L@o)NJC+EnIYJPPJ{2xctO~zO4she?D=JRvv=b ztMk^xgn>Co4_g!U1=gT)HUXui-u+TO@XE5sGbsBLB)Q)jLTzzM!aSP8I!Z}9^N&=N zblAF$>rpo8LzNcg)z;=+WuosIkM63})BQx|5V%QUi1+!8>IX}#c^Na+03KY96IJkA zus5m{tKSC@3O#&)GatyqRiMIB^Y}Dq$ZM3^-4;zXqPc?5=IOp)L;e?60=LC4fvaqZ z`7mZ+w<drCyf>i6&b1K@dns9kZ%g?OsZX+M>)8$QWW#hDopE$yTb4mU+1B^n$KRkD ze}ml5&e9NSTWS$ROTo_{2?F+HS|xO6sEi~gab1=|fSd;|jh&@0*nao53xn7QlctCr zjswFCngPGH&2dLv6T9OgK<vlW9Ei^0-c%H)b~-)O_W=5YyQmpFNEKrZ@_M8ZA#qL} z@dZB2X)$VXCRf=`Qq4YKOG-JbdjFR67Elu>VSX#m)F+jG1=n2bdaf$1E}4~RKv2U^ z-bOahf#xRgVov9$8tD{#`Xn(H3evb7tH8D^akqGVHvGs6#UQPtRv>403E7I2vrk92 z&2S5AxE00gET(O9NV4n<v0EaS`35IiSDah7@9!!;z76y2X~tE0MMv^$D-;dpKESAV z!ud5n21XB#0(T`e3t1Wbx8>2*+lH!_nq}B;bcpbNtzVW}i2zEi!)sDv&O~XudHP#z zW6av-38H4NN!=ue$l&A^sIn5z=U!$Vgr<|3BAagJ@|}6AifC}~M(1e1@xB*YU9Z}; z8gBXA=&vJ*vk8+qfh(fpe=H)aM%$EnnMKi-PA8-A^LGB{;mNr0h{xvG@CuDuQJOeg zK5NMJAd5RuJfK`R%k$(on8DMKs|vr=2-dW&hKfck#m%rja5GevD7hKd%gwMDXn6QI zgqDMqd6hNa3xkqtdM66jL41&tbvvstfUmZvdF5Oi)g==1GC~Y5rv$GqQ8Dg)E%otV zO$%O~=Uxfe-sUU(70u&lLbbM=@Vge6oP|HX+k5p2<bMsrq8F#7)e*5TzKJ^QaBBM( z-}+yiVn+*(k*+rRU!2_jiv?)8G{zz~Ki%zmP%b#xtcx_7+i*irRX|M?HY`dG(`pyj zxB?!_M~omFix<Vgi$?{;+)sKEF#uG|qE)eZp5Re0?>G*xl=w@kUz)Q_6E~n`Hek!& zwJu}rDx&$cCCKOH3?w}8F9eETlX<a{D_3WZt_7`|zK(RA6OqAfJ2z~rTe&(&kS6b% zc@93|_rPAII60h)>Rk(a-lfakR!L@Dx?J!JHbeGkfQGzjj!+M4+M{-~*Y5~`Jl71N zGis9HiFc@Vk-W{)rJ`|()h4ge-jL=9@TJLLq8ozHI1h@(*5991&#gs60SDcZ#de<M z(m0%L>f?=M!%4{;@>*6i{tiJSSzynaS3&cNw0~3luIG0%|N4x0h;Nbi6@fZmTKK!e z;^ZFYK1ij`_wcrR?ISO+-DbB?KAArD@_Lxw4t*Wo7FfW+;dTz(3i@x4G_c+trqLhb z_o|HHU@jOU1A+_>v9%lG_id=v4si=$qakkbhj_>z;&+=5kpY*4hv?^q_+8rua0#(S z6Opnts=^{-3A8~6TK`<#&!LL9fEmH*9$Mg%wXB|JFTK2#*WlZczu0~wcdF2hebM*m zUEcl$vA*_;Yv<Wm23?6K>Bpua5)bnWP9IDoH;EUsK{aA?A#%7#3|G;s`3dMZ)<zo* z$c@$a-&DaW>4Q&6&#Di=VETYL#?6PUuAj-VUX>&d5@I6}t5Z3jNTEM_VWY>3OpBEZ zC`wH{aIO`5*NW10!>l+nABrZH?wxFO<<j2Ss=luBxP5VZQbuE?z1PQZd@ju5_M}+f zw8t)N@?4TeDz>T=-wtyLdJKJZNK*_E^f44j=&fK3(PR64agX%aM=&tQ4#VhjCvYCK zk#|(;a-o=t6oFW}KL3HTqJqlk_Ez7U<<er`F|SS?+UQ;(iM9oYHznZrX#Fy75th}P zA1!m@SLg<|a05$|MSzYXTrYF(^Pv_h2VWGF(hR+Mvcosc<Q(*pLtJk~>5@u;btXs} zm{wepWOP`M0fMt#LFiL1&PJ4gC5VREApSJZt#^Kv>S9fy9}z-ypKxN*tVV2&bp`#O zg3W?z^w_2LhC7xah9Hpg*xs;9x69AVJdNsFtod7HfcXm_G-0y&{Sa?I3|w223a^5u zI=3YK{YB{X)0FjUK=QIiS2C|xDJf(Q5xGIO#&Uk+_kw2+N3HacqVG0+q~7G3m#QN4 zRb>8Et=@Z>H_;n=J%4MhwDZ9gjA+Q7ZhwD5CM#k2YpQF^3t8;RcZ5W5g~pNM53=gs zX3>1ExoBEVtcX#U!Pn)O9VPcl#GM&EfY66kY(-DAGTP+*-n=&#x#DYLZHlz6*RYg} zA)?T_9$+$-i;q%+y%bNyql28L(X3T^F#Gsc(ghJ1I$ho*fAK2tec|T>YxnNWM&mf; zbbyo6Pc|<SJ2+{kG+ElC1kIoeaNiHDhc!tDUf`!E4Ru^-JDw;-TYg$eFVQu{2C(}9 zQy!{-*p}BjX8SJA)OTOo_g~$l{UTnR(~s+UK&GCNh}n++bF*%%+oh1dA2aKLnfj)f zY9cw(^G3Q0rrnxS?B5P-b&UJlEn88L1zkPA67)<A89g7kr7PMi(~8z`r{QRlM5yU< z=a~m#d?ukhziwWwTV#)PSldO3i-@b-j%<=nKhcA$_8K)O@^RYViOPY5U7CC0(Rx4~ z$tE#a_Q^W2(D-0=ugT1U|JY!k9^9#?j)#UdVnF1&-YzTd18|;L$>L-auo-@3Z0R9J zs-LD>TuXZ9QLtlO&3krsMX~@8`UyQm@f=^t0_v!xcoGv;s*UJ?Li%dt*CJ>n6p_Fr zk(Rgd&HX_oPI_o!$Dk~fzY{l%5|n+o_|$L*&DflEtU@6_eu?apRlK_gWlgD&jd&s3 zz<sUpgdZ!Ou!lKQ<+E{*L7o-2xQF{z-PqFKJ-DW}_&32V!pm#?@9n189)z-8AA37; zEMB|<cWYaN!0y)50lyeJ_eTH|8&G>SY2}0oS5TzJ%UML%FhndA6-#tmZJ8E~K%A)Z zwq6+PA`u3DY&bbXJ|sb+*b=LM{(v|FY2<EIg$mIl!fyw2OxcP0g`8S81(};H%G?bE z_>CO1hwCW6B28HrPT}0?jZV89n&k6DEaoQnaV20wZ~g_bElwWg6)j?Rik=)|Rcaq2 zTlZkp({VHwp5CNtx_VGE&u;Yn(xWz@J+&EPLOtF|kJg>tM+Kpm_wdq7?w#TOtmVxR z;^q1T8G}RL)fj)5H@b-wnkDnx4N{cvNt}5TI@ZN(W2yNR$*3PnZ#3E^ls&?k4mcG7 zujKIrug_v0SMjqBI9x>9YceMH;H-A3G%qS`Gig7JJS1!RM)9FdxO?%_oMdo3L5z>9 z=80hL(JZz?g!Zf1GI#PBb~D?c)-~7|G+0jq&i+ilff`?Lo3NqJ1dTqX5ukgvZtO>R zR_Y6a^=y~=f{YW4$`{WEU%WrtFJs?79T8ErLS@EnOhf2JQH02kwP1oG^ENz<bp)<N zmB%=*lXK``yz?%lRF!oN?k}vgZJC$9QVaY)3%c7vh4}F&f~-iNF42E7(kSG<D8Bo6 zVu!Z|1=PlNF^ke7hx_Y`YtSYl_x8q%RINV1-rhkgrc#1(!ZY2Qo%TJnfQNx%LDtUl zSgm6ggSn*h`r#Vw7k3Y}R>p;bWG}nkD>0!t$LF^7_Gg$XYq3}{ub*1M<8X6rv+@{k z;RB~tI!Fz5{G9E$u(OU2(6TS@sM}XEcKZOVYj*NjH(&)PdPs>+KUHr&ksN|-jr;_b z`#MWF>_k@nbyjJ+f6LqbZvXxV|8ASdWx+hI<ch|EsMT=6q{~PKmYqa6Of2!T55TjN zqTLzlrQ`&y&hfGjOm7uR!3Va2EK<tol<wHAfcV8kMuLiJDANF)j2ryg2*tz}j@;<$ z5h^*3Vdhyp*7HH-uR-CIrRG`k>x=AOG*t?!0`vB4Dph&8*XeU)LB75aNrDmr`s`<l zwbg?>v$}g~C3jAhe@F6fng4H{fCT^dd_2(}4ch)Ib6XNB#m%$FVH-4mlj}$^32+Pr z$`hssKxQWDuOgxn%p^Qu4MDgiW(wZiCSSS(Iq#dia-_<s`U?!z)108cx*~21Y6)j7 z=NT2}5{AIrt&I{+8D!p`3W7}Nno;F4@q4d$e=qSnyBDkS75r%vGhIteG2ne2a-Bj( zFZKn<d?CLFxJ><I-whoJfnywfqQ|IFix)3m!VXuVQRl4l|KP=<JD~eJoS)Bo`NTXV zUf?wmz_G-O{4qm+yu=^V`2*P%cF2$mC}tpva`vwh@`c}bgd{ZP3yj&<!W3044kYVc zD@=u&y-Ks4{boBK=nd(h*#??92yG90q4?|DZ8NYg4)(PfBIp((MsCk&MM_6~Bz#?> z(ZP9041LgVRouRn?saQ;{zAse1)pX6A>x@|R<+&4|L)6V`k0G0U*AQM^al5UY>JZ) zqS{e9RKgY?$ih%?`#i$QvKst<Q|*4Yf8Npipj}7*{#4%u{RIF1)Z=y3-+%kO!+8?* zzl)P=FAg12pGfQy(FC(YOYGtZXoBKOT}*xhoFFCND(y=&@MxrXTlSK-Cx!xj5I56H z^=Qwf$Q-1_a?kEX80X=3rdKUlW`eKB+m`)#7&lkW0~g6R0=-nctiCBxP}x}7+*sG( z^=gV;3ThCwD^n+^^HHJIl{J;smQ|LOl{J*r@xNOB(tn!4Hf4;|8`#=@k(WOc9En(! zs~)=AwUmIC#8OoFlRFa?G5z*3+cu~f3h4$${8=zoX}r9a%(~!Z%E&SLgJ}Fx_((9; z4spZ(7nwo&fG_W2Ab*Cn@%pklR?%2rU(4ib%gXKa8aH1{WxTwuF6cjQ##)~KO*VE% z^XV>d=od%K>4&*rcKzf{I2_l2)3MN5>-Y=1)@jfLk5Ls<c4BU6yp|3j<L5`5_A9GP zR#q%)Jj6Z{iG1CytNsz?*Mq@Rt4>Ib9XxiAVSA4G+0nzt4jnOW_dSN~w&&49#tt7c zeE1&695a0Au*xxGD=UW$AA8J@!6!@|J9y%RqsLC3I&SdfDJNw4zo(2jZo=5VR2?^M z!g0rBZAqU~Qd9ri@5fA>IC*TQ2@O7G+L)=8Sy`1;$Bj)*n0#F6)DyJ!@ngs8FVN+r z$;ap~la*!r(BHAFtZ~Qc53lt#e~q1d+zF|_Fh{>RJE6bm;^@iK$JtK!Fbj0ID&T1- z0S94=#G;V@m$Go*^~Dd`tjW~o<+L_2L#xMwR%EP7MjWoz^H<WJ*Kq%0FcE2K9gJ8+ ztdlW_V5=3Chd^*84{cdQ1$ttHvrTOUSf?$G(fuJk1tM8lm=s}H(7d>6)kqM#@GV+A z6ct}(`RuDcn3Dd1@;}XsxGX6iFXsm@FR<HjB@)40e4ry0`d7x`E762+XQql(q3&TE zwq+Bc7+v`J9o#$_fl(WJ_(hx;fi)j54Qd6g(7E>)na9c88&J#I{!+=8{q2Wv+vr2% z5;~Y{F#;I4VVtgTpR$n(Vv{(U6CcK7m~^O-)YJE7mD#`G0cAIqPL?tL&jojS8o&-~ z`pak74OXsMwheYx+hCxLT$9^27(Kyv$ss=6Q?dU5ehNbxnJ~;ligRJr|CEP*7n5g` z&j336Ez_aiBh#i{3Mc#Tx>ExvPs~m(%Ai<$OzRtSC%R^kL1U!U)$&Mi9QnQd!+jKD z+$EV9<VF4pgvRcV!8g^!670kYiPDiS%f3GNYw&?Yg@R-?jeD3sgPsIPIKZ$_{ArjI z$0Elf5-~(k*IqPFMQmf7$)ZS$gRLmNW%coge~{j`OKwkqkoJ1CV|3J_U(n({gqELC zEOo1RrDK-#c1ZB{{!DN84&E;3ZC=uhf)VE+%^5%%H{`A;cyjyIUe~o=?p<EdVz1Y_ z(JTh9QbF5GbCl)SV^v!r0#W!7Pz1;}2gMRIK!Iir4sZl6W!|siEog`;SURlvml2F9 zmqQ-1kuAQS(?q893hAe@@<!0C)L?^k0GwikQ~*S6u--+=?ig?4n)SFwJ3ZNZ>}6oX zyP?gZmWZb3=H7Z!1SEgvCh(@keiqz>&49B!xCty7;2T(q%%sE((#wq}ojiYJ;lxoZ z;=G;}9vN@Kjk{L%#b>h`P?P(&@IWqK-24UTHvLg=b$%m)K?U~E)m>!@!?Qy~a5w(s z)+nXgcs8*Nx5!Gib33`J*3rB#NmnpJvSKPLa4Txf*AQKQznN@Llh=?KvYOl<J95fQ z>ESu0(Gm#WK#+SZ>r&t@0}UKIX6pFKgQt!gKjDPb)ESn>jh~P@w(988v6Cn5y4$$1 zV@C|#bI)Ur-gDg8J%$b&eC(JLjy-zn<Y~w4I;3<&=}_B#>X>Q&E#0!Tv~p5vi@x6i zx@pHhu4+=&;4R;WtgI7G7&lZjk)8I*YKXx4&)VKXFMTQsea(tl^k4}Or00^nh_^qN ze`KJt6W#M)W|=g4DEia-{2`D^ZgN}C`=i(UK$rO~^!^$9{+IUsF41lPL@f0FpOC2D zNKGXQPmB){6gA?s?dclc-&eS#9Fzu1{ca2v(A9JM@rvtlAFlr~MC&h);lBUdA>I2T zu7&Q_UF0JM-py&-w0K(|?B%ZWvPY^P^Vt|*-5;8T)RkQzyD?^w9Uo2)qEa{FG|k9Q z!P%*jGs~W`jgL$FN-bxy{alyv^c{JJ757a-SI(Q4GVgMYal2p2T|#6==-sKn>sy03 zx?Qcszm562DPy@WTYgiH9y9jusi|Yej^m~bD;+-EUX>GOOgeh<#0fLUZ4tn4>4iCA z;)JnVHiIp_a$=u<?3K&3p<A+zKgk3Jx6W!yrZRZaxJeclwDz_c8Uac9>~<T+estA@ ziN}nadP4A`s+B(nv!rwUZH#;y%86%XO`Z~n1V~AKw+TBBC(Wo|ez)PRkPJXqQ^%c9 zH8G`TbTDP=gyZbr^z46<ot1UW#4*PlV`T>JYHG%madx&e$%yY#@Z*K%i{nv_TgMlQ z0wxA~MN7Pri-|oy#}zEifG3-TCxvP5#2qJQ7GSAze%K!D&0T*do4%Jj3T`4{7R|1w z!967~FgT>ZM#v#0s!yLoJ9ro+js4908Akc3XXgfIieM*CeuMwT6z2yx&=HI>HX`M= zDMT=qfKm&S%R1ZEE}+fJg5CnrO=`rqBdL)ti?G<?H9?a!8l>lsr#+8lD-YJ)^JLp8 zgQbRy+(Qn^Y&f^QOC4FV+uPU2-~Yg_QbO|ddYG7F2u`Gk51(wBOo+Lu$%iS5kBTLE zcL&J}qjYkAH$o5xE3~Hnu^3Ynh_)X4xEWOLmY&0WrUad@N8_C<Tl10qysgH^a%i_x zIZsN=A4<LM2iXTZRJxqr`mmLll8TgOaM6eMBMD=r8ph2K_vvr+DX>-O*X9j<D4LT< zuG6SyUqEpyE4mzv8k+AbyzYObtKMcWR(GUpgEz95_iF~B*Z355TT7FHW(S%a;d#-W zile!r)m@ohZLluo8xysM4QwX!8CjdOX;&eGAyYn>6_u+G4{qTBEcwHV9qPt@9#*ce zOusU(_XO)g@@+(})VbynoQ{&_9D;ni>buuSexKxV9o5x%!0!qbzFtE>qgp?VZ&>em zGq1Qhcg&N2tzhNrIruB~F+E6xKp)HJDHCm1?b{Rhz}WfRIM<hkw3ybtekxcDqO-oN zqW}_d9UI{J`5gbR8ou5I!MdOQ-IC?=4WUk+4LX6=ds~mT(_fF%R0QwX>xs!pa^}yF ze4!{&XnR>QH|6BQP%p2tZ&<?kDi>>HnQi$P=4mk<_5@ld{RJ(HlB>O~&_w46U)2Dq z(Vz3F*+4wCTSuyG9R&CiXsLcLK=IZUq4g6nB;<ex84U!?M-ll(0%C3H8F=_o*iVaI zhc{eTT3kdT-rUi2e*Qdywf)bdvCXD+C$eA9WTMJH)yge8RiJNhiBo21mp1nIuj~^z zZU7!ha~Gzg+we59K!YEyu-P+gx?pEHS<iHQ&*3mJXdG@|esO{ku!*0{Zqz#>X%u|8 zVh+CYQNJE>=s2EbHP+<q>*{5nIAnl73&Lj-$$gOD{_KuNFQ)`A$-M0)i=##xq!;sp z7x!^LJuLREZ)$@#wKTQ3Vi{2$U<<Eg9QQnK4zi^O$$rg3Bj%5_-qux}K-VaH#@FDF z#qF^9iSunBws((1qnga#+xkmb1`zF<M3GSI?G=yyvOuhMK4HNkR<EK5QVE-7Xl)Z_ zs`5JFR>JkT35T`>ZtZ2UC^=M6YRQs!sq({PHIW3l&?{LhA<~hymMo<Vkn!%UdH8~< zhZVST?;OX&Tbfh2dP@Rv6DhD=ojfo4%ZRskdRO(X$>&*8YvikoTjxZ71>TBNCZ-7` zMRb%r_(viSP~H)&H$1v`fw!v=HsJhD77myB#C$HDrxdO{BQ(MmZ$rYEqj_T!e?^lS z7T0&X_}{JPJKF+RHL%$0k!UGulQ?C<FD3U4&_jt%ax(0$(;~XhBLhyq_{VHnHv3tK znj_eP_5KzBly(dDu$~Kx>`atJkaCQ6`-ZUQ1WpgzkoyCndN&Z692^qlD`TtI*bOp! zlOlmpCs($e=Vd$k=Xr7fuL~VWW^>rB7~=yVFDKcb?&R>eo0q$bqlUTZjhqlCY6t-K zJp`mhdMTi=MOUkk>0RJ?Z#kQuzFQTHypGPhC;x;7A{SL!6M&4r612fP8GX3ieL00P z=cZzB*iQb8PsE^BqQWP8-G~%*lr%48z@iyg>2))I<Ro)>mw(b))Pd}9as0Q^9C7~V z5Ij7@e1PkE%;LC07nt4+V)HklH!@)Yx9SXWc8)Yg<`mM9<e@ynk!TqQR;z@hvV)xg zqKGl=wS~=2Dh;846~P4e&;&)$)af3ga+)IEJU`_e>+Ku~(rZ7-RsJNe_9v+`+u7g4 zi@C)SJVSiRG(UKLHP7>t&_h^=Jvom@vzkz1Eybl*R+G2bpWLCW#;WPaWtXDZ2-`gg z0Fkgg7?uEE6=s6qn?xyh(_Ea)bnopkGJ(f~f!2Y!An!@Mi|gpSi&-O_F>939Ylc^( zJn_-(3(SS60qN-ziRMxXX7OihS9|Z`uZ6npoF1tCwmHg}mdnk6hpBS7kT)FtL6wZb zwLXb7LK&AM^aZ-~*LfAWkb2;&eg&1>kD=P|U*vJcvQ?dPH;rY^rH(jQ2p<(Y*h>5G z-mKc-S*f?xO6=(|^KUZQ+9{k#8el#67{59@*!4uegFVean0jfn2gpX}<<&D&Oz&41 z@LU2P-gtD!0<H$E*h7^3h5y4Ln(%oQ=ZTpj(N)%WCdA2NVwB=E;K>~*<J9}TS>^hB zv)%=Pe(!AS#Z1nQF@#i72idOIFhu)_+e^$TURLUF{bN9SezI`9P2*iC0Q3JdsDrZc zTxTXzP>PuRT9WRccNox-jLR+L5B5!p+dy4ptIJq>m~<IuA*E%|Wo&`vYfF_6TdF!h zO}Ry)_7*EYeze}eZuYLnjGHv(xbYLE4%)4Bw-HhYZP7X=q{eO8MvOgn%$9Ya84O0n zH6evEXA2-|(wMPRCvRC7R-d#5Q?M%FE%@GU#h7EpOkqn-XjOl3seMHV_t^gn-Qtun zDVkYREWiBc+|!VDg)hcVnj+N-%A1Mf#*Z00LqAZQOa+X_`8t<LZ7Lr=Xw&CN;WI9E z?Brvtwgnwdo2G_Wn(dg>WUG}yMZ>t&<EC2GO`EnS8P*`>WMx$k@h9NVIJb4~T~YH) zt~z?+xW9}$?ignZrdwaN&5XxP#iF2(=|u+OR-`7K1tjY}-&k)o;Fo>r<H9ukf>ar+ zg6H25{l0&)pLY;E!2adlK`HO>GOyH^<g9f#XnD8Qp_dc%pK^?vRf&A%_y2Gg@nYtj z2#j95++0pI$e0r8)+2fS3cBNosX3!a3h%?rCuHBTrsAhb&=d3a$Ige0LlbkVZPDL+ z@pqi!u!%iRNGP1@zmYQs;Qaj?uW&WLi8>*qqO^U-JDM{mHqgy>=Ho&Q)Q8_P4HcNh zMKTSQo9pmCVIJ#tg*D*kibEkZar45iYTeVkb9g;D=qfAiOw#A7nVnITqLF5%DuB&W z3v8{q$>>cVi{eUCTw!jUrZ7A67^yb4F*VBPPr*q78i#rZ(_;Vl(caJ1QdY{r*tnKi zyH~>8IJJy^b~6v)76|<{w@+8U#pa2wDDTYYGqeoqrFN}!!lP6~Q@-}M{#`g#B-Eq4 z-c@j`!_e1ZiO;5!W*oF*Oyf%o(D}^mX5t(ZiauP8jXak?WTFLY^hw-oM4u6S;+d06 z0*#;5HmzVw3=D=jDc0iUF7UdH7R$(tU`n1Ta?xw`+6HsO->@Xxx8^I-Y1tOf_e6Mb z`a=Unz4C7aR6Rqj1Ing!i9^P5v9s_&XAf~qp_Z{E%eZWg_9kXtj+PrN;l%F90uQ`k zDrx_L7yG%oMh1SLAn~B7d1sb%LFS?uzJTU14xN-|u^bXSmO6bJIU*`xF@Ur$vzq7t zg@Vxs^YiNfwOYZ<*X&u(#Bhu?lQ>k&G+%coJ*Bn*mW}9FE&sh)7!Hr+k1Js26Xsc* zHN}p7P>EeTkE{U+?9=A785Qc>oRQZ^-&QfBzIy@HIe?yevoK|QD>#-mC@RRaMwi7B zSaRSKn_^z5nLlW`Tg{78tbO`R!W<0EYq~e_JkM-8u0~6%WQ`R9Cj>zJf|%#pKe1oW zlYK6<W-XC<<#10<Jg!m_<${75W+Mrg*&vIUt4KZ9g$!E6$YpWh4H8ODX7;(_pT1-> z*w9UggZ8f15GEiXdei8RBFW=Zn(45$czf9Dq!mi6=wmjv0hJ##Nn;CBoj^*Nj$a%5 ze9!OsNaG=<TCkL7M427X!o{YndgnW0FT(qH?EApwdT-yx0-Kyi17Pb07FwMwbz5`& z@r>g3X7E}qb3S3Bz}ShT2JOauugOC?`EqjW1!|kNf5isd1O1FV(HsWS0JtPy2`=r0 zTdvH=9H)9*x2w(H_y3Uh=J8cmcm98J&;493Hz5gGSww^T8gQxIV%wR=cV=wRj-AeL z8l34^ssvD3gs^WK+_f6Tt!e{m!7YMV7YyzjLD0GZDy^UfcUz4M?*5*yb3UJYKcAbM z5TxyVf4}($azCGQ&gU%e^WGO);hw@l<1etOF$&zAYYcRd0Wf@bxm@Nt${+&*ltSXi z8HC0bn!9j~(J06SJ%9@^a+p8fK$8Cmol>le(jO5FQ3Jp<u#9SOCt3%BDZrFt=$mXn z2irtrd;d1@#5xW5u$UfP9s*?=n{*(ADQa@WGwsOiETX*+CAbjndWy5e>3%oP%R?1A zLgp2Uz1r~m(spn6kzUEqr2+{PAKfDM`22FASrH$!GLHJ_K@ZfY3H&AP=1DXY+35_E z9rbl2(vh7Gev9nb;=vYQK@~f+a6z;~tx^zDOan(qU570(Wcr_nE{{;GkFVF32dLd$ z9Q2v=%#C6#ZhJJl11Oeb+Z`d(9uh<eKMg&&XmT^3AHV~=(9M651Dsq<f<pYifrw(W z5tJW1lNsU=Axk~hWm3}tWcK1BSiIApzaf<N@4^`lt%3uy4ozG`(rhLUwJ`Y*`ucxs z4nRuv^#oEMJCORMHy}k{E@R6i3s%ZaVgVg3UV`GMC@U=<Q$}j*ZqhM8$a8uIi_ur4 zk_}ZtauF?ZUvd_GWPGo+6fvn3NVjv%HSO!G&{Q}S*yZ?sjMAY>QoUVaqFd6K#+IfL z-MC6+c1Ies4_ffi<ZvC)5MX&BSATxcgLP;dd|byF`U6``n%&0YI#7Fn>&$OhAC1gu z%3~kbmafB_%il8{(BbB(v0%7$I72|794WQ*561@4KkamsnkEcHjh+ytJ0MDOms*=S zQ4#5YkXp*9af1Owu?ZX%M-V~UY2@P|C65rbRwl`G9DAtRASdxjrvJNt)9opQQEcP^ zyywcF)$92?xD55O$K9^S+r976=6bx<`yQ)Y4`l)G<*e>;J>Gy1%Ia}wH!Hu_^$_RO z%O3Z+9<Om+-SrTRhj#b=p9xP?S+}bvNtvy;;?gnYKzsn4F2qML#Qh92MIaq<Vj+}a zS#@05*5end>-QSeQ@4)~xa%iMkmJS<$7NiD)1@tQW21aW`Woumignn|we3Aeo9o)j zXARCdd~Mw%$yh)s(rgx`&cC+NHr=u)N%YX`CX>6X2+y87`e8A+>68Yup{SPsb$j<! zHoA69s)gn=1GoIjtS0Q5ifkt0a1{Z$1*rFv$cg6YCK{89uNk%noOm&;VG`-=z1dCP zK?`(&HsZTz3H_CEQYHlmghtioEsS4aaNSB-Chk}6t_PJ)v_wOta6(9!X~gLji0N#l zRG@Mh+|Qm=CYqGs5EDoGm7we9vPRJJxX$!b=aU+#?)LzaR7L7&Z_xKpt3Kp;i(G7? z+Pvor+J?$WM4iA#qjMc<c9$y_))(Ic0@xG<C_o!;+RX-Zoc+xsh%ajM2jD{B)~<zz z=){I7)QK<h@76*hv67@##A?zrqwK?6n#A{Bit<VPb~=bugka9G#r85YMGz|`!?R(| zXS#(>Lv6aiT&c1Hu{{OmtO`Uhx&J<UVxuW+AUMqK+WW!I@@^M%#n>k8-bMH=gAo=} z`9?pt%##JFkl!+nYyqaQu)tOh<Yvni_rnR+dVDrRmaE?zDJOw^K#ZE(SPsm*KhE(& z&v0I)M5Xnso9Z2e-3rHbta~8+n;~muAf_t^s{s-7C#cZp3&hP2G1v3y0f`xr_ivog z!0#buGkJB$USSsFGhQ~1nbndF@nFEVNzK`x!F6`LcTZ@y?Oz<!%I^|$GwoU38cYjJ z`fg1A8tvIZP4;c;Xm-9G-*=gd?OALpSK7_TPJ(H<p4^{QacbcYjm0$I!8TsVT^y1a z$v1Ig*uc{%JgQ9~(_S#YUCD>E<5)ne+_vb7yKT|2oX#dxthHm5CXVI*Mtle@d;AR5 zmezQsm|Cz^%Cpd>cUg~rJvs)7>gJ#ALblGcHa9ZAOIT@>&Cz{u6FEe*;Pc0U_i<1n zLV93g1pkAeD-uVkbtyRDrzF+<Hru6gly;(M7J>uRMLTmW=5kq*lh_oR?TFYHFjfF9 zZ1cN$GXBi8PP}nl=`BT0cV<4bMn){Y%}67flgJ4gBw@Ha#_O<2-UY#va^-XwY5hKx z`ikVl6y$zf)*3X0Ga&P&9bh5O_}K$!KW~LG)PBClu_lkE`@?w>2jqTzkR9%_vJF8; z&`6CMqn}|7$^R6*m~$-v>}u|9sPzsVW?|x-fgqj_k8cdVToVjnr~F)8gJ{Z#d9K4> z1`3GEP16|hi;7+t!T-8F?}K(hw>KHE<pyj(7CV1Y<Txy>(?l?cg-5qS^BgRE;k9X| z-m>cLlL3D75x}cZBT`EIE0e4?%>yyRCCSt%Y2=S~OTK3|k5wrDZl-x2p#36TjL#gl zaC}r4gR2p9s5v>_&MHU5rlD`)oTc`#G9%EE;RlhbC*UsMpJR!#mZigKWqXT9C;))g zOp*KqHZK(PaP_{L2&nOd+4Og(w)Pa8mxA<WLV2MVkDXFGjwzr%U?@wGu=d6J$Xi0N zc1(XC)^5fog_8CiEXg5QYfK-QgEdP+d{7~jfU8F-vV6q)XE+icybv}6_!3|~7Z;ZC z0dtInq>sxww%??whbEXAZ_aP${^68@tiW=wph$UW-rKz+zv}+dWPdmSQr#;rIk%_J zC{iZ-D&njt`Z@`$V@f3zPq3uoPHI&68<xJMT&o6+kYLk<dbMdXsqR%nq%7Ko3UK6J z<P9OA6>2V4{TTTNb@jfs*M@AET)pzq_Uf&of{Cv4MGY<Xx4T(|X6+b@2h2UC>CgI? zF~>1wZ$-EX^ZKpDm_GabLaAfDKumTWOdp>SMCJbYQ#8@~Nx~^qHJ-<$vF&La?IuJq zS^zjb&B%wX^fbQlx~_HWG7n-O4uHBk0LN|*sbK+!!$R#L;lI<XL$dfWeRa~S>;5C( z2oi*Z|Nrrk957vCwgUDP`%@(v*rJ4al~lSoO2zP>gEJusoxL8=O4?NrqbNGBgBn4r zSCoxh{7baatA3+AfWUenJqu}J=vz<~f!8&*zLSQJ@X1+%-18kKn5akaI4JuL`^$1} zGgdaJ@)7rDhqzbHYwP(+WoWz*cb)kuSo<6@eg*)ZUP0Eifi?%1FGCHYh+R$C*k|)q zh}2&28+yLrxmXsrLNQh(QIY|xjXxLIJH1pDesa?k`)SH>;hR=5!Z!Y*e~*oAn~%$S zT8iJKI~vv74XK`J2l|{k3;x{2h54$Sg_Y_34&Qb0o5K1^XSr7zp^N~rID~>?FO2mY zX)dgfj}J8;NKguae;Q9M!SgD|d-Z(nquarfdIeGgVAgl5t^oNIlSsx@pEmj&w! zQ?<X#N3zh2W7@-L#zz@?QEpxwWA*%qG!Bty+7{cOkid}a->@_oxVJg@_JQUtB3?Pl z&rn2g&{tqx-Vvro3<_Dzp<V-!4~LL<jIp*cmc>}j*|W3Yc~_Y<4^EzNw>sc=fb&3( zNS~#T8+NdXm%a)CUnbs!xveB4A|U%U*`lg(TeF-*NWyVEP;LoF-G%4(At#%`YPCC3 zt7Uv&=_ko@uvr9yFQ)lr(wT}8dYB}JoCH!)cdH2rPCYfzchkIEx*<^B4c-s41+acy z@qP%(1HA8;`imMGLuXcE7L4VJy+6Cg+1f<~Chg)=fve@IN00!<*bu~|XXk@lHe(e! z;xszSf&RVZW?&=`5iR*(L%$Z^zX{`NwICG*n07aW?Lx3pZN4CjO_J=G0Ysqz@uAM5 zhcvTTa;^^c84k9D(lxb-ksvg7+n4rabW?%PK-!Z5JSy!Gjc`hXr0UQ6M=d-^ZoFY1 zkhYeS&4;f%O(9bMZbl_rp9K$)qhrB?W5i2VSTe^sI{k;`!NccBIbQgVLR07TB#zH; zOp8a%q}3)f6$$s9NHI+80xGHa!dh!=uRv7$(XRekzs_0rOKk*0kjt9ol*$}6(Yocb zHwRmgxu?p3(4%9)ou)wPgwdR8@Jna6N*euh92;WUvC!E%PGFcfXc0G22F)}0AN9qq zxI^nfo;i1Rg9}?1z*X<&PvS<;cOPw|uJxCB4d!ElI7+$350bFeK|=VlOHq+6JPK)^ zrCe>#QZ5DGlnz6(?aWX~4HbswU_7nNjVFYaQGA35b5GD5??=6cCi6jl9XStMLm#Zf zPucE&Gw#Y3{aW}4AtVLKhb3D3MGY6;g1_0k9dVKS>mYM2Dya%{L@Vdl!AT7q=}xU8 zK}HzmyCZ8Xa6U&MS!9|Fcw@^fZ6-I>5~R?gy2rA`<_wIV8AE=DTwF;;hXGy~^^fr; zuV|h=Wxj$*CSWT+yq!A&3WQ5pDY5Vjh66}1$A()fR&bRkp-}-y(6AflHHD7r@3PM; z#v!3SJge1h9oGRZt<{@b{c#kD<w6^29!`>buZ2R^?y$xnvnhtc>zP?i-oZG+V?`Kj zwvvE%*W@&IhfH876gYm;i<&2A`GWYu$}~ma3Dzrw%+d;l2<w%;Vt?h2q}L9{49K6G z4Ez_#9m#}<t?WHqLkgyGOO@c7!XI^V!%KdbJ8_vZiVP$y5&UK`*&(_gq~E|_U?6|m zX8_Y12=`fXpP)?YEa3*Gaj>CE2-x#d7%I;F8Z@gw<SQOk)pg0lDQoLh;6?w-`D%<C z-hGEs?+NqscEL~R_&((L%9ArJZ*oPU9MA`w&!#wD<;+5HRs;0g8#;!K<s<tu_)w0T zIv~t?b&gqU6}Ju)ZL@g6uHsIxt$shwO0=r|v>+C7BUr$4gVsPH1`1mFkVnA&NH7L? zUkN?;O&+1PZIrn4>7%u0StgMNX+9@PAj91Jj>@;;gSMQrJ(^nwYC8rQE}`c0Fk%tp z?o*E}o?6q}@YZ_$g1^Q=TI0TEg4F@6n$?Mw#H?m%ds{Mg_bj`|Qke>z2AjY5n|_hM z>HPMF4%4RBv*{y(O&@}y-|oy_JR1TW4QSxM5%!r`F{>#<8z0!mr;VQlwDHZk`5>%X zvtWL${eLMrencZLa#reIAz@f1N3b%K(LYB=qH<G6N2kJkx_KF?y4qX`O~@wC(Z*tf z&8w#ASoF-e1o{w=))saT00D<2RJYR%QU!J|xTfUB%>F*LufM-%Bz)fECE`g!6k$gw zPM`p3)t$aEfx)huD=oVZ5aF)0?)>RylJp#0%{=om)zS$&SuDeqMF8UjsDGL%-Gym( zZd&-MS?cxNTt~hB-asHk;2T-Szy^Mfu;u1DOmlsGrbQ6qzHluIZRSpKLwg9$55a(i zB4eaE35=`_bNjGu&fk%WOBUSKY#XZpUz{!?{NCSzfv}&3C@s$yr)GBmzU&>#K>aQG zvIQ)6fcX@gUx@!}lpn;oi8jKIXEyUkqyK-~PW~T^6a2qZ<9%aBD@=ZN#6)5lEfl+R z)ArFGIUA>$+peZ8V4rep=5#D+u`o>gtXS9!CTCGB*-RbGnF_83pjwcWsW>O+OUsw` zxPo5l-hvf$t9w)Of`BDRo2>$t;BT-^;I7M&I0D>dv9jbHY6{P`ivF+)Kg2({J6KK) zACP<j&VA1FSo!4S2Vg#<wxea;-%Fx7cEJX0XDfb&oDxnQ9$HtVVzWdws8)mVd3YXj zNd<u)31uzAVAnywqTiKXW#)DSCplCM<SXSwWx#V?f>fVoIL(<Sl22RgV&GmZh1~+j zY0&uWZuvaXbho4uRDE_ym*br3IN|h?(%}=G!L+oZ)-<><$j;#(dD{a?*1<b17YeR@ zx$vJY20||6QPO-&{W^%vJF^g3w0UsSk<DugW=ZRAHcuYj+ek|xJpL5+3$a5PQrf-F zLCj4?M*wp(=C8v~Ne!6hkHdGN3wvzuf;Hg=%5}#bWhwK63+JN@NiQK~zT4W2Mo_KM z7XwA?>$x*+7|8`52|6rLiz#{2TF3(sv@FaB9HwSErO}xL0`;e010l=01umnCG(0~# z%;&OJ23*$7luqyEcIPte*zImLmL=E;*7uv8HE5Rb7Stbi&1`g}#d&pQ+-MvwKF#13 zc-Ktp(f>Gr4R&cFKfsWSbR&Ju^0rcK`Ve!$_}D+?lO@|8x=eyXdN@E)7n0l;<Skf` zi2V$&FrD(v3^^2!6@q9GENb|B0e`fc8+mRe`g$DHKccp)RMl4%bTHCj^ID_aFq7uW z0w)f>M$ANs>8oh_N^>E_E37DY1D6To=8Fj>ORy43MdB>3SHNZ5ALTM^MF;e>&io%; zzqDyxk51~JoY!32kmH&YfmLB1u_)SVpg>~_=4M~iT-%@f^B6M*nl*9i7K{Jxm-tsf z`lT}k(B^e=6v*MyTsO1D<yH{rmVCzt-ShkS0>Z{Qoj`6b0jxWO(RCYg2w=VEjl&X{ zSG~CxqL)@_4cJf~ip}&N;Vv{4pl4V^&SiZ%J%P^aGdgqgN^(8zmM-rE@#oM(ypqp% zXnom)1S*;>VLF9v*S*~#4Wpp$<_rmCHrv+-{R>;MB8F4n1+&{+bf^Gj`1gE3xsvG6 zU6d4~%1W#qY;l#jnnEyEVr!pM2ij7^m}IDGDNn7zKZo3I8K5jW6FSL7eL($(a5+05 znaO|AEmevmZpb4@Lm72b1E2pRWxod{*Pz#eSV>oJAwURTe?S1`%&dtqCt!uiNm<?6 zhlxHn!_t9UC}GW;XJ=5?43t4)Q%@+W$~@^bSuf5=c1V-5qK`E`{9#6o%NL@pdEop0 z*4!4{p%v7r{-3=>5eYWAnUnB&^$ZphdbM}W`5YCJY7N7}qg00TS>o71^1BY(IU}R? zH`jZXMY$)qRw@q8CWf@V8NY&Vbs!Ow_KqmQ(l;yZVhw=!^Oc=6t=mm|H|@|<e;d}8 z22KsFEWvJo_N(42c}Q!0W^Ox|N@lk)J7{(TQ@fBVc^kWsDrKg|NnBP~^HM+AYzoXq zRn`Ek`=cm@>u{P=K71pajxX>teXN3g*$m5+m^FRC`;-tdchL<k@8f+GolLL(5Yci| zY)M(toYvp@uLJ*~fMD*<&x3$q!agynD-N1SMrTF(!n$_y>94Ud4JL?#3rf0dpoP2i zbxD`NMjJb9hf$~`JnUEGQS-w`<=#rKO#|FKM7zVGpHe%zxKZ5UGocZF9~bJ8-A92& zeqgbTdoFq^6E3=)P9e8=)iZDrRQ{~n6)h@u!v-E@MNnn8VbiZvok{aEIaHD5snk4Z z{8-T?oSEH+hA|{s6D>Y>J~u?<;5jM{vLoa%G1tz(xmo^FVK2nqAnxxX2cY|FCa>5a zn-FCMbr*c2XtFl8yR4#>LgoM9<11n$i0Q%xewIhCLdDNuIk{&hPPc@_ufuN4Y2S|Y zwktoV*URLO)}s}qU1A+?IqT?U(=9e#pHyM0LNgS3<rZ(40g6S^ZXy6x+2%LeH0~#% zN~Z+^Ao&YPMZ;jK3rB_{LRb4L;q{@^cS=h(akQ_?z_?{Fj>v&<?PUt7EHNKb$)=23 zk!QZ58VymleZ_wc=d+`O&nm><eU^`0HoYwnSe<ltGhz5uq>#Iw>@{)rZ5{Z3Ka}3p zjO*KohB4Z)&hi&t1h=RG$L2*`{6VLCl_R;cd|>O$7REuZut*N>yBUVZ0B_#t%N`AY zP;!qH_3B)zZ77osP84JId4Fk)6;`W_U@Rrx#4nng7moxS#-)t90vGRrhj`_nn^$M5 zI0YlWfn_I|XfRh`=m96Z#m{26=h6frnV>B09FnwLIqa3oeG_&x>M7mcG-j?_917WO z9DjD8lfRsL=8sY)_wCAVlet|2Bm)0wK<ac0NQ{ybDuG)El{!#zGdQSBgNJ~_2Vl7z z0KOc-xzjD<rDO`NJ~XOB0F8WzTyg-OgTS=rz$r8`u%%S^-M|(_02pPNSNIjcGfgQM z1S0)$&fk9EETkh7i(N~NDGM|<+k_%%h#*$IsAvG3JN@<Ltw0(DisL<m$x&EI8N?_~ z2jK3i4Fhg28UTXoRp^o!4La<60th?DP&ji4M`vh4Fj?jE1ef|?l#UK{@p4@nSvblS z(@#tD(J3ybXcLucxmBB}ftx;^-~y8s0;5GHx>&g^ZrfdOWMfT1Z)<+R)z?GmEHV$9 zl^cR;e!C0Z>#+;w2k&-?gcNQd9*5>O>KY<DzD-0u$YhcA9^fVVL1@L6CGW8nVR^ue zqNCwB1T$bwv#JU+s|AiEviUn;Aw>-?ED}adk~W}Q&=I8%asU82Yx1NRPz@1q7?~5R zIXKX)4Ui%sI=uMtLR_@`G_N)C&iVVjfayVji?<^~Nc-1DkXDkM3y+>)VbPq6Ik6`o z4nSRoXn}f^w@4$dUWRw3+iw@q^$K3Y>+Xi9&>3GDM@<=yqAW3OMAwNvULDf8vea_3 zfc+qU^L)7XC1Y9wIu|5?;W~zrz~sF4J`cA(I|GZqp!5z1X3|+a6dCJx?Cz?kJBD(- z&?N_r$o^8+Rj;uD?N)329=aN*HHLX@CG0Hw#@AS$FIQV_cNYSZ<ibBdpcFwS8`#B) zS`sOaC$)@?4I?zS&Uzo4hYt$ww!5#*y06jX8zQ|*zmZPz!Y$AZgS|_bN+$(Bm^BP* z=yL759fpg#2lwR{@*AX|e+%ReF~mIW-_~VCHpW+lec@LBl1F8L*q&81si1lqF?fBG zGk8&N{uMtY700y3YICohmQ?O;b-J?M&r9xupc;R9K3CxfU}tBqpze&#UZLbNeu5yM zplmmLMF4G<>lP}txq|2|_z5sTH<>T|zN|ZyFo!jvVDzo>n=72T<yy4Bse`<tkqI-x zI`<t8a|XkkOq>H_$^Q~30G5Y~JG$ZDtgMzvIiftYTTx1~@8-OTSUs+Sy~U#a9Hqfb zE8+uyCe#S}yNifM0_QlM0YXkm^ESzy{C>PBFr5bmG{YT-4<&x)3Wz&OiU@TV@|D** z5E6hzHx%B5Bv-2CatbX?w3_o*@YzY478`Q=icO%~B1cv6rKYtiwx_C9_5zWn4>mXA z)mr0OnV<aA+)jrqY~W&+gEb&_D~dE54Y;6X6gez2-NfGh++;s#UYx81W}rAbp54qP z1>Cht8Kb9m=oHgzDiU=7kD!}|$l)rQFejQ>4gwbsc{iw?&wMpazQ$NAT8%zjZ8mt4 zvD_Pg&|J`W15nZd_ue_J5kAuXh9A)Hbg+Evdj!uvH>c6Y&BF=uce24|$&{#9eT*;a zokOU5QR)^xIKUj%V4>}3p!{Gjf0|ctK1gEsN@veduTz6wm(a_mnD$fl>Sc5A@-beL z3w27nr$D=bQr$mB05uDG2%VX-;&_S6wVb<%Y+*xI!I%mUokNmP7nRR6czx&m7G0Ek z@@+WgBlDVFG{3%;&WHCg(fm2<XtwODWS*y!yRU09PrnSEE#Efm_=zW<Jla-zn=<TI zjgv?3T$vB$`V0@hQ)wP|I`QVP|LN4BJDDYNr*_Xz(il08@M-VV;5(Z>^RJZ&G@3?p zXL5>aq@CIlRb<(j3E1qac@rj{U{iHQGJ#GTZHq5Pa({MT%7r`MrS=QYD7tlAW}tNK z#>}AP-6U1+xCvvFcr){uLM@pzp``otlZ^5g)mvyjW!&*W&d_vS$4qb1dj4wSWa@wU zgEE8TP8fa4RJ%x}3>|ONh|(dF%#`_tbAV=&k?OOdWTcUlqN9#K-qpO}X}FjTNkmzg zKY?^I)FM84^27;tB8=+iC@rR~iXHi_v$K>k@(H7l_s@vhPobQt{0il1Wi$N|S!9mN zHQ7l_(-^%=8Lu2=Wkg9!%>~nI$uhN$n9~?s%B%S#cgxhVaoVz-s}z$pCut$SNvWMs zNiya1Oph8$*V^?tvP=PXDL(kVu?1o9bW;u^TZt34LX|mNUB3LTozd;l9jPF9f15%w z(?3#)rAr3b$lFsXJJW3@*~meyvmC-ua-qLdq66~Gr4#F2>5WLcr))ctuA5WD8%Rm5 zY7PxCPg?0n({|f*BTFkbE7=r7r}s%ZrldgIVBhup3MrEDIY9qQHI^a?Bv;03c{Nb% z1?h{DW<APNxC^P5?It~k!+VLjkA&+754Riq=4`3!XtIDx<YL%7>HkvoBlu#aSyE6B z?41GQHPC#~7aNRuX_^vWypMlx3CFWF<(9i{D#c;=eI`BzcC_W0(S{*N?3FN2P}s$C zWU7fh{HH!g_8!aZm)gs{iBto>pI{}Al=-$#<jn`X8In5IuJcc`RU=Ytemrp?PpBy= zy*&cWlKCoN&s@JQs3-iyGoQ}raAk5LiPP^V3L5_HOy%=u7uv{=Ks*XL?(+CsCLd&k z7yEa_%gpPipqMegDN^QyV)G_NsAzvLRv?(vNATj($t<mGW)jhpY1rYD8S9^n&di<+ zOL9kJ@51Gz%y4%@wvj?2J$Ub#zA)!^%<0g!V8YE)IaTHV3GIvRHNC}+8ag4)yE!;- zq^vt9`su9}lY~mEdBs%$u?`g1;P2r8%kGy0EdPT_S7ndFyv_9u=57Nm04w|TyO7X) z07)-O@YXyMctd>?b8xkRjCp0=9;O|Og|7cwcoJpbb9iZ>-m36cNZadU3o<2<FH-vI zVwi0d*Y4)H^VwD*XiuLH@6a<mLF}x+Tf%Dq-gRm4F4Ga5)<`bWz5?UdiM8vReqV|C zfufJe39ua~+6LSdnvYanLC}V^5oqg-LYowR#pY87VYfI4d(MZj%X)+`N+KbLSqQ+a z+V!A7lOYVy1Dus{lUB}C*0Vgbna%gN*8$wy032cCN-^vMTgTrT*g{zBZw747`@r_% z_JFNE0&MU3z;<(fQkGqz=>XV-4AZ~{l9m;Uo%;jY@9qFjDv~^N+tiNGj(g_ASh8IJ zv&7zS2ZmIr#=2i76t~H^a^~^!Fv-1{EKn*>U5Ia4-^2(<KP$p5?ux6{&K@aqwUh_w z5^R#pIA?#?0Ce#;HY8ik#)0+xq4eU^wWSuG`I7WpYI0gtqct9$HHIP|bgd=2M$hjZ zQ0G7A^69~+19Y>R#x%Rm9(juPM^-M?E^(Oes>=PU<AEiit)^^rPR!a!hs|xuy~U=H zDGxN)&4YSELfhg4MEAb*$R1Py3iyJ6!u;e=o>E!afD-SY5!*|vWZ$2Up{=`NE+NDf z+RS_7el0)M;Q3KNk>2!Fm3*jk4jU5Qtv^7cle{xa3?C~o=k}2TKWWaNB^Is1{9Ltw zP@vT&4&mk<YR)xH@m+b}0rB0<+&Z6+e=$#cM9#0rD;;WGIibN4jyFiT8-f);AVkvb zjov;<w-EETz5lFk0fwLuK?lJO(V{m|%^6I~;r3|<a>9gs2zA(>gOCdV|C=jsnKClG z<zUL{7%WK&HZmC|kFekUl9hF({LMb)cd$A{u=-qnlPgXX+1uBt7X~g#5u1fpDT|_a z0RfA5$o@`rnE>o`Wvp;69QJm}WfgpmX2;@lF)AV`1zP`UWCh3CFBPHlx<D_cuGRu{ zC7><e8JpvF1hbW@3RTYUDr#78p?P2&tuGS*`9lQR+6sKf4c&vqHu;v-@dYVwovyCO zJ~H~aK1@>P1-9y4*t9^w7Uy?hRMsSmly~0VJJ|-a`dTeB`6vB+-%Q=w!!>ug0okF` z#=%-^D#&h=t-G^1aEDOT3l(=IOcn-xn<e7>xovWT`3R0_z@|m3NK!bLJ6RxxT>0dw zBW|;nVkxxv<x4{8<Jj0_epi+>;hZ<w{sQjLxsW&==LHpV*}e{iSh$UxIEu`R$^>m@ z)tMhQ=?u&b)>@MpDcXt#4^bL0ZkD8*X^@A<)z}X&wG3X|ydZW@yKWsi-Zin^K>>+c zashG-!G8`C)&dE;!xFzcrWT0U2Vd#7_#ilrJNq{Ad$3tMO&KX>D2}4Qd{{(64Gh_` zURuY8NDAmnGWlG!3sRzMXB<dbsKj<SP~Hw3;5oI}GgA1pqJwrhqaPmQ@}=bh)<N9b zE2m%txn~L&xktbgFr|UjntZI8smDIzi^EE6Q3nS`fELLQ?JNbAVJJ;^3MsOc587Q0 zW(*r$Xs0Z-ZU#m(gJ-v~Fq%<hH?mvGNngu}l$pN};%ATO@o7!|5kY6}nbH*OsXMT{ z8{2hYj&1)OvATOfOEQ6IxG!im3Sn&@D`x~PVXgk=xA6^3tHQiUA&@;2vT47z$YM~~ z4n>iWwJ*K_TmwrC@9+yH2kcJra}!ESemgNCX&COHjJ%lWrdb*&J&k&C<^#=AB*9*x zQx;cj%aVB193`3VyRa-pPQkAY*vovsg(h4#aWDQ00NuWUQtNpG4LJXWu-e5Ej3bm{ zCFRE~rMPk~cpge&Zb8<SoMWEG%xy(LSKRKgSaZD6oT_}w2{X(2Kc=&n3!wu)cOj?B zE7XE}OGV&_Cp;dxUrKoHtVaIDApeZD26Y4Dfmz+Zd>Pwtw0#<L8$9)Mq5AAgl<wdV zmS5T-jp{`+(p5t2jkGL4q)NyTa}7qh(j<91Y@NP`=d|I)j7|WYeBFXY*wtDVSia_$ z9q}P%KjdOBDLurl=AyYBjuW%T^SH@H$UotDhN^JRKf-<pD?Ez5$MSiP?qaWwxwL^x zzLc0IUv_BCCiiqKHa9S5={8^xGa_ehDWK7UZ7z`$acEWxOc{}@gitV?<*IyG(F6d) zj2x`iD&z^YNM|rqZxQ@(9!Ewruo%B*DL$XTRTW#YHC0EuYV-Vb>o9erOY%lz4il2Y z`ju(_?zuIAIB7>z@i%O8+ek4z1i}4u!mGFl<oU(UrhNuvTkz7lKi+92%}Djf-=X}V z8sib(4`T<G<Idk;o}b-<X7C2e&J^1;wzXyh#bG$nRvwj|s8u{QTapM{`D~uZcecKS z<Cx!~BgY4(N0C4G{x|vi?{8>Sk<`3MJf|$Rmgfw_dq=%rY=nb0FKKVrz_+47flnD2 zaKf^%XQQ}?fLq_QiYqiNp<NxMuV@fD>#*po(H@MrL#eyg#u4)iVT0eF!jvAJ4PNrW z!71R@#qqn)`}ZiSQJ7FQKxVwW0*=Qq@0xO!J`P|H$>iIaaxP*a?7N}>i9^Ww%t@kD zY2*w=`{S&Z04Qq%D6`zci;aMjYD{-%e;@8?e={^~XD6#UIvr1Dj&^I8%80BA-<uj$ zm?%kd;ua9gD!Zx+=Gd2!+ekI(X1xSQ&$e&vfOMsm?kVSm7*!%iRt?$$WqAmz{V?-; z8x&P(ZY{`q=lY7g^kr}~oi+49E$K*+Kc4(*?08O8D%1oXj@M`EsirmBFCsi!LiEXO zM~LifeI;ZLk;NxP;_(n&9rXz4Oc6=4mQgWm5Aeo?HbtwlSs%=e*3s;epp0rGFN@7p z(od3&-lCyz*YK>;{8Z^h8oWarJPHsMCXVGwbs9|NW3*L^XXB)gqY8Op_h4b45b<ia z@OsLmg4Z^a(W+p)SC#y(75ko?BifHH9?X$L?9<74=G1sATQ-~f6gRKOeIgJ+Qr93u zCsRk@!2bpUhx+^`=2ys$wA)Ci2p1=1Zkj7S-4KwmQ=Qx$)zd}A;aY@y92NQ?PoLlD zBev_19eSzn7LQ=rFt#IA@1)mOLf(RFHJJPr9VC`w+Ngf}G&zre$h^M{=6$-I_a5fw zZrT^^(6pn<xIi7hL(@AonQMBFCiCNaiUwahi$lUEn!V*?H{&#ow<QbBGw)7I-+4=j zd&9>D>OwJV=?%1s;{yRW!N!lMh~CJjD^2IDc38^gFdFi~=B7TKCr2QPMCrdVfTVoZ zkk%I(NNJK{L!<Pd(7eel*psf$&V(<p`XIkoCA}(8uVe;b*klDG)$&LBUFgr?J3yHH zE;<;$J5D+aXX^}hh_&BY8;Y*Tx;efLWk!1%7DG5t$SfN{YR~h)hQ3NV0;8=d|8A|H z1?>>VJ&Qe;k>cf|h!Wgsnq)c>XzcK^(~w|IMy2M={8qlkFj$_BJW`0tyn)TA@*jEn z@8;sZPP6`Nl8x%srbf$gVQA9vC(T>4I%wxn@!2U^ubw8glA|TrhNQ@H-!9A-K&8z6 zGxL2zsm9qhx6bK3BaNH-S^VUA8*{u|9K7@^%13%$&&xrnGVW1bEFsw>@^+c)8Y}Jc z=8k^;^gf!=>Q7I5{l`;suw!Y3r_X!1(_5L};d!^@phI^DL%%<x%?*uo`8EL|)Q1c! zBOBAoNJ)F2lS6+uHvA6jBR|mmB}RIWUqc&x^`z`KSRN-RqOruhK^05K;rul$j=Ele za+Fa76N?1{5SZN=peM_JudpE`aIS07#pE*2q|7soR($MoHzG#I$T8hg<R8YD)9d`h z*o(oR222GrZzMaMK{nFqiT<`s%8e9k^vnwdzBxM5<Yk(ar_4uA#cIx+-YIfUz>DMn zdzcIRXkU}&-WiB{!}VM_AO<;G_Y!g*NPPVxK5(q&dMNi0^8y6AFma6K>=ySCYg}N~ zPxZ+&Cqw*@WuX?+S!i^Pr|ajL+Y4}y)Tf@G+=dcrw<Lw~mO%WihhVGcYrZ4Xe}m~K z@s5*C@u^8-bg4vFEMruud3uuOHjvWfR^|?~I*^z^LmvXzO7qD~tfpGXIp|E7Qo_95 zKg2BjGElhRRNBL3eAd0paicc#ra1Kr;-P?ai3wMYulK%XwwBg<`|-s3l%i2;M2lxW z?N{dwJ`7b$tw_#-Q=IzmBS0U;fa98%6sX4m=Fc)Km@lyPY8M|U$aT#>EG1$rWzHjE zeKqc@Qf&1#?@>k-cR#n%D~dWCX0at@eU{ODNk29*W!8^p)4GUZUAJ*4Q@I9HkYOrY z`nS5vFZ+3#3Ee;6+bvZuPl7$09YWeW{F(s&-BJh%KW#L_xIdH`qUCM|<bacRY!BWV zs;k8IDRl#+y5Ow`u_5(M5e%5Tc%;|&U%Ys1uL_kDFH$Gxq8Ndp7j1hI*d;IW`u?0| zNvi!Y>gB8Q@lagclZWE*6DN-zhA-2whLal)!S7}mZakwJM~|5qIJMaZA)iD0TlKzu zA4L0m>V$Ff*oi!oV_>+A9QCq(595P}@Zs?D@ZZC%$5^;i)EO=O#(6S^pV+p3DeUlb zIo5@LhgKhXZoS3A4YS<+?8-+?o;)hLS8`Gd_nI<u!ts#@jiaWV6nQXq)ReK22Q@Vu z!wI7%A3t{3@j8tuI2BGFeVl#3&^yw0*o^NSjziVtQDY|B;?_95jhQ@d%2YXD@pl(5 zHh|oBs={B)Ki1<;7}YpR9jJ%xzXYTj4n0KA@WN_1{4oEoQ74a?sJhbQ^&77?zcp<# zE^YoNdHbtzWBea9NIQ+;&X(<`#z~B`v&YfP9}<VNP@Qe2liOvD4rwR192K#%yx3?l zY1HH?)-x^JClBAg23z`@7blFHd0fNE6GvIUx{Mo|-dN8y>j;PQ+vq8c<HiR?z4<+B zoE;&v3Z8ZG@C*67;VI`Y7tgo!1~JP~6Kvt}j89#Eo=rJ^+&Jxf=4mNgIr`+2{fAlZ zj6O8$CEsxq_kZ{w%^Wuk8XAJZBc6hjMsfB157@s?^1U0G1uGx#UY4<t(c_OFYd40Y z3wiMYX6da2_(sndb$sJ-Q^w7*hrs#x&eQq?zs8T6`K!^#0hbfT+0AE#Cr_L*#qI_p zvE6~Q;UxSf8%I(9Ts>LIgozW5n=sXF2H-M%)JgVDInzA(<cYx&#*dnO(r7zN=HGC# zioyqgH^m)Zg*`G##g97qxbdTopFA<}%%oiVlyUBo@wqAE#-E@sS8C2dEB%;gA6K!k zNmIuKf9J*fKtP%U;@q9v-oxPe{wZpB;l70q1*ftFcpuGeF>A@(*DrCJ=UtXCx6Z9L zPsM72{~bk?u{}+`9&*FTiN2qCKvk0NQYrxyJ2Ci`J4t-_xE=53o;Qn#YsUKn<N5!) z@gn4qitdG}q3CQBlt0Ydbqo}!E|DDJ<)7}w_w$O9i(SHsNT)Yp;|si!lzFa564)Sf z3snJmV4g)#N)aB-Z?De?MwOU&iNZwCvtzt0gxj(~w~u4tPf4BfUVbBq<<VS|qbu<N zPt@Z=mAWD~KanMc2V2H>p12Dh-Ps4a3y0+Tqq03Mrc4F3i8YMUrctmsky;w7$QiL( zM{fIt_b-+2^})kKGb<y3cM+W4ukr9Jod(z5$8?h3OZK%%ioA!<R2Z+6Byvbl(<3nh zsAYlq6ql6(xXq6UGVDi-^G?7IjC%BZco)<xC)DsCU0|M?@@rhdvB*3Q%jYdSxF!#C zV+jN7-VV#lqlEeITD<QHNvj+CF_ojpC359JLMVAFA<7zADCcG#t7zfXHnPFzde`pW zDXgMPzjnzvX7M;Opiq8spd#RFvFIl|<hjBW^7KP77v((Y<iSu_>#?0E+<-S8KA2B^ zB>t}PcKNaWNx~I=)=~@cezsE07?Wn(d9L-CO*WUg^?{LFf%N)(?kj>iGUK?<DX&Gj zxq@O#MX1_t9;^Ij1OO$5ZN*Cjw=j0@%vh88Y4cGkey99T6lz4nx5z6w(knZeQ!1j2 zpX+@CFQf)3PmrRF=NrjD$DW_;Z#VI*nQc?96Sv(~JXFGtMbwb&2cVeRS}%X2rc8k* z8_BjG>ZL02gptGkp$>aU3gt|-9qeJk1vMD^|1#O@^f9Sr%thqME%N@sY@LGEoG0e0 zLOB5(XfC5HnIPeXftZ|7N)##I@it=jtl_7kfsI^nqWYGY=ksb02U3q$s;bguJQ&;# z<IMK>nRd>ekNub5eMozt|0@KuM|k@m<mHcGfKu}!K1)*k-(3M@_Ty;ZVYPa2Nu_-d zH*byG;GBITi(EsjjYB0Z<_=^m{{lJvy<*$7kn88`ga?>ob>*<MZ6L2U9|5j!ov$l? zsJRv?Ojk}l`g!^0PTVIottXfkdyefA@87}N;(_6Ny_+u*C5JgA7kOEeuOPRSxw*eA z-uSjmK)-(sIfxU)*>w`@CqZO^m-?}SwG`-w?oY-01~QK&CkpUNO-rTp1L%HngTj33 zzY;D2DHJ8lcXeZurWzN&fo#?&cdK8^Qy}NJ%}wYz_4vba)*>WRALsp@7NSOXp-w3? zK_i}$+?$>TU&9xJiQYHAMSo}(q&BRSd5)<iI2Vgb@0)MaB(~?-+#M@XAfh~6!?hAt z*_hWF`u;)YYxn)TC^nyuTOA3q2bh^^QfMx$q=?f%E$GH^`dFdaSlOxv`W-9ivg0q3 z1%#bSnUxjoG)tPtiH$76ymsCEM)N0XO%g&m9i-Sgzm;8X;Qtox$#Z!uJ-tu{C^b!$ zjdo`N0s*lOsIMkKVeK0Gt5E(4#pW>Z>g$w1_)UHT|JU=sg&2CFBT%oW!P3fo^ExnX z6$lBljsf-PgYr5~;oFkpeyr>?%^DGefh^ZT-#*G7Zm&Zj*J9U^+J#?J3z9whB2URF z%W={`-6OxJfl6}H>7%W!0|dT(&H9E77M=Z>=l#&WEyP%`o4`t+=bGPSFRq0s%(G)i z^s<&0h2}*pVXwJTQ-j0cOzfnWI@W=5<i*theo~CY7W9FGA-&W+<OB6U&`9j^q+Y=) zY7G_Fg5!!EWlbi2Fh-?p^L2=k;jRycTaP>0V9w_{h6{#~9>rXXHl|qIfu!Ldc;5IN zqqJJrdxG(vf<U0QSfSX-Kg_G<kEE|njC}Pr+kOOh5_$a~$6!Pnz$Lj=!Zk51&)gqq zB_qx537Wm*H@hrnvnObVN;G9w`FpmS+AURR+1;KgdCqbQlY&y8f#ay+k|z^ScC%rd zg0XJ#H>};(fyq5a?%mqrc8k@2kYg`j+uq*18_eJ;f6=ect<NzIaRP49kNC~*%h_xN zZ!K+lnVLYljlG~v)jL6(CRo~p62{RctJM*4GOG#I0Jq|q$OS4itH;RGNj7%auq9k0 zpC*v?1m6HiNWxq#l544mu&L6OM#zXWZ{0i-x7@9`t?eSreV~rE(JR11N|^kO$ggX+ z{|mOXHgPRq>SK;#1jj{=vlK1DMKU4FMoNum*~r*|`MqZ(fq0UnVb&3Y`Q*SBeixeC z8*06MZ65La$;snZBQDurP2x<})2iv|50Zq`CT4{H@Mk_4ih6p?`P|=wBO*M^?fkU3 z=(=)Lo<3vqVL;*|o<t7-n}w-zFS#1v{VxY}kp_?324)7^yc*xUtBZnkr;%2;1$+4f zsu-c8$eU-oee*nTQYi@bQcw)%yh*7?P_Hg7Q5{;F=!8vrnS&PDyAOq>hi-g5^2iW) zpx3b)fYN^lV+u;&g1uXPufj66y}tB1ZxRmD>eULhrZ57Jmf|86E9)}-HiWZpr7Ezx z)v>b|L004rsm_IsZnt&`Bl#*aW2MTE`2JBx9OU&sYU+p)Ug-!+HPFZ&gyL0(zl-1# zsJMX{u+BpvSyBhD<}J%H7$M;0m{|&b;9x=!z~XuV)BauXTRJ%5c>giSH^kyqq_9Q0 zQo&`=N*j|^0`2jR@RI)yG|iXZ{7Lv0{I>B;$;Zci7jxM>l6*NlziW60$o%D{PIq65 zy!dwL#crV<1D)J?PC0w}my<d%$Uw!Z;hkWUv|_v4&T&7~%M6v&w~RAs6tY9=0eXb& zww9+E@of}@a)OYRR<EOkL%F%V5(dT>jcWL#1&K&Lcta%-@wtph)EE_s+|RBe(RQBu zB9Y@b2n&daL~XuER56vAJ&;c$^E|buvZW!f<S0Cz`rrg61SMI41wYsAf_0hJ!AWKo z+s-1pEVePUR^sl%;-CB3b*<ZZ-s4)Gv`Gq8eC~R&R$Xi-)Eu1SfBF3Bx%^^>5$kX? z7(xn)<WaV<9(Mg(lp=U8>R#6r+lLDuhN@Ss#AEuwy2s%r3bCo{BmV!w-gtcsZs0WH zMwQ@&&hPMluR8(G{yb6|z+!z2v#i-yCdPT+ogoM}mz2RlIRM8U4gmKOxD^sBMrtL> z@KN8lJT{_Y;|Q-(8BS|aN65DWR*e*LWE?Gz9n;NAnJ~&@M`zw94mFc`XhEiLY@+q! zX6XkfS8Wug`*2>XxZ`F7d#!O-_9Tg-1(tR?)CT!2&wLVXGK9T`EF~B~uxIWh$*M~C z9Gozp%F|s&vfKI1;EIK_Qq2}CTv??=T#2iwdu>^G7|IU)%|Lnl-N;KUY=FMKf>n^& zz0JGxnihE#ROK=kv;MuQt6i7*O@~5rB7FFf>Y}8O>QHwJtrya|!u(m9IO-0e3m6GE zT5=RK{(ztc&GJqXEQe>g!Ob!b0Zf>qEN5>n#b_`2y<GC#m$Q{sy2>n|BM)nMnrGIG zmMlz6#Mjj3r~*F9>&$7>>-ovzNi9lQ@<RHwPpG$mvS<c?VKb{Jzm|m2Qu9EC)!As* zGib`{Yg#}`8(5lEevseZOm$q`*77DWqozg=t5nHS;W*t)T7^Th+`qaCCx<GC)#Oy+ z1UsKK`>yL1UP`aGW;^R`w>V3lV}UM;DLIvuTQ5>mT4m)lTW(vrecq$W%B`0@&wQ@i z^%8R_NbA*lMRa_KzkaOKiz#VpuqLQbcujSoHAUvq-SZyT<Y-Q0ob9dYQS^Q_+;2E? zArnL8ASn@tm}_GoN-%+Yyk#yyBlh`XRJiHKucRMe%Hw^ld6?VQ%~h1!yt|IqqOQ@^ zyEHEP%&lEB+N#CRL>oSYBr#3f9V_cv+Z!BQYgGc=?zL|0daZ|<wI{2@RjtEn%itbS zOxP6gMWnSyCk_f522R+Uau@Sze7v=iYcIU@f8gzpR0ns#AIz)4WN?98ogpj_;WE81 zuRv7YZck53a_DOTPUAgbs$fZI1OrT^B{i_5x^9=$u|q2Y8pzIo@F@^^H-^{w&a6sR zf^|@T+g07-=*>!)s&3B7uIhDvRc|WXyoXgu{Z-eSv+9wmWSx~r*k2v|?6TgbHsqE( zc+-a=&iA5(D`Ih&TTtBgL^VlK6~3<Sq_W6o+jftSEy!AE63%DMXrUO0;9BKr*e;*p zK=-K=(VN@bC>}$MvUm)fD;<;JTRy6&Y9}7UKl6*xs`ZY?5a$}@F<`PCk74)eMk(t; zJWy`#!dY;9?gFpw9C%1dhFt7L=+Xx4Mbf<DST6H*xnggv2_l=Nup5EUQ=N;efGHVg znK)?k*Te~lpg&(Cl05YP(;P-qAm+9B%kOZj&*Cx4WpQiIvD#jm#C%g$h!#6jSzzMo z$t2d~%YP#MLHq9bsb26G<mZF2&~lwL+YyrR{;yh%lAeo0{v55n1l#ukVg0@kwZE+3 z@6TvQK*8cS0Bf?PBU0qH_Jnb*t7jI*6|<b?<Hbeyn&8(!__6+AiXS8t7+~ER^A(BI z^A$z(p;e+|pH7TG>YLY09h&;YNE=Lc4z_NT8Dz;9HaOh{>4R2dr`Vi+56?sQNvsoA zj##q6{Fq-7CztryS13^<9;-92o#-_B|JwcjP`{IlSOlTj6$E`Vg1Hub3Hm##Q#Zsa zvP9XhP_GrHF#99q5lv;q($iuROB>DC*wc|xo7_())}A}a&12hW#n%lnOa0%QM%Q}7 z$5|2f+)^vTf+KcAJ(EL*Wy52?sz{avLaZcFP>YWEg8bNtRuVNIlA9a`=Ry*sR{e)o z_`zJe;)Stx<WfXpIWoRWj5SMyD_V=%Ce3`NXgw#{$s%N%<9x2Ilu0CQ`@U-s+=dR_ z8rEOMwxjFx+ksAAT00h{EwN=!5J0luG;Zt)7}EXBANW~rZi}_?YMpzfpAbLY-OF)Q zaD!Nm-K-tk>JL#d&34<s`tW9@W9mpdu_D38gE3*!QuA_|72AYkVeth}0FXJ4;`B1@ zu8M8&296Ckltj4Ew;*@7h=bfB8ng(_)TZUnOk4>u!t>Tf4(&ScCaB(n^AJt%p{U!z z<`HXq<6v&jqGCHJ$?Lj;etfxn!_=rC-<bJr8Lbo1;6wy@8f1tpQUrp$C9)$WUhRt@ z?|gE5Aw9?jD(NAD1p*#<NBAyD^8p5^)nQYTf#|}D2>>8G53!BpQjbzzwFy*k+!;u3 zpn}_AK|uTsfBC9MX&#Z=5!b^a>;Em1{8p!atT00xwP1+o$yUccn44GU6`_-sHtuXd zzm}UN)MjsOAQ-X}@63ZT>AATiADx$z40-<Nd4a%qG16T6@q6jV&l44@OZ0GsES7Z{ zW^;X!6slFGsXzybYef+_!mJ}3Ksoxd-}jT#%f99v@?7-9zecq_79{9zwLU#l3o%*T z<}9`~3MW?Sl}kKC>z@`6{o9Zh4>4rt5D)(<(xI|LcP~fvyrQ0^L)gm9iWX!EQe9UB z`uij48w3s?<~8gnO^=+?-)T+TKPA?*#b48VJGrJn-<Vt8{rjF%2c;hhf1*hB7P5}` zn%y(YG15lSUBGFJsL9t1A0WAIIrpEp$ha*6`g&TXa4M*rxNbWRX3(*m4rx7VyeQX{ z?Z9Ryl*{o<xK2JxOd1Y!db7Y(#TSHbWLye}xmIdl*i8vu<WT3z9%;^k!$B?ueX0(N z91?u3Zv&g9;1ZDGmB_0o^34q@lzN}?>p)q2H6aAT@$xyfgw6uhdo7{gzQ;YImOXoh zFPVx(1(qo>5)nT=YQI^fC(1Y<(e_3Fb_6+J8*|H8DTf-o@78(Wsxw#5Z8ja`q1jie z6CmiRGDP>Dxc02u;Pd)-^h1-eZk&|wFk){oV6hxY6F>2a;nf#9=h{EV>hOp?h84kX z%!AhxWBoz}q{K4m_ya=F%&D>15%%|~^DK{gTFmFlzj8e50{vzT!fW#2$!*gGO3B2q zmcQ3C+^+KEHDt~zN8Hy3-#*d#-z}_2HY~GGu05$0a}bTcl`t>U+6DVWvSBLob#ZD> z9I`OXC1QJ!o(_t8I?jK6m4(AAMEsZ8>R2xyW5@x{HX9kC36Y>r$`GI@!%u-V{K#6W z!namr>Bmzu17!)X-D73tdjqxvd1eueSh1O^lBat5PUdN;nN>~u20M`6y_R`btfWeM z){%bZjKh(cUFU=qQr{!2Jnw{+8<DUOR_Jbxa862j1*s&4w6w^VQoizkFBsi`Nz`?` z1;I<kx1i%Lx?W%Lu7I6`3lDrnzM&<Z@0TE+;T5=xxpID|-K;V$Hg<FP)x<@-C*J_x zeY<d3uCfhUi3t|tgnM2+uaAK6fk@2C`Esv|o@TRun#CB|)uUy8^VH$r_xc~bYHHM% zpaj>g(i51<jM`OR|3ju`Uf1}p2K1g$JJsv|qb~21j`BNR=^Gw~=iOoHhN(o{KY68> zxCd?CFqM}{UhkFuL{Cb%KJr)Sh{uo?^0AT^p6QkSgExe{XH3$xVJ;j-gmp|&`j4T> z=z~{iGiM-24rg6-(A3QDWEDHrX5K`)$IyQTXGK{$fzLemhagK8t8fNv=II6tRJOtC zL4yt&6v@$?i>B}Yo+OPi9Bl5-?=)mItGI_}MRZBN;0;&^vX$ZYyI$2euizs7k`u+@ z_WwNdI)X63aSb@4#EcW6=!@?rxS-fPL1l?jps2W3j@68RB(9n<qPlRWCGpn?4wr2! zy_xD;WNuLArbVP!DNn?HpHCTP*#(DrrKfl$CwXO8dZnXnGh8^37Laq1dRK!cbijAU zWWY`SaH>~u6tBe|e~XVCpgjM>`M`y0{3>a=O3iOkg_b4m@v34!;POx5@8C181*2VS z2#fq@uXKv*1*HbdwlcAj$8|&LGR!OZE?0#jn60!eVYujX_~@0Y=i5G~fj^XhhU_J) z`Mw>f!4x)ODnR>P-3sGRE9I0icN?Uc)k-_4Bs$y)d<B!$=0KGXSv^;&d7x{tYq{kt z=6Q!pZ=}RBzc#vGH@ROM+^?JSt+qq&pLI``x%ba-)b>8F%WLOMcz-+k5peAn{1yt| zijTANzKkH4he%GEN+r3aTM5mOu(8U^f6YY`L>fLpL)0dRGUW!U6I(sWbL=~qi19hT zGZ1lvfxdvf!Dq{Cq>c62+ByFm#{8c7jUn-0F%F>eKduJLCqM9!d{?y4Fm-sgkCD6h zDlCqNJfN#PoAxo{19*TNB-Jsbx){kFU4hCV7a=I15^|UV6elKe#+}@TnSvF2Av^hN zntkdpJJ<08cB%gpOuUW)>;hv_KO*fFu-ilMa1KO8o|iYp_AC3bm*hfz%$HD;nO7;q z3V{6%X`Qh0#00M6iFh5oH9NL<z6V2eTD-+Ogpp|TWgZ?)98S~h4*k5|YotM|$6YzP zLH`!e9RK-U!D|JY1{d%Mppqm=fXTxiWqHgdf<meYHTVIfrNC^)&pMgllFU{y4~^Ks zh@IVxXdao>AlC0*Mk)i5Jv>X$WFFMdsW_;84l@DrloIRV*~vEfOy7qOQ=I7lJw-O> z?d`KIHCPi*wz3Picm?>cK+A7MtHAfaifcZ#nFZFn1vYp`ql#mSS|B&{ky-U<qVD0t z1r7XAaYS>2*UAN()xousM0|JlT)}g}T(u{yy0A}rXw;Hst#0h0V2n6Lx{}q>Ho~f0 z51PusN<2e$6YkULUJ^rpKk$&fP|4k$SNYJePtC=+1j0P0kmALO)!M{paKLF@U6mYQ z{zB-(P?8BwkYaBab3Sn^JU3^KQF5t5gZH1<@)!ER5z22=;XC+tn1521LHs)gDQD54 zrsHJiBib<o7O<5#gP~gBP5Era2KW!w{#&@1Lej&~_~||!{#fb8G`NNoa2oRME<@^z z`Q|^|SPaVTN|=e3<9&Uec7VRELP?wF$+`?$l)L><^T3HVmi<lI@N7|jtMfCAY|={0 z0F@)57j5voqxgSPHBQo8-%4`|)MW(2H(;K#Nv-aKGa_aL5FhSU-KH<L0nlE;tj+g* zvm;~6Ig`Z9C!ufE=mn;)E}1fh$d4v_X!*>!p&9o9RD(d|Gx!Rr2d74~L4hH4r2ur9 zo6ch>Z|ofGeGJ-`FuB3T7G*Crr@5nN1Id&5H6HxC17(X-?7Ph>4UaE)(5FMH+o6!b z9||1G%}WHB59Q)68Pkybz7<^VCt|~?WgB?2r}^C&Aa}qK$%9BJ*x(HSOsrI;X6pEm z_3p2d&%gbMoycziE{S#L`+&I^r#U9FaiE(B{g^DC{hsL$!DETPnb+oMOJsjPW`8Sj z)GQytXjSGVCH7<;L%{$@cRF(l-Y_uqp1*%6X}HS#sY<a*jkMxf2Or^VNEK=h&VJ1) zZ5_ks%g})427$qxS5;yb!x2aaC@29Ek#<^J_&dPI(y=v;`Hsy0G<;mEQeYv*N!FS# zE%iZsZ?~uPDUlmPIf8SiIaBVFRnCCvmM0}QXzeBZs9^2d=^qCR-9uW|QtyZ64q{}6 z0>P_JY9KnJ&@{(%8s9SSL3!BDkNFZ)JrBQVO?92!k~%g`_m=5iK=MM-^rw-Va_svR zIJ)!o6i`}Chd8V!%%p?`@s#?%j=bFf14R~5^!NFmeS<}q&jQr<#e|X7bnFQ0V!U}C z(w__M(UM6NbrRB1QqoZ^?i@<kqY|!WLK_KxlT#OY1-#oEZ8-|i-9;5mdHo2lc#&;i z!UL9gn^O6Lf;PlJ$v4fd;SWhQ=EpU{uP*8-au{2JMSX(fvlew>ELfDe+?j3O!u^i5 zB~HZ0k#x^cD*PJB#k?#te|1fo8>x+3kd*tdR*CE5r|QSgLo9Vna%0G0u)i)!o%w1` zGo%N5ga~K!)oF8^QM`N&^P6W*<LD@&e!9VCs=M<H#ZMKzWD)K1lU48d_@=a_>fJI} zbWP=^lPwPXdX7k&X)>)_v^!06?a!}cep-jfPFxBnR=~CD3-x|uj+kVmi{FSfeSHoh z2%EZ+Bq5Ln>R@qcVL9w0_M4yWbE?7BE8(Yd0Q?`2vy0?eO-Zc->bw-i@Su8i^!F2l zM@nEk2?wGg4E^LB9(l8VZ@+5t*@RQsd^eHTza|PSnL5jhk4Dv9FXwia{vx&1lsNW2 z0tS<&A5!b4dN~2O%;I|U^xkzRkt?cRT#i|>kGpkC$zUR+QlQO$v0np;%vj|g>McG0 zDz9-EEQxpuG%`aH@YUv2!j%B>GqCE&`*hjfHPEy>N5c@ACkL^IYwCGGI>$muK4%Z+ z$)okUhI~^g&i#o1xJ<l6PZy&Dvmf1}unspj=b*K8vI}O-o|~nQpAs%7a{68YN<n>E z^UnUbo;_MGoB@l51zQ#qVMOdBUb(;MxB4m58x8NTw}d=1u-5d_pqfMY%ITxEoG-M% zJM3~SIuC7K_9$QFH3eHY#%^Jkox5*uIbkjxUDNd|7Kz=#Mgn+G@6$>a#Ci}lxBKFK zlpa25mi{MnNL%^ho@sCS93XNjAR_26?NG)Y0uHAvUOKtGC*Vl0@PqDPLn{nm1IE=I z&|Y}5>{G{^n@4k!zzA$-E*Me!5R@ovoF`lG-?s4UEGbJTcjTO6P8i8G1#Lf5(9j`B zLB6O$D#*Zye=)j&kvftc-b*-TiCIl5whXv9I6i-}EVSK#+l~TC_*2^605YR6gHmy{ zmUL^q#a>VE1K=*_?{5Y}5j3N9WY7%S$J<9b%maS02j-3^fFJ;uwOe(xy~iu|QL;p) z=Hr-8$st}qgw49axY3x-R4rTiQ|;uTTHVu>{w^`g$sZ&_e)VL_B3MG6J(xXke={XG zAwCS@1a<ACm<b^)^4^+@r|J{ke$9sl$q%>hLonw$@S(knp!2`gzV6@+-C%cQ>11cO z%0`hs`rfe{3Z2d%P}1^F@ii0Kc-w7-vdyB78L5Qy_Fmdxs}*1<9o5pwj@Qken13(T zNx0jQ4V$MS`f1CA3um`ya5nmw^d-u^j~n~}1w=0mYCh534Cvex>yWFFLOZo1*xIG5 zh+^wne|%Vhrom7Z@N>1hTR1T90D?~bs~0~l_w9l=;l6_Dmh1z5+zu_5I_wV+RCZn~ z?aZK?5J~rMNQ3B-y&*^NM_c%Yh&+p=TU_!4pNEjYNi?tMt4pS_hKC{i?T}{@z<IP@ z0LgSiz#_1SAaI||OAfXu9DEU)b%>gVW^EzaAqfGD&X>tprcV$PnvCXo_TXe=Kus*k zPr?XESQ5=gPU;?j0&c<q5dH%erLzTQttHW43`#<X@370Xn+!h~Lh4a?{3<WK%OkVV zklW-aJO!T<?MQzP&F3BUHu(POeYC3O^;X~c)IL}cZ><L_?I1U>!i!Idz?vXCjmcq> zvN5@Jr&_TOb$b6`c__DRD}?66=l<PpW!MZpw^tD~j%VBP>8t4WE+-z(g}Eetruj}C zlmpTX8gCYlCR&ki9xY(L%j?@=oI3d5TGw`Pqmp}Nv(~+&d0>JNJi|kDNBR7n(o(cj z;$S;daB{ja=_@99K2#795J6(g1lz*O?kFsG*8Ne0sNu$JDAbBVSG`6S%|~}}L@_-P zTU+kzee6WS)YzX$gQJh!urPgm^_xMbc-07WiY-V(rxR!30wM?|BF;qizDEpbsbZQ( zh+sf*GHzQ!jB7So6z3VmbdK+_9D+;cA+p#-sEN!lggrvo&IgPrd9+oFqvTOAVDTF` zDG+ITPaa!B<k5PwiD-oAbvNWuTh;}gxgCq5v$`;OwBn03dSAQ`KASs09lJ=ly}X8j zWGiK6ZqC!+W+A}L{j2wph_07eiyhwe7QRL{&gNUQW#gPUifff-HG|=SujK`ZcBazu z<gFm8S`d}~M~AP!co%wRpY(!nUmT<rbLxTnv$1`Izw92{TSapi-%Fj?<1R+=eUr}K z$M<Q5r2D<JClNway<^*(!uZ~j#tm#)JzHf-WUul4d4$4ysUJ91PDFsdlsDurfD8LM z%!Y@(d|$rv%FnC$qs{-nG59}6|7&f3GZo%VBM9u#W)?HXwUe6pqs{-nG59}6CiLt2 zY7S+wm=r{jOrW=i-|QJSieP<|3d;4_EBt1dbV@}jb1_MP2fzR(W8W!_@1>=^*XS2X zRr~6nxeRh<18yP7)EX4)(m51iGee&h>IlKOd}@Q|VPd*ER;ei}JL=+~`#W^^Qj6Wz zMDnJdjar)o_D-?2Pk4&Y(<eRoeZy~FvXi+OD+l&}q`9~A&<W?iga9%D)^`!X(e@$! zBzo3ZZONT-8sxtuPj~Ax`8G~x+xtmbOgW+)hZScg9B<)I2^t_-dO>nIUENwD^V&vc zqhe(?`Xl+eWc#_gPi<iP0dEX3D{;&2gD?2+POOXX>+NpV%p%1xmAuZJPsJN_1-mEw zq&AUZKeNj%W26!@vH^3&#TbwF#a?jPd_VVXr1_V@EPk8sX0aYOc0UV>pG!-HMadzA zwPIgY*1`kJy8|~QW^pQpt9=rOI$K<1*ae)aUEJk6GAxVxY+eni$~A1R#a+Pp*QSmF z%@$y~lcE+M1dKYk{yB}{<7oNg=Dd{XY@xY{;ugzdB?7R>>@Ev~(f$C-tpVt*rFaDQ zEoC+*@?(S4QLoc^5uXWOpI6{(SM~a-p!eqB_1c`hUkhGuOZmMI3=h7HS!L%vi8Q#+ zHZYUXVkz&*vUJ{)NUJxPv|YkS{rs;S6#fb)!}><(UYdJTs94;+JiIi1kS_EiQ~e9Q z2c6yv7WRPs@@rU_i7I(GKe>TF8n7sv)p*(Ac5b!;6$3EhPXpsON(sZA8ZN26(HsN+ zet4r-^qN@EBk__k-;sk?a)B3L1EbSlnGuQFzY}vIc<zaO48P<oV$@<o3?R87zwh8{ zSa=l|`FmAjst^dgOSvBC+`olUp}IDHpawcGU!FeTs=D|vS)sR~{Bz0p4(2kXu#KAW zGG~^dqBi677e=HKGg^NQMpq<E;F&_-cp3RP38CCUt*1rbT6ec2EjH7le`+J>Wgb3R z7J;8t+{Q%Mf=?&4%HsHn48SdHTOmF?BqFRf{n|BiCf?~LUK5^po%xfqr*6$B+l?*1 z75U<+7|aAbdnHfwN=V*vGHaQp6{K3Z2xo%Ev{lNH{%T$`yS0!fcDw3&vt4iC-%w&M zq>pFbr+*1aCG_`4_V2Uo-=Fe#Iao%|-^$CiZ&&(rEFqZ%Za>R(9_Bd=NWk3+OiIJe z$xIUi7N_EPiMjIZV|#4es*M62#<yRb*N!u0vAG`8Hl>K-!-!L!*P*?A2iq{-ir0|t zQ`N(KK=AjoHoTu=O%ArBw6ghj6sCj2fj(7C(KUZ)JzVWSygU5xVgKR1>4#AKXNbjB z_hrOyx-nVWak#3>bk6)XW2v%>ZO8#Mx4G?M5_8+k9Wg}pb8)0h3dlaky^HRv*$)qA zty~~?ufMt9Is+IwA4`iz#*bX5u#Sd(Q|1QhkS2fV72Sd>@I1LxVV(sd&y>N=2UyaQ z4#QsFJ_SB}#ayLsB|OXua9_^t)UPLFFeSImMZ&ryzf-&4shf6PK8g@*dN`bw=o~JH zg0+skoq^ehXJQ>0P#*sO_}s%Qb|q%<eDo+jG?VF1>b^x5xL(c^NH3q40qHi}@^&X? zXh%T$euZ~XOIbVGPX7{fyZw8e{rgt?_fz~`Ztk~#KN$EiM6TUdH`ilpy<p$XBb4~| z%=$c^+D4jp(mV-^WlK~<-kf25yy%?o?V%(rDAGz2<gUXupoE5x=doI@H90RE`1u$= z_XOFMC{L5Qdwz2ca5~$K_$;84Jc(8}1@u4iUCQ>sgOF7ToADla`MK1%_s?n8`8;f_ zY3yDMm-t1la=#v>m>MO#@vJID<|hpcfcelIkg#nJiI`JOM?Vu)<XfxljLNeX*iY-j zSy#(Di9f+wnWgp3wK8hif$Pk~7L9}%T$KeJ%r2r_$uL}WUZMUFKx|s<ZzlNZqz#Gy zd)HuJW^~v3%J5sJ|2d`h_<p<XdKrcTA78h*`t-xY1c=m8X+|{iVjD+H2CssAcO;Rz z&Sz7fh-py(DBd1F02ReOQ*p4aV4~MiJL&+Kns;XrmZTj$2g;B%+wdM3gdzQ40Dd#2 zln&t8ja0iMG?VEapoW_!J2fW-PqpIP`qtQ?^33{1IhdPI$ZJ!<@h|jhU4isLEaR!* zuB|{Ch^LanY~M3xVj3L8v_4P74$pUPQ)>OA|L||--LCa2+xp8Ha!Xb71%1-Z57FR3 z^YxAu^*p~~i(YOCUTzLv`u1(Td@p$U1uy%N;>-)ZOfz9;1PsoSRA>AUYD4^SD*Sda zQ305n3lmely*I}9Mh@S#k-2@AuQrtwysCxj%C}>xcI~5iI82}h&5s?OZ(4DMIT-k_ zWy=Lf2rQ?|=QhI{9U|y{dTNt1xNE9;Klk@UnH1A<pnc;{l(;|(Bk5{3k(cK<Oc2?d z^a{zLDKtU0GY3SGo_FMUSrW|V9{X}cZ<h1rG@sKul;tcA20-@Q8|bz7i5z|%alB4R zd@NJ3P0p&u?*)y&t7#_x8*uzY8Q9eHta)izP}52E{x+>f&NxJ%KfaE3{Y*9c>)`P) z?PjoNua%RtF@@s?ew$`F9(Hk<%Vi*%q!M0}=2IcX@dM~`YcTR|e%jr({;lx?%xWdw zh2ny*c8~3wAD5x&D`mg-OdH9G)c{>S{-%Z2L2ww3!?FEK%`YS{z_YF-!Al=#!P3bs zUY}#*-(p1@rd!%uhXvFeuBvIk&8dAXVpM+ca{X2YK&gJ33Zy-3qTfFfGl9>LLjPKd z>h-|9LM34`beK&fpFEuB%Zb{BP9~;WS>-neH1l+TdF$WR8W3%x+`W=wJpclii_8GL zWpHFw{<#5(54{8b3n8(@Tt}uj&2o7I1lQn+iTP4Y(;@KLD7A63aSK~mDV2P!hBmF^ z@I2DMc*ejb*%e$`WHs#m3bZT?m|r*6&|yEyuBg>+=5)If{dOyP(5|G+{FXG?yO~l* zw7;AJ^HG_W^E30|Nu0-X3LQFtS()LjI29C_wf!5>8Y6k5jKtxdGLIe@?w#2zZ8(3Z zD)j;8*QeBY2N2Cl2Y4b9Se4RJKSM2Fo(r4QLQ$LpbVI*oeH_i=$_`r9n73y%nFsU8 zp;#UO%`gAc2gkFxo0XL7w3zititq`u-Zs0&;CAO7C07CY>MPg=v>HaXmUNgU{e*p4 z&(<jxI6lVf5QEocAQDdQEp;BkFQ3j_N;T30-~r#6%7IJrN}7dKLp}glcy}rinE&iz z|Jk1*3f`avY$jt9x6;O6NCmFe^x~9uvc|luMu(iqU}Y4;(_qzR3E&t9*F8@?B4%f9 zBVRyV{!rv<D?4I@R|T0TS+aR77CVSb<n3)<qpZB9b0q?^e!tGBXwnh8_@vT`?2S7h z4LBp)g2k<G#DB@wKh-TvU)+1`hOV;vd4<29H>zw^c=N2V^B^>haqef!_{ih=j#9te zSL?Fl+x0$_@5u0*_IZuDVw%?b6R-OFc8S+SmY75{)e&@uqH0Mu7c}UJC4=@LbIs)` zpK5N3P)(XEqR%q}>zry$D=qnj4>}*Q(gKPZFxNDZ=C2xM_Wgt--#J?CdH>)PaQfyi zgKvswuS|Vl$3Dj(P~SL9t7D?)5SPzPw$1TjZAm}D8mbTUYdl|pUm<|`Ld+F*eI`jE zRe|F2>8%+MTSAIfj^Zhz2efmW>}5U3ES;VKu}eW60<pKqmo5-nh-R+`5aV5md4Fc? z5U5E2LF=Kd{s|+pGxaAa8PT6@KGykBYQc;D+u!8RS+Lkrmau?a(FNv9<U<@m7qA}o z`74|@wa+h*(cl1Xzzsa!2YiC#9|Lnm;^u05o46cP9W86Mt2)4}*Q$u9)JkuJE@&0c zPS=cn>UqOreF9WbeVjj)g>aj}-aixz@BPh2F!dSEs6Hp=_AiYb-p5mf1-wN(3fsHb zxEp+)oydXaV@+hx>Acc4{}a`oX>_^Y=n}utyP-39(sO69g3?$zgLPi6GdLo+=1dCt zW|k~+=`*+>`wT8MHKvp^7~!b9&frJC^cVhT7LKM!2jm62lD_Y^;I9aaVo%`)<a6+^ zd4Wr?kM1Xhx)QZceWnqQ2}WFjhB@f8r|a{JbeB(HP_4#IUDDtA%y#*J<#yz?*{^Lw z@D{c{C%;C%=pH&+?8>~x@lxb5Az_hodEIVTp}B7+zIlh~ATFQTDBQjknxg${qIPQ( zhFd_B(fvDZo+=!q_wP~izGYw-{Qpj($xLl^KC_W|w<I!9a~IW9HRCl9T+a+4u+5BS zveW_CJk$DV+}9^FVdg28p0TeNU~qS5TJTwsaNzS91p*JC#=%*$0iOX!S@0nX0>Yx* z_>aln>Cez+rn|xKw!m}UzM|?Rbi*rgcytwrA+rZ%=ILb1QPCY(GdFfXJ~ER}2fobg zfOQ>TiLgqPT8<rf$?kxo2-#<L6bFX**3EfwKmGG+j-HpcF-+EUUTLz%yAs2B4byq) zgn@+KpV#eu1e!xFgk57H%rhP6p)3AbvrG)Po7-s|zBqpl0VuXQ#J9t++SgAf|AB!9 z1!?X%LA+CSp4Xz4vZ?ax$vTf&kf>@(Kk}Y>Iy~X_uf-9&Uvf8F5b{%THuq8|0$t(n zxL~`2eU~Eq7v9Ps$li)yy=}g=St+n{C|K~xIH?c&n%CyWhGS30KY4fGKe>gczfnGJ z>bQa_`Q+9)L<BLXJH6Qc`DDAH2W`$lyHiMQP8&b6agIbFHt`M*pKNorwVp(slhJs6 zinc?n^nk=kGWU1`+6d}OC6dQbLz+dlF|p#rZ)gG=I1X*mW3z}a>WkLMLxW`ApNq=r zPpUHgZGCBv*f?@_pPn%P$&;9NWTV%v5e!j53;`<(yLd)_vG?}ksFFj(%U)i4ThJ)N z-rh<8Wt^RYc`UMPeh3k;02h1qL0gd+JJL!AxY!dB!(^^SBUDTjTHsngz)V2>HYRz? zDvUU51XLbQXL;sv=kl(@+TFD-CUQ@`N)ooVGY<Beu6f);`CDp!-QPN#$4&c5oq>OS zHr&|40bd(jzyvqS_Rk?LCprgjjc0(HL1?n8RAmyl*`};`>3U2ZUcc2AU_O%`&Ig$1 zeSqmiOJ95|b0Jp==OicW+lc<fB-|~`pnljzKJ5{hv4{wmu{yxqFk{(`zYoj+O8@I& zW<S5~!sh=0m?1eG;R(PRx+;rjh(<`m%tHv<T&5poKn79#b+}Y_LB=LWASc1>a6dMi z7E>pD-Par<#PgFV480^q_u4s%PEUc#O{bUK2>jdhJ0!v=Q;8Y{l`zt;$F~wjHz&3i z=?L^SQWxoS;F(51)*NXk1I!2khbD6}Le3m4?1Yf7HZFGLLM#tTBmy@2M#!ag$8gIc z;g*r$mihp<*zlvCaf?Hi59Gyag)Oc2;L=JkrZ8c5I0ksJ1zn!~d(b9i+AhSY3($m# zQvfs>+7vmb9)TuGtp18XV<+>!8fehb>VBonMRAT4Vrnj&-5@w3;u+b;u{d`Bw?JsP zhn9p&3)_{&X%4eE2Ypi(=R(KgEK&BZ2<lNV`inLVgt-ArZ!yf9rB+gokM;IW-opQN z+_P2uPt_9Qhzre>WP9=!vqH%b`=W>trnr-JKzX5KC_=#j9}|LAWd2i*BVAaZ?^C=u zc`Tfd&zC%dFk75x^iwl{vepY1*x-J-mBG23+Fv+JEDL+JWI}5a<J;-8+k}+9jteD% zR(+Ipt6jt&m77eD_fCxWCl31jbXJQ)0o(FeqxdBSM`su&zGc2H+2DU_FI0&WgjHgD z=?u*%j<V1Uh9@aC>tRjIv`*(D5#dR4A3baeDu?*rolEI*?3|9JIDds>7v;$uyJLC( z*B-mvfh?W)njG2x6Ee(7$UM1&g8PlDR{ES5xa<8j9ztj2C)>EXXV14+_XCn86ru)* zQi4Ts_{5iIr`d-N4<sOo#9qY+`|#v=dlffv6}f*`lh?bDE9HwOa@M#xjs%zdm*l^a z`(w6$`7RZL(dB#7rg}kGS#6|$E;T+6!8PaM=JDLU<cD0g#ihy895+o{ZrT6y3_h-Z zXZF80+g+>e7N*SF?f_G|E3?zv&1s3N{~K&~93lPGKnHaL>f8NON8ovcEC|k5+Kwv_ ziaDy4#)U|B5?kzz0e_RMVGpGwSVdNvQnQ>Wy<!+O9z2aEr$Pds5}PO)k=4zhIiK4~ zPdb&7J(&`T)Z!$wnQK@{!wR}*_jxnuQ;CeOc_<4)x@qXo$d_KVy_~98>pNzYueE!S z^$koZsStOAdM;y}@=k4<gEsB7ksCr^srB?`aqwoHeM6y6^Ix^w-6FFW66cC<wn_B0 z+oaqVz27F+tCGaVJGN2u%WT!Dzw)>0DZAJaI9i_~II#O=N=S5O)t%axr-G)Jp^x@b z-<jp?v3j*7c=c=4q(!NJLsDlD1b^&MvzjwQR3Gnu?Ytxg<rIuZ(iAF#OuwhRVMoiH zXfB>_ooZxF^vlvn{-`BQJZeE@y<Y+vBo(PQ%*M&>rhGi7AcDy%C?}EZ|M@_Zx5qL7 ze8bFUMxx9SZW@CUbyO~sEzzu0EIlP_lZITSJvF>L3A0df4PVjMi0nVijA_v%&ABtR zWl}_QaXv~kEcW(2(#;VUyo8y?2fl@LX04@H<z63s^HiilE4-TaZiS{}dXq-@ZPM29 zsPn$p<aTA@OuH-Yi|-_A{4cgpuuOfxyl8qBR!Wn4<z$e_vo2fq!pau+#KW<yS~cr7 zc({8%Gu?(|-iD-DV&n!1*Z0Wume`QsN<1~%Kexp=Jz(X&#H;}e6q`0_L6Y#lN?CaJ z9B22vi5hRt)g2p!GU&#|;XO5x6pQ97yh_xPn5<`~S?TV<zI=2Ml{xrqNrGw{_fAul z9!8+=227Xz%oiszvADU0ohu}bC&?A?hmu^q1uwgP-?y(&==eWv_7PHD(UrJv^j>-) zT2yWpRIn99u`#l;Sjf<d3hCLnM!W{axg8>C$;%|EP^3I9G|$ItO&J&b{%I|^8k^PR zBNzx6z!YyIch^93;T**C-?O6OMF00y=FE*)stZRb3s~WQYd_am<7UFN_a$+WTkI-5 zzl*dT7}?1$iJ%@=+Lf)?C1iHLigR?owS^_-X%u1VX>OgSpck_OKk_bL*q@w2sZQ_P zs08!O>Zvw;!#!Ak<Wqe+rdaFFO!ghSsyEr!YOWGF2KKKt4^O3>PQpBpk}ud*YzH4x zB>w`eNsyvF_#;X7BxRC3)C_2ijC4ky20{pxd5ofc&E0+86(-L4b-p}~&tA-D{jZJS zYiG>&zsA<MtU_+$XW(+MSEAWmKOOaW!aUcv4#2s28U_%)j}xlR^&rG_>Np>8?*MSi zQX9RJ1uO&$aN;P;>GkHZX#g;6&Z@pO&JWEZx}einbSg-Zpo4Szda6p|4zSixHm|@u z#4WYYZBCjqIShV%#*TCIPQ%D87l;kT4Y~>(1yDyXwwHz$GEbdVXCd_x5|HqKr15}i zAK@<?+GopI0zv2*)T&548Vgl#l}qE`$tUMJe7ngDViuEyM1a0oy$vns@0zcsBro6Q zZSLl#k*S*fq&oI{Jh+`6h*r3^p-pa%t8#CRc`r22gjqIM{tRH$cTsQ!Ba<O4vzDL@ za?_RgG{?=)5a`T7sw-?8nMHHK0$Q-AfYhzj2ZRG~%UMjiKZjLXgL4qVEyP0W_WEA8 z*X%TDvM8(0AFhm(z2x8!`K$yugfg7n;gA+kN=_W2TsLVPqNQ5gL11JWcciflF9X~$ z+^qH*;N$Adt5Y?CjW|pr$QsR*W#B3L`$@uf1?K%eaOF66wD8M!?ikA-xPb`3{xnJ6 zCKfq%XbK=l%pU1=eG}Z6dtE5T)9XsNV5Y;(+DUQ*Ww(WV4)O~BQS-9s%_5(+?rwh+ zV|0UiKse_3I!+&L!5)xv3fBb~XG6CrfLnik3e^6>R1h3_jBFYj+=rHup4<l!&G9wd z`F9UUTH2`kXi8~YlSi<r)_wwom|i!{>pPdOgUw4xCbEk#U#BG{&F&a(o9f@0jRS35 zmp%i*Jw=}MV?ZhUs?2)gjCg^$wMae~=Gjvk7a#*wn#I#?+^N}I<*uhye{_s#05F^t z%4XCG@<J(K%wBZmA9hKPhLTK5X~IZF<pAGhs?tlC@vUP>b2ox-H{?o2rc6|Mq+`mF zflB>>&A*IMTynR0s&wTDSUMALq)M2w>oDrG?z>V}Js6O<%_+svUo+JjNVcZP<Ga6Z zdN(wwDRQh4u<(h(?#<ren3h|hPn`5Sd~6Rh9SPQagsspLBUisZAS@Z`Q0KfUgw)gL z{VwNC0?8_SM_&im#LaJJLaT9=g&`tJzeZU`q)DzaFBjP;Z5HiPg+XgRNs%*fPgCCM zRWA@webA^|Z*R5BpkkT8Yffokk~qLsk7Qp9MdiK9<kU=(Fr7CdSCA)etT2Q-8sQ$7 zZCdE&w*y7-_B0Ppf}0+6G&7U)+X8YeLVonepd;<Gs>DzDU*2$ISlB?kR+a2cO%8L& z!=a8i56r3L!(!&AP8BLa6St)j+$cT2Rsrr7)v%Mu)aTG72AHQO)%)4q7EV)o3QbRB zZBO&mBv=VQyBl`TAiLYbX<}Ulm_PS*pt`)6aQii*Wj+T&&Lw=a&@{AYGR=@z3xJQ2 zM>Gw9UG_q~<s$_gT#QeX9NU(~l_I6kT+;_%EF0dW<9=_vPxx;vu;QI{($b5P3I2-* zcu|B$hYk6$qROg_ppu4`wXS>G`!oVdZ};@_!a~7Wc`V)q<E-F~^=S27fg@u+8N6JO z5wFs-c_(;zgsbEn>3KGJqqB!SCRput!OL93-jn0yFN2;B<#;(Mc==e4m!}3V-?K0A z-E6@f!TNWX>gde*{aT!dji!HV(E7q6P2XHascp|JhtIX0Hck@C@yyFauVqB^_kvDK zU8mFiPqfao4sV`$rf=vI>FwL%T0cI=P3VRhe(UCfT&+KIt#9>P-+{A;oyu?fc4nqO ze4-CdXB0=_Ed9}D`@%et7h+4(FK=?aGV*x(&E32ikorGXVFEq~Is8Tr{Q=wTh;Eu4 z6U=V4o5cO|0rY_+TU2`UDsus>zT>I1GLYM|#i~o|=|bLuAE}SmGU*X~)Fh@d%&-a- z;FtmXSY-|Z5eR`~v7M5&B3!D^)@_eV)l|+RZ?R=7<+5NIR=;yM468owzGXXG$6+ik z$}CeWo>d%bdwM8wsM6$LiKa8ckrID5s{_3ZyHD*X;vWjl+PozA@`1UeqxaP33sOQ3 zkUv4<|7Gt@;G-(C{qb~H-%h8q5Xi=E0D(azVMKA1pgf&%FgW8ZZ{{E7Ig6qVxC_mq zLXe>1ZiAqXOAuGksE8|Z!#(1LTM+jpxUaaOsQkX)Q+03O+kHC;LZUN&KX0C-@2y*P z>eM->PMtc7IuMtZ>T-pPi_5I;s3L%ClWKVaJ;`~ZbNw_;rbd9cOt|Y`!ONr`vXd-7 z21b`cwWdpqV?iODj05L)sO&H|*ubQZ3@pNv4{9O#C9()oo3@A|=uGa=A`|LY0Z(I` z_JO`GE!c}zXEnfy;ut8)m5d6zKZqM-gho;M?4mZK+%eQ{wc;3H3G<!TC7%4GPJ=U- zL0I46wDJSsXrlQHS5!gR8?=ov#*ODa9B=5n(hav#_*X3?@3Y~it_hrXj%pzqHh0B_ zLPuy+nuoaG4tUsnG)x3=W@pkn$O&C`o^k>OgyA;bA0}#G6<Jy%uv6lK3lT3YaMP1i zilo}XU)mzMFmAZ_CE<_xNeMH|e)Fd0oXgP<;)h?!LO|vLR@ZMy7wVkJ@zCx|FfQoq zR8vOmEyku_2rXUKaBdK}Ouj?e1pHyIA<*~%a%RgCV!>T2IK~8rVG$%+lhI+=K)D|9 z)9*#w2UOc*BsLU}8k3K_YqWt&B*WOG;vMH~pK+im%Q*31KN~y4rWx#f)P>0F9#w0O zEyrwg)s1lR#{>1G1SRmd98MC)i2drbE;JRx?Hy_F7?cdbvIaKd(shpAI7U@9&2G#U z%u)}`B#mIo>;xq}reG;)6h+?n47Ow1h}U71)@{Y?9pu!I*JxRH`Uu>HLJC~<`$ir* z@~cqnqC&k)oxf71dgrlJW%ATR1;8b8<}b1OPn2WgImcE>Z1@rseOB;GdlP5m{-_aA z71{&MzX-r|!Gro$@S{^;?`z=yNS*ch?6~}1%Hq>^&gO9fg#T<QY;xiHkb;ga(c3q5 zi8L{+tsg~Rp1LYrufuLUo4|Jf9b4yh$D1(iU9qp0PdAH)xDQy9qUsh<RrX0C6U7l$ z)fH+4lQIL>TOGl%D^hK&ieaI+ap3An0xD7?HPk)0Gl2See-<6=b~?<2Y*Y(KH^l1N z6|w<ZdJKpuR<|JPfO}Y7E_LV@bTR~T1BWFYo55bau^GEsRqCD?xHvFMP+3=6qfZCK zmb2|5OiQEdR2(I9)tQK+$%bL&%cD3Oj)+D21hyX1H5}j|hjyjfyy!^omJ#)F39@kl z!WhmKW#Iz^!Ua9_!N5tQy(=>B?t}LT6B)(tBkI?*P27PXR762Mn}vnq#x)x}AH@Mf zLS9&eVi+ch;wxc|xlfUDSqHn&1pWs2gLN7(A_VJ;*ot)~Z!u0GlQ(y0j)f!oV?Yv9 zcwdrC;SHlDZZ5EjxPq4g=*a0?QuDmVPdDJ_4>Jrk-B{v|kvkHBPPj)`o4PS3N+L_x zdX3%sHh1gIN0`=giaf3VaGdG;E@|CQJCm{>XH_2QjjI`w`0GcxVg-rt79@SzHyqp^ zf72lrtJ82O@CN)j@dz;XZ*|Zhb`$k%PZKog0j;i*hQ)qjv3+42jBwLrRS+oEP8Oqf z<r^f0Ib3sWLz}#`3wX&6e@aqBd%~Z5cnPGZq46*iwvuZk$_dA=d6n3Jzy3o7|DZg5 zVnT)1hDW#;Y=LDK?1Hds!A4-gt_w9=1A^Nl&T0(Ti^Vy%{c?@Ka$Ty-auKj&Y#RH_ zqNt4ELi3E{Yt$Ez31=L?fgF5llo#C}odEUb^yBH}4M~-V!X!hUD-1_YK8Zy2J|am5 zBJnk%Dj*8f$$4=Ec6C#m5cvchMK@gw)}w|td>FpNWtMt}rhoZL1c>LWLIw2=9ltuY zUN_;n+S74ZZGe?UL&LK<p;^*SV1|Z&ATWsxz~HEVA}*==i714iX)1v5!H*HV_;^@o zB%*FBfSTGcNmM*tV%cbGtKp%{+1<92++KlvhU3eKy7zBTWp`AASVJHpQQg4Eski}@ za|JGIcxzLSrdX$2X@4o$2LhOW{)+?=cVbnbf<Mdj4$uM$;9X6#b{tn4DAEW!OO#2* zfjpS<!t?Pb445>^-#Zn5sCyvJnUE`G)mC!Vq*t7o(5-5~C;~u>RREza<3|Q=BLIfB z4S?ROuYkj~gB`4ZL9ku4LFXTf17D3WE#qndD(~iauqFWP4OHJ87aShI4q2>D2?zIf zo(;2~HJVmH`10w&U&~_*QNZv;evN=B^YQNX$C8r0Sk3DifoTV}_ZWsn#3V;;5XI+# z$<^}pt=ZZJG!LF(+=~$32}KyrSeVUS)9J{HkJk2R!QKvl|6=#w@c<Lp=7MGeECCy+ z(t)J`Pz2r_Tyr7QNpLha%P)@;+Y{g}g||Mw#9Wq5BHcnVK3Cdsz2}jXn?M^j(K2%+ zMAND|v;9Gdv!au<)rT+E*e|dxTG5Hg7q8hbu=V6dAHir5^^5AzNL3?ty#r!2uB}3> zr<Dh)-XE|4$?#A{{+O^DNzUN4^x?_3JTK#PmRAuP3DUTBisTQ%i4g`5vg>EXqVGTr z#;i^`QnJjxjTpO;{JmQ>qC0nkNtViooXK{^k*s~64d!Rf`YU+7w(qlEs+{65hWo++ zsx+Z^WZgk^!Bu4+%&U7ia-NJ{kJ1JJN1b&zmIG6$A^3jK_fmVA{^Yw0+yCADIMirB z`ly2wP^}W-NPioOMbg`K?eA@v?(COPgU7&80SRCmBmJOE7EA5BZt7ND1jA%|*P?Vc zbqxj>iIdo^hiRMc?1X(V4(=&sUF`4l<JE`p_QB~4pJqXFAQB61;{k+z5MxE+RBnGq znt%wcgVN0pzeo8dN_=QqJAsf;|4K4W#dNDH4-<Ai8EHCt>pU&E!iC|kFOQU@=|7xe zh&_P^pxdY#gJmD7MnYR+SuyM)s5r*UpS&3A+BM@BJwh)7r6DCwIMN$`&?h}Inop<` zqEIz9<B=$|^W{`Yor|h%L`fbZ%(O{hJrdK8w01|<Yn@a04sK7E9YbZ5SuokS5V=Nl z<9iF(*iw%i%VeU{;G`y@O@!UiMz5ix5Mh5Q9|CbC3~E<S1`!TBiMdJuH)>!Z=?x_V zwu@!mVe_z!Y*;B48$p;6SPrt{LELQ_BbzpxLC84eCR??#QEP17$c8IUw2<C27}?V7 zWDo)$B9#e@Z1fv2A8(nFjZySoBb#)UG_ut@Mz%PveX;D1ACE1>SlPskK`R?p2v#;4 z_{GX5cOBF;)PZ#X&ueDWhBvpFO>@3&W}~3mMV&bfNl(Pi)>I3Pv%9)IU~DvxW??ix z8x2-d+u0Za4vj7)g^!P&4I}NSR!nYyE(9xGs-<ltj;pwyg9@is(-lLgcOJ}ruCD|G zOf6I+#x_7^TXNbBOw!m!^Gh5Kea6^EC5a`XX>5zb*wzB{;=r`2D{NFJAEj>}#oEUE zW+W33X>d1`x)cMOz<Vxu16Nvyk;2rX?xgWLZjpG2CA$yKgoW2(h6QSK4zP_qGZGvH zPUk6o&a?!skq>9cV<VVFxKeCSn)U7lGeKA*iWNSt7`s9}mj^9CA1^I8BVJ%L;)4ao zxX#xn&NDLRUG3TD+}-eH!hZRk{nA{B@a3iU%V*)?RuWZD=F|an_%?|{4qV4)#>FO3 zV{8IAwF?vCl>RUrn@IWVrcg&$jd|ebTv(DIwy;U=0$hRJ=TAW~6Wmqfk`Zm$t_W5H zX+>iQ?6VM6obc&WXc(nhs&GvlMZBT(&M#ih0yC5<Npw?X4G$~$PxTrnV3s0f5xin7 z)cPq#evH!nfWup6(}zbDBX|xjU;R~Arqt<yDkR&nW@K1RX)(Vba{m-os8K4?7nKun zAAJ}4!RKYzYVil_-Kk>`dbeEv>J^>^V?<qewRksNMLQh?$n&J!rSRiG^eBY$d$~>Y zD8sA*YW*|>VQLerXBipa4s0*|8QWWo?ajpY9A9joIo%)I_rgW93+_GP?f}wc`l15$ zeKy*XOR-K_>h3tw)=(vQjFD=8l@=RO*v+?rzBBc#=X;Xc5h+sFawFHgj~uBMy_v5$ zj#o_)bq~hkrJ&r{S+Ina>Ou_ffl}?=(%d!)^_c6XQ6Mq;M=`-g3CwO5li~bRA1vN1 z28i4h<-7Y)Yu>q~lF#&B_!LZIK3iwfiwb-?4;gpF&8d!j+Ug$ae5c~FandQZ^^Mc{ zg5!v(G=bWQlpW@33K#cki1d@(HR-QpoTWlLLbKwu`!+~`_VzTe3|0r~i1>}jgJ7Y8 z*L}DNWlmYlCIJsD$>Ve%vi|GU_+>YpwZyY*Zy-jU2?<KnWhYSXTI$u1Nv`K<cVEP) zKkpzTlDXI=t|RK@>?W&ca3F0vR$t`Pi~QEwF*3u7>}zcox!j8U2CZ||O@s_!ZBzRk zp?wBv7NS%%|AV2elRIZ)0_8kLpKdm@Z}Dc|Xu0(}Y#jTdlxE!eU%IO3b0k|HW4Ao5 zYaj}PH7*mg)%S3)4`H*fJ6g`Jo4e{0-NKOUtWNHrh?E6@3rsF!*hL$lo&xhXw2sfX zTAv+-RHVZZzD)<fli}Mv*urL>tJWhIA@4U~>q16C@qv5|XL?a9U^cl7%#*7yT)8l# zNoo{Qm!T>4BUESA!^wR#kN?`63Rz9Aoy4sWBY#f=A@<Od5q*{|j7-P7CHZpFSa%ez zSBwVTx=KuLlT1$ugs&KGv%lnA)0An4PgPvp867>={>m#ytk8Z)Wzi4lHjEk%^;B=y zLc!fUlee0H`D$Dy@LufRV_S@3RzYLEz6GUX#@xM)Xp4RJPIw;iz6*}#{X}4%b8PTv zo*F{x(*mY30cO^s&>h7T)&##k!4(BI+y!0XAET~17V)qlOTA#X{RnNbJD=B8pMfqr zHu%4~w^!^I?;X|XBNT2cleA$`^$yG$mil)oa&|tVO%Wb8o8QN@JNpnV$ZzXTMMx5! zLqS~IgZ1Hxb^dcB*KPR>88{BGaUDT&t$Gpglm9R;0&Cz4P~#Zi0UAbq*shVWk|g-* z6QEm;(@BD3t|Y;yS_KQZoMW8i!0WBhVtn3JJsJXQZbGsnA^6*R3a`+e3JAWfCvBSe zAt;jMj!dWq0;1b8hW<ZXr=m7EjC9`~Zw{Tw9*j}pQn(me@XtRT*%hhQpH+%Z!5L!K zc^A4poI1p%KBSJXR(nY|>ZDRxXuA=|cN$?AgR@Bj*&h%p>xP<*a1)5S-LyDdg|h}1 zb{z^$0#B0lx9fa^rbb^h;S43Ylws4lG!0#_?(a)Jg8KZSV&xL#t3!4ipn@?5>ba6S zZI`<{X6AM&&VoGTJeAL+z?T=$8gZ~Wz}sa{sTn<TXkG9ZX<N*#pnXg(sxHOVHSr}j zJ{;tULr^}<bY99QmR$->l{kD0ft-Zxn_oRs>?_S2nPmHV%R1ro(S}mv^7S@fWH{A3 z15jMLe7&p1*V_h>G(?#u_5#P(yIOp`Q`?AVO{%Z=0QE<lkJ`-&sJ5;1WPfIb^x6tV zvf^QK)tU;bBv1B<;}gj|*&Z47qP<Qpq86pSPHv8A0d)wOXpTY9*S6%C8nu@=fP-W7 z)?wJn!!g(v!7-Y%<`~XO;T63`NnUBTx{hmwSHkKKj84L3zs)KRIw4s+titGlDum-e zYE&Z`gru>3r4I#jp=vpS$hOqQ;3B3YfAL_XF}Kr^d(eDRU(q9VJcZ}Ybs68>-p{a5 z{R}XR-ZrQW=wtB*ksxk4yCZjH15A*skXgAaou%oDq;XZO7EXsogEO@H0D2EwGH2#0 z<Z`AAjNr=hJ`~L?QfvPq>VmqfyS{|LjNliZZL02ifPLBq=_EgpPR`LFJphops*L~% zcZ3?G2W0t*)g}fq5u}rI2ofxe_<JKj!U+NKRRYi5e(;=#ERBIQDf1oR0mUF+?mwYT zQApg@U5jUP-l2F-lPYLOwF>7jn4Qo7Qr9nZ1RIWX=phxfQ?5|*^1Gzrkmr_miWtww zIJ%irkBAZ4kUS1~P^PYD5c2Iac}7JRzq$Qs(JxaE9#n4)Qa8dK8dp<A>ScO>@+@*q zUuqmy@ZW)++AG+zxYzbK$o%{tRBO(H-eyHieqB$)r|gDLNW+^lHvAL^XjY+3KY=vD z;^L%7u7alS7?NMbEjfx?L{&p+HA>KTQFA8XhO*M?Lf<jgnZZ22>t2CZW$I+SDnwNR z#00TcbFun*X0^6Wd%Aqf?()jga!;3|GIkk(%?4-13DWC^nH4_0er)%;vNSHe&YJ)d zUV~hIIMUyURM_32z6rP+4Y+4a0D}$V60e4^1(R(+&NYJluI~U};#$5CUKA|#aU;^s z5*ZkS-#eqwl+fxZ5ONz~5HK@&!*`&~7^otuo<rCaYZiS1aCtAZZX(CTXm1=(*{s$g z#)+`p(jB)i1m-aSgJ2g+T^p>Id90fm_d(RDI76fR$7aD$*lPE>hJAYXH=FL)_;!De z?*749@J;e`A4`GWzx#-4M2%>JpGSQ0a{)$R85ShhM_iaX14}#r_ne6KEW<70_TlTW z2&_Io%Idxz*tpDqyJ}{Q4>lI-&YshqQT1v-Q1<{}pSirMQoD<&r6~Drz+34H-V<SC zdsqy=k}7o<g6L?!Iv-n-V`pNPaHt~COHSsBJ~e}enH#cAqO(eCPkbt-_f4u!qYY_X zdHhl<vXMF)X0bhBJ%uw>h4nYnaw8PtDr`Nc>#RvJ#G{xNzc($ukQNwD`hvc_5`7J) z(bNk6P7ZJ%BO!v27+O?l&nge+t^=}qMqw<K_~(m{t0zS7!%WtbvsiQ-AsB)OwA6KD zL36s7)P*lSWcp%2c07&-i;zHZcf=sVA$bt6+ob|V-r=$VmccSy91ae`ZU8a{6zZE9 z&63m@i&;uf2Cy?y78j30*#3+JSpvQts!IJ4S<;Xs3YWd;4{^xZ@P~wgD^6xB5dsDy zwQhX>5hTHW$cJJ8er3i6Jiv9=mH4J`u`JWYq2NAZW~7O6uK?bIB<hj9mTM@U&{#yi z`z7BYEOTjgGi=tssYg2)0kD(Nqk(>qPjx|Lx&(WSf<R52ZHy#?0#<f(0JftTH<15} zMOIs7V_{(r?TH;>4X*e`spYsG<X-cr&H)W1%XLU-6shKB97wpcKHfts@}t<zO}O_j z9E+<U%!5g7-U%y&KLK(aBe3-{Aq2Og-s*ZBU*L(ap2CjU4GT~broAhN$MTBsB<c8; z9-{ie7|(S;YvB2QoD}49WD#P2PeV50g|5^%9GJ;x#vPf_xUHCxK2UVrj9|BI*MyLC zCq_rZhhW6aRWqpY;;t1`_D32uD`6W{e`HX({);EbO4v8jo`JnVvQ#%(#Ie-$h<+Mn zg@M?$uqjK{++~w^s>&1p3p{}TMNM!J6|BA7yYUV#Hw({;i{z?kZ_7e~i?pvEL^qHo zQMEqD<>?07C%m<F8G~WGasgc1)Zn=ngzq1WgPRA~+k;Gb@ra0=Pr)sYftDaWiv-i8 z$vbDm`=>)-dKh6Y5^FWujoP(AgQRC7#zool`fdC5{l2d^VoFr4@`-%UhbQ7LqdV?0 zn6H9D1h>Xa(xA5jRB;+j&EwwbCW%F^8>IJ8RiPw0Ot0t`z40q^r+YI#I-cIn0L;)W zqv{D{+|PxP<L(j&1ci&f^g6K=5u&X(nllj99T*N>H4{Z-evO>I-2Wfz1v!L@rzs^7 z^HuXWsLCJLR;&34tQKL8MA=s4P<E#_&XjsWc#R)upd-{W0j+D2w+Coc1(t(bJArm; z%}QNzfC8ZDMm|UkR_YN1)L00h#f#5pCODfa09&Ku-Z~vvr%<9UI++Akwm$$Hx2)*~ zSlp&-)Yr6*S%)0pdW8zi&|a?`jIA}Tday$ka@vzS_V!VQWmkZA7r(_u|6q;Tv@e87 zy$s3Ab0HJog2Dt+n@^VvfUj?FKhNc2LUx@A8@PT8aw--Bp*&xILfkxWeXb4YMo7QC zbEO}$4t{ReT#ZHCsbtNgwzuYQ+O+F1WhT)E-Z4#1kw*fVB)4-;vQcM1&qQr(@9;A` zHD0ViC@@`$h_sM;YEU(<=br+y;poK28VPtTM$a$DL1lZb)?5~@?IHJ`8iE%f9i-~* zlkn(+qM`YnWxL7mPxKTGF<HnK&ra=y8E{>V1kszlOeeJnt+%sRdd67;^rS<f+^BDR zR)F0eO5sD8f!-!u;6srr<iqMM;6uR-avJ<#%!u)V+=9hv3pH{Bm4X^W@&+|J7^7XN zsdl5L%7q%qGT;?autj}bTP`9>l!Qz~<B_MGiW)h5q@c!2HRk@jUAU=o<Hk)kHf~%J zQN(vUaN|fs*&xYKsbm9BU6fEaOv~nO*(B6S)0l8uDia!$F<@~q-3E%8_EDC@bOYg= zKA2vw*GfVAQ+s*oOSVDXWt*%A34IrWq6*c+P==FS$hsLQ$Z$xi@YS}8(^Pr7)HZX^ zgc&2yXf^=G*4wh)*cmg?YBQQsz{Oos+gHwcmIW=aU1$tIQjjmiVCl0eb^6xm(tvkW zv@fLY!Bx~-{GpQK3wJt@g}9c+jGSWc?sbU(?gwkc<}O;5t5kUU%CJnjEn#2ji6Svv zniw8EdMG!OZ+k|Xs7a|O4@B;&w{Uq^1_Na^{-Qil7lj(MV^e`!$3&RhplHbi3;*j{ zsWnZ{`(Gh(XSB?!#L2REwY3jye>^l+!k+Kb_+BWiy`!a`*5S&LR>?5`_Nzs~9YpNh zfRMZ)h_`IQadw<lGE|#tJfO52Q~|Qxpe9>yA*isbhsU-CD&{e+4Xh&eqr%z;xMhAq z9DGf>1<$;bSWUJLj~Z%~?CIa$gVk!mDnZSFRn{LajP7OS2S*n9Ea@B^EVql^V3h`| zim}hrMn7TxSgZ86`~lNVJ~D<B-xBP>bB_mVR($OPb16Nt@5gxpW*EA0hYDz~I2SdA z^2g#`9^O@GD~adp^YL}}=<ls=`=dFM=|Osf=(?F2!=9!~WFUo-SFWL8Xa_HEp02M_ z>T(Uc7FZBMk4?}Km^bCaF^xfE1>Ci-U^UH`kgF7b5HJ{30GXWUJi}eBhdW%t810$y zO!T@*OHx90X#Nz=^nVZ<+=Oa=$W?|6%cZCSavq-3db6$vFL$cZ1}2@aaBYn^9<{Ut zfe%Py&QA-~^I27_FE(C`Y1iXHuO`^RAYg#H@C?{w0P9`Is|cm#Ac0t|gyVa7gSOjw zV7>=14~mXPl{scv17dE*LW1dZ{1Q5N4gQ#1pi5y~GARuu1_SB-TGVnNqyXyon%X#C zM)121zu^E<)`V+~4{Ph@QhF4lIA09EKd7xnGR$%MH`?c^!*Hw{!!J}B??FDSt(lLv z=c089N>|bKa}mg)c-(rF`LXi%B=S|FB#tkN)%%BS2$rSM*3+0zVRYf1@K=#YFJ_X4 zHa@{B9AlLoq0L~V)JiLVFAO`q!iPTBqmTZeu%R|i&i2QN#>W~&4d70U=??+dFkIR* zxoxGGG2uvEF<+zLc3k&z%D;xg_ZWVF#-N6Kvns~gGyAYuFK^=TCLbC1l~C6J-~eIe zu!5RJ(PwT>iIzI`nD7x6@MXzo$jg8p*x?b{)Plb%@JGEK_!LxO5{wqBC(Af)KXvuQ z7T5uqU#S>5Pni^P6>!*_j=1(u8cA7Di_I`*+t0-&_+l30Hi~&~Nl+R%8eF3Sji#Rx z2nw|d2<oPuFC$`#)U^|N`AKtQCGveci@#1#RIDyL+;8zuhpDA|bRT>eNB&l9e<&0L z6F&pi*8$;nE%X9wrybETOw~KVP$~iK@caeK=>|G0({s43;qMkkxHrh!a;FT!pOahd zr#+w*u;Z2^^mndy7<MtRTQmxQRD+5p;u3=CkzSdF?H=Oba=henp$y=4R^R=}ZtGw* zMQ`wf!cAZj&Jj$N)f<VOM$}ll@`EXC{QRt#-8klIT&y4q@%lOByai?5APdX~PtKxN z2iO@Hir?#Xk+20pKQg-sI4ot^NCJ;lL!2RoD<Cd6p%jUW`tUFdVu68-iquq$I2fyx zsY9h1yxfrV4pho1e}y|bOc{$0nFT_u(Ijy7L?&k^G2#3OVyYLK!?vqwPXA;jSDWS_ z8l7etpBtJZ6zMeAAj82uZ82WjG)HOcrnw30Wo<t|@gWxtP__vg#B0ytLN>uE{ICYn z3Cg~JJfK7NZj?`(4kf=8BMu%nyCj?kd%!(e9^Dax*-t;h9~`IYP~wG+g9il!f@Owm znH&s*tHBiK961%UhWGLD&85O*zWffeHBaot>I{eF8SB&`EbotgEn%Q2wu9vjw0UY# zlIsC|o_eJi$Rwit#lRYnaNnrvjRWC!!Cw~%#@;Ei^$dP#^o;G)i<D)Q?rH(#1*IkK z@Om@pE~>^u_f{vCp{Pg!Zv9T2q%+^)0T77$ZBjqtow(R*LH*swT75o65;2AkaFImv za;F-p=1qdw3=ZsSjU0u(-$5dnl1uT&`6yb(4S%CVJT#y)ieX$yzY%2MMvJOPF6-W5 z^(OMn^a}Pb!81B1W~mEVgA>!&1B0QLfkVxR3B2g7&YYyN|9L5Y6L?8pP=@JjXgBbr zMH~3R0DhbRU*iirn(7c!0iTiz8SmWS4<PtRZ3);NScyZzru~Xegw6mFfoHgOn}eu6 z<dh>P!}$efCOk#LxoYH$K?SJp;d*q06BImqgEdG6zdrz-7^y}C8}I=A?CT;S5Fp|R zIbdCa6x+RlNNmhm3O{r-jz<ytTK0|s=(7T)31iF?xEWOx$!)J|+L4{sn_!O10Q|ot zfpAz4_$1;<KlSKD7ToHq9!Ez*rh%4LU`hMpVjY*D=BEg$^TmLs^W;I*RBI+O_u$tv zYt%ec^TWS-S#Rs9H|R$v)<~!5Wl!l8HO59mNs@GSd8(xdwan7h($jIx051)s_+fW$ zl{=<&;pYnUy&-gA?O9f!bz#2VPTiERdF}3aEI0xRYw%aaqacaChLeEqP4q(|Cq>QW zXH;_=jhY*4znaTWMa?}*)Z8JsGZr-$tf%!{C{}UotZJD;gim+49n0qVu$A0AsZw7( zTZ8@*2nSwOvzo1L)4=;s2n%VAR&$Ubr;i%IgqKG9y%jgNSWrj%)$!@3u<rgEO^ZVM zD9%HV`VLhI$i#E?LmnUKXvtgv7+|x+A7O8+QFEr(;3o(QUO-)`VpOU}kElV|ZIxCd zuRmVYYD|1sSdFTXgYqCo;#J5AyciLG6>O>YhRzIqT&tUiA{o(waJ1W?GAC6|Xx-GZ z^%wpsXD@XVG;3!6>WxZg`H|Cs@9{01`^WTH$ILzrU@xPzeXBT9kF$f+jP|h1jf!q> z@VB@UmyeD{`_f;S?S=9OjJRwE?pyil`M)rc)nlk9f3q@X8&6j&g+~9>-i4rmMcf`P z03b2Q8#tw%jB8RXiQ3qW5x{M(NVQp!3j8ZD!fPEBJ2~Ntiu_J@_XvplZw-j&7!W`D z!5}_lK%DOj;v)j$Sa2_lKDZx)_q`5q^5FVOwCWvQ2MLE#&*8DwfCV_~&a79>kZpxb z6IB5JVG}TgxW~P_0l&z(wr~c5BIgQfUn>oQCG{Z{6o{jtRXmp;s`s*kJBg13KEw@X z0bEVgc{5;BTZ%eiSfm#*#(+&e=QhXI5Xo$6_?=aHCn%H3bLBXzaI#fgiCnS#$0|Js zFL(!02`{Qzq_716pBdNy!miZGvOE~rh6V_*3WV?$86YHN9pcgs7ctVdGb|6bNKP1$ zT<s&0sk8W49vqRZEe}{_h~%zt>_9HGUO1^EMz$130a_q-?r;kPkGec@(*jXL>qDC5 zA%<O8s$RpW5Q8aBTOq2%3Q^-&B`AAgg@7N1pA~{9V3!qQ0t!w!2hny}A@<i+2y6r| zB3EwVn3SJZ(JnSQcbYW<Q>W&AJ7Oio8i6d2UTeg-EwM)I1##e<gG3G_>6)6GpEW|C zPAIe?I`$G(SzXWr7B-#n+!&Cqo(Nr}w^$iuFI$D(s^3s~0`-}@n>;~w2efJJiRf7u z&DO^r7$7*VdPl+=itTaDY4m$6lD9jLK|)8Qq!}di`Og0&k~BzECk+x!a<X$9B($!w zAylB6QG>NF&ilw&vJ?JWqxG7kZ9<nqaM>m>onqd<NT1JP+tue)PIHT%^Xy6%$7yEU z*)HlF+Xa=hA85OPP(fUn*e;4y4s;XfD6nAoD7v=kf(HZYA8nd05Q~n!+i$y&V;8Ab z^m0-UFh;u>t5s$qRvIjDXcAJUAp_QpPAAzm>>0XVrZFnEVb0LTSC=^hwhPi4tQou< zrhy~fngNeU+RB#U*qo%#EwX0tT-AoWU{*j{C6m(OCnYaj)(nk9hzwCTx4@clhsay6 zEn~Z|`Uv)i6e|YIh8`=1ZN$(=m=nvizlQMpiBR8Yz1R=d3v1*qR=>!0wxy!UKI~I` zg722Vc7fdtInA&fv<*~P{hqT%j>TZ_ptL~Ao%rK?IW<dTYHHrb?Ao+Oi7YDWo?f{L zPzs3^0Z`#A?zSRCZea5Zaf<Gx-hxFDWn9SR7tRtA^fQNmCbd08%m1W31g21YYa2vJ zU66dKnBc4!hf(spcU}@*>_!3`B625n{{HRiF>^8G5TACFR%Z^^Wh6-uLlDgub;QqG zSaUBjq<#m^ZH~=H$6=j_vMTMjt56{3$52lqe}CWyiByVU=a#iT0`>bMFLF#;Q$~i> zD>SF{4)!lI&ssIARBeq>1uDZMhc>~wVvc%iCgOU|SV;gSh-^73YHPy_WIF9GxZM03 zq!R5e{g__K^+fwAdrdDi*=(?z4U-SyGPYH=6)_j}ux(m$x#$>F?8`+!zEIVmDA%1^ zW>RU{3jJN1RA6=&{k>lFckYA8yh8n*76)TlDF*{G$1biV+G$xq2;!C*R_w%oCYYB8 zc-mAXpgyBbB?i={+f?F!bQ{}L+}C)HO{FSng`rRdymE)v5e5}lP=;d&F`wWJz4hi3 zbXX}ylD|tNLS`e0L9t^b(Pk@3{d^i)5CAx{g7y-h!*zS@B-;cQSX7wUs6xRo;sc8| zi0~ec=TcwO!nUx6z~10BhUkEiEis1laC_b$X?qUpyg<|*gFq5h*oaLIi2}7hr>A9! z@l0O?H-@CMd=Ir^cJsLX@#*mh2o4S{wQ~N~3PsN2gBo$6e;s8&+5c&{?2V|eU?0tt zW|-~K@I^`4q`nR`!p;*>D{?Au8G$#57;2=UZzHUeJzxN;uQgR`JYXV(ASVjX;{SuQ zMKrA7D9lby%4O2ykUC{Lto1#RDC$dG4p=#V6$qaX;%^K*7h7bm`VN*_)Z?3rD+Sml zz7Nui4smbzcSl^@;l>5sMG?%TE{+o5BK5*l##TjCgWzRH^&G~)@m-!RgI2I3K7VF9 z7B2Eff%{Ti+OYj8xpnxBaTy6EPp-{P@QMEe?KaiRy?6-IMn_R~R<0|*OfR((D?;Cx zP;iG5tMo52$8{aC3ca8lAzix;<?Q2ztO1TV0^0ZPV2?gXHP~e3Xo!$Cb3^;+f=ky< zy66MCxMg;=j;!!Nv;sa2hSDF0=AHwiw9psmi3FzoReHPUkY}b)@5XL#<fU)^8!{jW zx$n@Oe{qR()q5R*;oiXTA{)bf-O%M5=q|~HrJtmI=Twk(Ujc9b{eKU*rl3qmaA=uT z`e!iY`FL;~^10wxi``dE=b!mhIMGhS|87UX-xu(o2l%_td&UDlBHT-(D7yhhI5QWA zT4eMBuk_W_53M__wu2e}AR38b-MKbbPg3}|FR=X;`Iqw$+(SR?EDq+3E}T`NDXgD+ zML_e`z-Wt=6B#Vi`YI<b3nMW11I5i{in)PYhMc>k#irC2n{jbw4g8B0Sp@m=wfAjA z&5`f_jOsJEk=j9B7YI%dXx{U{F%L%ffl(n3b$J9K{gDL!FW8f7;PGI68W)j;sOT$| zYq!xGxEPJg*x?U(`CJi!>}Taq)w`|-&V}X7(WY*MZ!inq7bDiQ&jD869aav!u2fT& zpWm+T&~MgGZw%fvz5S1?H<RRx5R}h1k(BM|jU{7vJ_T&(?K&GaS8q<ByY4LmnjG+? z28}b>wN?(!P?&7BPmEUkIz$1kaD!_6R|PLl&M$|?3zU{yedeJE`6w$V_=_SLpl(YC zxEOJ!HYuKcs6&dr#JCb|3lXB0zu1R-@KOhdU3$1DE&ykp^k5S0WNp0L=?dcxG4b_o zcR4(_6*p1Attd4(fX^O;zdermv_iP!FkBAQVggLMWmn(^@s*w_;Q{FA7Q{FqNb{+| z4M6()wT(VVccFvs*iLMXpu;y5K=%mM6g@(}e_-5}x&OPuWZFVd+kquI&oAHxvANL0 zo1K&ho>zLNM3w}0(KA5&+oC|Z{LMmBn2w$xPSTuU>nPJCVMpruQBa0(Bq1z45N_f) zkOU~T{H@#*E8z;9X$x6mSV^TOPk<7XB$`y(g{%}>3j9GM2vpHN1hvY4t-iFG(;Jx5 zN{pTml=vaZ%+dol>95vG;N~3WIC)@PwYqaqh4~ldA@~>OjAuSkb}pu2=Sik%1x%<F zz<z6Rl9-Zkro?In6oTg+mXq4yPa&7PJP{HmwC~qy5;m_5Wwky5FA29c0UAlRU;-)e zo4yk;5V|J-1|aH1Y^6<Ln7voJR=^<?SHuhqr`s&1v&uiF(+Fxxo;wH0{f<pB%q)r& z(jvW<*GLfOor9|2l(Z4|WRS{_)kpv*p0&O*9Uj1mBxwMLGDG64;C_)3z-iAB^I0<( z$t%<$jRYUd!b#Tz^V0Od`?0&qY3=PpbZEY)thvy17j6#@$oc<7$zFM2rzzRFIL6&G zz$n>Nw^rFC^y**(>Z9XbSp;&`w}YI6<@tZ>fP*C=dS{?HSb9{@58!@>gQY0+caKlg zaq`?pgu9_|_cLujh_r}iuJ!W&aW`wRivm4lnJfT<+^_553?<8TCPJ;8qu(HPN3h8n zp%2&3!#kLC(6-TK3l7(Va1V1eB3dPF!C*H;qYOYF!Z1RBgnkC&hVJazB>mjed55&Y zSgn=zA#Eo&q?g%-iBk=za%|p7?TPRnZ4E+Mv2BmKop39At!<a^0CX!(jiuTG_Xz9~ zrSPvac8SlEb_vfHZ`xCM*w|JC+dJXj=;qnLcB$spe+N2^TX%w>c(vAW>rgkgiws?y zpX(yjp$M}BvubR=3D>`EPN+k%{1?OOAcR`!2IzCdnT4W}lCi?BE27#eC^S&1x}uT= zt!BR{wF>tI73ZLyQK5p%9?d&-sQS@9KxvWy>$S&>SqZZE4uFbC_5eB;WKn1&#nn-l zRI$%ap4K1PByp$P+*XPFpdf3J2$65v2mBU@0|GzY7s&#<<a<)L=HOC~Emu#YBsf{{ zeiN!(S7MExm<E#%EkG;e0gwh$sMG=YCV*%Sd37URIU)tQq||=srw~SvGhhTMLD|UQ z2?3vle#y?1@`RC*!X%Zrh8@c9HII~c8jBDEHHJexE4SH(^V(E6*C33;Y`u~3T)a*& zPh(Mr_#pEld&4;=703^gK&pc}5t{`l_uvEQ4KRJ>fLp96>I*R<3h4sHe)u(NYPqN= zs^(BU<{*M7^1PKZ*(zPY{{qQtW+MBiTCRe}(9d`s98^sY8@)Y5C=k%YZ;{(`ot1N} z{Vi;jH!B!oL+Y#459Z1T`|6g6y%NB#g(G}$Fg3DaZaIa>Q@)R?bE9ta?l84S^SH5N z$HJIM>#m9hhhoBT%E#ZiFzn{2sr)k!GBroV#m0-nHX3U)>8n{Ca1}EQ__`EZo0xb# zlUQa?Voua`KQT<bnnjonA$WaJ;Rk;otl@jSqu^Ts_@YE|S2vQOxY;6hZf>(n8Qa_4 z>SKErcjUM)zV?Q2#ahTt!F!g%zrf1=rB(R9+$~^k2Q9U&d~Ly2u{R{h40GZ2Gkh~~ zg{H2|{V&B|PdEKtXWv78S8EOfJG)<RX9UF=xd<0^4g))*NNzLb1oW8TFG?t<LXqY8 zN$ON<J3^P)8FFB$t;={obX^9zIcR6x29kqve#4teb8-BYmGftT5!ZuKKX02d5n<%@ zU;$;pE^aiwqSbIwIUWO}n@ba0+w!#iAO{{TQMEC<L7KmcvLP&3{S>4um6@CJV)$LA zo<x-WE|dfB!cM3dUbhkEg;Mn=ra+FXTT#UgPC1VSAffw2_8b-J4|%v8;y%ps*m(2Q z)CRQ1J!2ufbc@0YX)3v;^+5yx!=g5e?Q!2K`R>&yi)0t8mr)%RBVGYNWqk2EJV5zL zad_e!aZbJ+RqyBlyfN6KmLdC}Lej_wW;q48%cT)+bn(JnfLs4wIzt!ehU2j5BvS44 z@{sA}GsM8R)eFoJDB}%FE+T+(;2noV1=A835)iM`5bJCwzisf$?QP6$i0Ueldg}7o zb@*a5%AKR;#h#q={MtslPokSorX{rNuK()kJNM-3>3Taip}3=7y()Y4_`rdU7daEH zKF_6Mp9v{1nu={*;}<@3%VyW$Ll1&8RXERxU_{ZIUR(%nvll-E6J0_QG_zM=62oK$ zD0b-}Sx=!E4T;xg2d@w;X0aT^*0qLMn=Pu)(^jxWQ>U}V64dE&SEjG9E7NytgQTUD z5<Ti=^_K*}1Id2ggv<OMIJkf{+U&<~<+hwP_{CPShQ61771fRO3fin;3pU)$L#WZ8 zZ*_nf0Aem_R`;VXn<LNKVwBWnbFcoJ2wyj=)@C<;t7iDE4S^<fb+bs~ZNqc+R+PG8 z>01$PO+SIHXbD`iHLt`WD_;i-5$j(BpeaxurEf;0!9ta~86~@^M>lVpZoqPFcH_5r z?PIx=#Y=8PJ_57VoycZ4d-2lr2p7A-c;R8U&Q~6isMagiCcCw@VhyrlZL*uwjo*s> zNbF_{$g~xMHTHE>{7PprCQ|BbbuYPMb?xIZDwE`~Q~_zTD!XY1k2&4=tyueb%&qZl z^KC6{)l&G(t)w^p=&RNypE>9j!IacS>{Uy&kI$TL{8sH}K5OMz^)sL8b1@3ws?$(S z0>@k&^2TYuz1`f$?HlBZV3eGf?}BgkZZHDAF$MJ}PL+=$;j!22e0-j-cvn^!)nDD} z{^}peuOumn=c~J1U)>;Ibx}962<hMDt3AT|!_r$FUagNbo=+ceeY!OBr=R=4`d>Li z<zB;H%*hzg`Hej<dIzk^sPVk?yyz3K%5l{>H0<{h4#EBLau|w}N?u^km)o`W5<Z~% zOXC3P`LbWY+8*5w4>$O9+u9WPRb|+(%b%xVBiwHtoz?JLM`tzae@d&-A=412Y7Z%b zFKnVxG(dV@ZUdtF;nRrwtj0Fr$5ttz%13gvkIlEZTZbh5FyxSAg%3c^OFw8gz?q;w z3K7MS1&1kchFHaaMXDQfvv*&B)p-=01MjZIUpi#fv*hOcT>E>)l3G8chdg-n&Or`l zczm6RT&ysCo`_#CuWm#sJ?T+2U8FZ_FH8mKaWgDD=&?@s_&t7YNsq@YFb?wP+V^M6 z^XlbT0XsQCr1z{`fi~sy6eafZA6x&1v)t7%k<;+dwaVD?Z0#A*zO+yLI9fPSe{n!; z<t?>!No%xJNC>NROL>ZI!fnjeeM!6w`qEmDhc4#@xU)~yXsECa+A(8_u2A<OfQ?3) zuaMcr-$vuuv-J@InY+U3*;3XZ0tp}u2J+bEt6@mqz_{;6OMVCt_nQlcFFOE;#6m;6 ztz%-#O#54mit<J6gksCD2DW-ZZ03Ofj%~cFz`ed^j<)Fn_G4ZFZF?~4tO}Hq(qObr z865~lyF`V}CLIdLmK(CSdRes0NS=n9u_|p7M~Z!Kn?upkF539vP%LkSUz50KY2PmL z!@(GRUS_f31*095@x#GzLfSks)Rr6errJKrNU=z5HD#ni(LT!f;ZUscU6OPt+9fo8 zI2ivr-;Xl<z-R|${BSVRD1*syu1CR2TuKWtVRaHx%j<omAw_i1F8!p=V6N6>J3w$N zQ3(XwM8fe9!pI&&`GRiNZt9v6US~&C;xLB3wNK+{4V=al8Peh4EXFhhJIvmbhMh*Q zFwy(Tld~k3TgRZMZFpR?)1mNu0WEb%bgtDKbwJdgSdrdsu8*gf>v{ALpBiML*<zm> zaYRb<sTno}HCb^ga$G}fWxU$)sGv*E+fx&Mml&dvcU6VRwGp<B0iW0m%DLfWc`e*{ z3Xwn&@wkW`PIdUfnJ+Gm23zjd!EsHkM~~+JABs~hu5*2!f>TG@I5<V>A+;>9A)NGC zU><}Hzmsb>xzzie-BMQU#0!ilcUEka&s`(RPIUaV=CqRwTA7x^0L%aFnwBttUaS`P zVj;sz$Iq(0yxq#I(hY###Yz=fsg5)M5hClg3)5Gu6zoN>AeTJ;&*LyhZk&vmJya>l zf$RK0WG+Lp>n!ytvH%sTbKvJCe_~@v;O|FRl4KzA6sNSo#<MFT-I2<!FH#By<H&V} zdT8jPH!G!7FSh!Q!J{}IA($B2%Sp&lE45^h9sB6GlgE;~$&*>ZodfdZ#@S8W)9?g7 zE=+Z)9~7yl;Sz}~RO$s}rbBG}%3z~pv&d2p;{o=HtB}r5r?wsz8Ecj85AYJG<Py`3 zW6~HU%=2_gjiF(c!@sK3idl%w0d$Dti^~qT3Mo<nLY``zhIIEZf#$_gghhYI47S6q z;>aFW;fV*(+;<BGM_*51aGecfl2v#JD)!Do#=YlJcB1EMtMJz%`EIY>fL;q#6ZXA6 z^O1y!4y={pt#~J1(M?vnyY^5YPiwKtg2T(?9&u9+jS)p^-ZYe$JcGajzu$27!Tv>7 z&RiX#;MwoyAYNoh6s0mAv5K$IIj_>*LkulO8pvYxZm>!RYNa*VCS4R+y+>KaPiWud zv>{wjRI~=g9Y1&?2@ftLTEYVb-vf$-;9?_iApsw0O_I3SiY^Q;Bz`Y#1Q!q$tpOpZ z_(4EuIlb2Ey_lOS!h8zDO)hQWm)w9(!iKxa>T{#e<MOD-Yr9Y#ALou$p>;#b!fF%= z1NXtfS;T|w#2p!$>PJkLrWbe70sIP-KWvILxf=y0lB7?y(&G(n`^MO6Ws47HIIZoY z$iCc+X)OhJd8dVnO?@H@TAvm;%b6A(i92Finbn_kinE0?_m_bz(HE(JL}tcWO5}#f zTrHB}abIUYKQD+pe(#};2xC<12yaLV<Hks(md249JT&qXj(y0E^DrbNq}zi*{;XDa z%wnX!2<!TAi%wnXBdigwu4Quss6)*rUUdMt%Y%;4MlBg8#74<^5no}*Z@T;=Gl)p= zA}y~e&gr$SmImvB!-}l31^7X+P00%x&y+wKMlGSsZ3#`ER!V3D#fgY+#zZRgMEH&5 zrKX@h(JDOq0Bh*)@Qg0*(;>GV>0D>^d_F0i<;-Ek^Wse6nTHb&joLOJA)#Jbu&P}` zdR(xZeHd~!U`I&Lw}zZ!^&V#p*-u2}A2JARkoct{q}~a}eYn7pb7|fA%L;TiU%LAW z-3fFdw--dQME_&^J<k(D=4taXE(#IL_c**IBng-2<;6(BxG#JSMxm1BXnhv+dEXey zwzgLb;gKCeeVNr()mRLfU!^XdRiR!6g7Yd-bhW#>^H?TK%To^(K<HFjktLxbH6O(# z8I+JT{+X*R$GtsM#D-&D@tEuDUDr6Fkh-Z$q-m7(XLXJwzRy#)XPe4EKC_TnW}IW| zZySjraI1PH>px`jg%=y$*tNtux78M-1|G%xK<~NY*s5{k7Bl5%M7@RVc}~37K586d zD*wuae+c$sDB?m%#2Fk^hJY$O9?%^gR>vdcGV(J1U?#xG1^8oz4!m615xM_DAc`yV zO<<_cjH|Gqah=uD=WPR~cr|KPQ4@S>iriNE+!#a0%iw1l=@f^}&bu(ye(|k1w5KpD zu#fcFUF6F6&11HWv#sfqmjck}(W|~Z_F28wSs4;Uojuc)wz32d7Fo>lnyWUQ5X1=| z{htPfi3ww?GA4{=4`|q)ObePAt8~n`55V;hpOxy{V|BXN1@P(kv)X__Zh^E;7)>$= z^n_9QQzkX3v~y3kFsvI;bV7JOCvicZ34HgPL@HkQ#)Ew{S|1N|3R=rkWFB;+9JQvq zMypSHoc7G3r+P34s+~?4^7!-)NEo82!{o9^0|{IAqk$@)y<f}qDr`%m;_cnlR;3`Q zRUudf$Jj!(aI!{UtB$g1Q12Tho3%rPx}0u!Qi-`vI!MXb;ik5UbNqy8BV<gudUK`@ zSkM>xtpo)*H|cVCNV>jL1+}|zT})&O3Ua#93XhR@Muu*^>$~aCk)Ouz#b@bSm!GY_ z-STDU0oP@$>kPB8|Ek;9!au676|^h&*4dfM?%o(>yRne<;mjObAaur>dzoAOr?J_z zuAuS$mM(pg;F7VTu*Ge}R-PUZg)&Q>EMrpLQ);}osF{R=;|q}@V{D?;VQg*cX-+qO zGNyfcT8f3l6L^>^V>0V#|BYvg6v?>8yV*KQ9+bEo9dvn`NdfkgQSP+D8SF<hNT!XU zs=dmFV?)uJO6xm=!?G@gfIEXrAwWuw|0Z75YDFt&s#bZmQ#XeHhU3WwvEU#>*4Z<4 zX8eZZkSUA)Ehm;V!{*52915@9eK@Y#BI=(tuw7j>ljW<*6sjqr0dsia^Op`s?%&6c zuU0o%Qk)~Kwr6pU!RkO=SYxAAqfc*jIxZ`fjY5NHjeG0Z%qo2V>FEm9+vYUrn}090 zQ`?4@ku^8qn9$1HCC9MLf02bugB>}4f*R_I37%ml=*@oRGc&hdBFPee0ta>xlr9@W z2WLCPzADx%xs&oiQ6sFc?YB%?{U^#MehyZ^*EZYci6_O}V|*g9P>zfJHnq)e{Ylhg z@acTRM9Nm!oJu|;)I7zES<L*&j9JVCii}x>I%C!uwH=WC(<Uj&{^>(fX<YZCV-5Cq zH4tSlwJ7V2ELqjTlGZepq%>S}iN_co2maG+6C%FDswv-5MR?YE*S<%!-4^`PFDV!i zPG|ZhiQTb-RvMl3Nv<qcne==6@UP$7HiV71sdIYS@<<Ecv*hb6(Y)nJm{L{y%;tj) zLf!tGtY@Pk8+6=8i;X6YhWAmUo#ekycSQ1Eo2xPj>NJSRRYSFr^v$eJF_NapqSjB+ zc5s~cB<-6>F4cpKCsSM*Z`(w2oo21u(yUotR%_o$+RrmLd7Ne<ZZQQp7Q4)+X*qdj zKA5FZT~GB)6h>{Gu6@<CPB&_UHA8zLIQ5b#+PM5F$}~FHiF<)1o(*W8xN~-J?;qhl zMkJU^z58itoIh?hX^Obk?t#*jo31PiN96{NNmOsjtU@H+jI7`T9;&2z-L_9}Zj0hf z3Qoec$b!*s)-TitrKo{660T1JnGO<q0u)+67*_Kp!Z0ni&uRet9UKYWWg4r}$}|p! zCuR|@5W_0UY_S(dNlk5)Yh;^bxkek&*%@>kH==o%g|&81*;1j0;OrV{L~kW(lVat| zf9hvsstk{K-TBXIwburj%J#gPPe0SfwD+Hnx)=!U1oP^JlXXp@jI{)OzI5zj;#jc2 zI2QcGOk(;-AIo@yTTbf&t{bu8&5?8MpVj7qMxA@cXU>68AKXlyr?Hi}B4pZ^upB(t z%4J}hoG($kICqz?bVO+ho5|X(?@*FnE+tiS)rZIb7z$6d7=lnL?dvJfeZn|eVV9kk zXChM4P|mH&dplomh(YAXf6DEA>uO%gk;hz^_^Nq7k`Z=eu*o?HZS8T2XRZFqb)3rN zg615`e)w&PTgRi#HZ?OU7>J%S?a=Y6kv{rsTxpes>#RuIR7=MI>^}EqxxAc4FZLXR z(IEMLAGcp&Da`*gQ!aFuPT5D@#L_8RX?(3CPEY$_ii_>iDIS2fHvpaD1*n5hbA;zQ zUwHN~@O<K~IkXS<R@iFn!Wrtm&Z{{@NN=@k4tX%wlx0AD!&A&*A2kU&8EZLAW9jT2 zd(s~de<9Q)jz6dK%4P3vga2ebmTO;e&1?5BWW@vZiN?J7-T{8l}$;YX_}^umaF zJ;F`Dd$RH;t{Ca6_(8NeGy+ApFPMr#zgAZ}L(V(6dm8~&u6`;sJ~$_{ZCJe_Pod{Y zEtnm`YOmn^fq>R}JR^K)CziP@$6X_1ggPzI{HFu<|NR1Jx07_0j9(ycoM2gXLALcm zbu4k)71%6PNAu4T9KQ<H;rz1<j)VA4W1JO$0LeB*_y~~bG=p!?d^Us(LT?Yds%VWs zA-nrY#l{2RbW*oy!8M`<cVMw{Li$m_xSM%EebFvZ_M`<rcIVhQLTwDO7(7oEplB3> zFVw~0@jyG8UNo}<Dv%J)7G<*fd*DPNH6#o~O?w1dF_FGnZ%NkouzCnrM}%9HToU1J z3PgzGIO+8vE8%__RkzB^zp@t=9a?WWm6tuky=S9k6^<ruw47oIr}NMi+|k&UXNaje z@*<96Xqv0eoY?`~P1Jk_)ChNbU|p7NsBKQj3+uz-=KaV1{&({ikbjP34e=ejn-z_m zfIp5Sm*fiXOy!>i!aI}sXBXie!(3z|VXh*1dZgy4$B*xzS+20mEJwPfP=7PYQ{6S( zN2<}y{|8GpXA<0@2mjL4`D{nHL61ZkJOpy<`ZJarxP&dhE_BzTv(!*$i+`&l4h$9~ z{=e;7bOh*MwobCz2I#dMSHT`jy^T5@)<9m2piIX=sc@rq>HtQztR2*!{V;X8%~<oo z9>7*X+~^w{0H#atsAoDt#Ly3`0emDOBA!M3*aqzm%O$nheihw^jnqDi<?1^}YIErK zgGOq5KwV|C{CkRq2_yV0@acRDiJT~e?l=KbP~hw|8;ga+9IHYVI+*7_8s0l{jkGyB zg%W-w4?a@DZ4p08c*BNtj0e*0>SpmZ{HxHyg`MYXNJwAth4j<`2B()z)S!y{fu*kK z?^snn`bP&C&k51|e#Rr*LzU;*5H0jVv?2-7YaIpAVqb{fvX5pD#5_2v+up%Z;_n@V zqmTRh;b?;m(d}M{&Q3yfQb$3w$rqwcHbgggAv!+^(WV1C2uCLk@Watb0|T&X<wezf zheQyOx^h}GoQ`tnCCgyeg7vV7)ixm-Q+<Pw;he}B3Yt@>r@A8&DTjsnlG%}Rew0uT z=Tzfg1ZA49+1aVJ&FBYPPC;1uVFm!Z9~3M+Mf&FGVSY}5FFowd@jpTCh6qZu^5pbP zR)Ve6bJ>VqO%B%NjMc!gQ0oYTNi=COA(c;_&IY(F^0{J01j$6_)waOp2<b#&k<U>j zF?A@k&b_TJ>PjR|Kw5xVoV@^9k1lRuTO`+!l7=NQ>F23HGrMVYz$QdZrqf30G^}cn z)+N8%)3Nw@;>#|P4WVLOULF9LuR)lk3^zAegVObw|97+M^^=9T_L3(b)Z%DU$q4St zS)z-<*hO_#VcaSYpAAcU1oi(m;93Hfpept3tPP<doZT`j(t=UCsRq_P-P`J`ny1v` zC_5`yDRPW(H2Q<FcN!S-<bzsb8z@==D7@nu@V<hnpOM%v*P=RS5(*-B{wyN*p;-xi zw4T=`I3%D)M@AJtBqVGkG}=gL%z%S2URX2^y23Q3Ud{pzIQnw|p!$jA-~dk+Aj8<s z0(i#OGjH&YmOk?ux(SBW+8(GIOIJd8ImGA-f`l8Wr)+_S-$#^e_Bbq3h5F`%M!UIA zt0fKZpAbuFh(@?gxT2&YGyom^dt!t5A};I>vZS{n6lo9#GL6ya<WgkavOu)2au`+C zfPqlYo-jRJ!ocmc=6s-=gZ$>rtRne*sH&iZ4Pl~G^YOjy{5Tr{?;%JAjH*640sfI6 zs(Pm@^&U#pVG3b&KbPb#kdy^8jJhyX0TBL-lpktnjgajfQG9ysvGAiY&B3~N)i$#6 z>Hs|T%hW`?L)^Q1wOb9^^io$Gi6)PNSBUG!!8{~-Ty$XFoiNoQV{hE{35!KONX z4Qzn*D9-fKSDB@6*36c^^a&DMSTzPC3DP>H4rcldt)n@SgKS~MwMEw==L}G=PWjMd zTsQm<@%_@#!T=<dkqAjvYzIL?vBkm;jI`*;F^>{K;lDR3QL7IRgp|=DRxURIA9Lb9 zoD&o2X3KP}nk{E5Y@sep7FH{QET){N#y|#Qx@5dj$gE4zi?qP(`ibl&Eh`02Xiu(8 zip30TW5l9^1xGCMiI$2YcdR0q(K1NICY#MP$F#weal7>vFy-7y!piEJGKe-mHuG?0 z<JNE`ucChtSAxk>xKg@Ga^-cw#;|&3R!cfp#tl~@LoB$mPIKjTL9pC2v#=fB7!;nI zGaE#tnKG8nls5-8Q%=`B+46&VvKtm&^JKZ<$(Bq!8FzRRl=~1wqhYz=aNqsM;W=mj z@lcx{w4$v&pc?qoEGONl&kk$>OYCM#0F%8TBOi7%eApPShFiMu%KI~*a)E;uWdq|Y zr@6$LaL3oj2=9bda{(5}*-sY+kfB?3f$~kAA%#1djLtxj0=>Zy)Y={}r=)CKM2gwA z#)5*lZMDfE(hzK<w=Ib4q0q~GHlLpwR{$$&h{F|nZ>o3pCWi|^+-2(J$zTK@YIh`B zJr)n5-nBZ|)V6SS(1WZFR-ZaDR2K@?&t}9)&c;twt5d0zAY+M04y%QMdW4_mH?~2! z+>SNj)@Vy@*li}<jO(Kcs|1OAW|v#t$6005u%a>b#|luA8b)0quKrLF3R@O7i9iL~ zM%4AQu}!>1ER4Y)>Q`0RA(0Fx^az`&C$i#bg(^5~6&a~Z6L`ja8J0j9^NHFv$9&6- zxdwi^na6Ah=rNyRE8j6M2%0g^%`|4UGtVW#3Yq63zcHcY>3P0w#=IbP%+Z&cTi6@y zF~6NvZsi^bT-G>a+%993sxOf*r$9x4!u58?-<yu-)K(;sm#{mXi<>b)-coeh#)6%x z^hB=VAQ>0z>7Yj5b!_E}yu0l&Kb)Ci%p~$2He-G~(`QTvd1om-<_5O%9djNotYn^7 zv^{1bR3Qs?RjXq*n=zMV9CMXD=KCkKInPJTm>-_d+C0w*>3KqH&M?oH>@lBgd(8D_ z%%@r%^I9|Jvl+*H7h~oz@8ENgHr=qDyqSY)(7%}x%2V~Q6zC`L4lz%-F|ZAv{9fAp zRGxGL$Vh3nZe}$=jHsom8X~BddT2(4WqocH_pz)cy7-Jo{(NFj|B3(3=|7$}{olAm zehE$nk$rwgrAb|avSYN>i{0}#YRPOQZ<Cvt9&q-PySOOqJf-?}J74~sqOaNz*C@rn zx9RQmZ?JY}+U^2-xnNcW#!!2)`>Jg(wS0E--?094aZu6V4$#rnG=10bPDk9f(WUu( z`?k#kUzLIHqp17JdM|Zwv&yYe(P{<e>8JimILioUKQ#$il2kt&Bl{sn0)Os+Qw&;Y z=o<t0h5dD#Vs|fVka`f%OMUv$ZtNBs=r1(bm3!;aFf_f+o23CzG;_lHSpy>1SvmWO z_5Oq427=cKS!qUNcRUl0FLF2L0UC!~kZ@F;>?VoP$Vj7dYCy76i0gdf8h>l7KGhL4 zF&Z>`y-gDy0H4J6FA%;61<&EK(dzv`leL|`1-W{52UvwiTidJWvy4^P1JUa?M32~B zHJ;a>*{^T2U+?Rpk{)_8m*>K=!Py9r><bO_c@Rms1{n|cv&ti%S$!`N68R!16x<0U zvadA&lxPx{{<lD^Jv`EJyb?HG4;)+NbDjSheAjgnOWODrw~wFkU4zr*cd*O4;{_yg zT&;tS&!B*%P^=>gZWxRcpeSl9PJnHaaRUFp!gp|3S0hEN^7%sH`oC-C@6`Vq%I|DR z(+cJP%(uS;>271nmk=LcNuxJbkC?Rj>TE_|be?yv&7l${;R~nng7W|>d*;vd{<GXv z&rC;sqR1aZHXZ#J(EER$ju^vc;-}RHPuP+j$tq9XqcT5<6k${Qk+v|&HT|=w;<4pt zm3k|b(#)a?*IYj{R8---oJlAAdGG&u@85#GKO-IeEWoy<08_s(X1luFR1x;IZRzR^ zo#5F{HK1Jq16rC+;6_D?5KE$B%Ma|GKeMz0dwXV<k*%H$cBZL~E7L0cDXO-!G9Ghm z=i@wGGqB2|kqL6|bXjh&Hjqg@xGS*j6>d?rVOXNZZ7by7XC3zIr>EfmteElM=x4=D zt`H1)cBVw*Wlfqy>+!R6=)}9Sw5>jQyZ5tn_*pv0F3AhVpNw>HE}v8MQ0MabKm9QM zGu!>wu-$K6UK8pq+o|FK;{_sjKw}UAT8CsCq2D5)<z~c*F+RE!&NiLnRr6c8OdM=t zcQZljcJmkm&*<x!8>Dx*h9JWi7=a;UP#<mMEJVI>5~l_wlb$N=tjkz42RUYBoP$eR zjDaK2Gn_*&T)dSd17NkD$(sSrq?fv+7LjF~$(w<CJSfM5I@j-kp5L-uouxCGnTpDk zai*?QAXjUnXSME@Irdif)tc418*`L7{B&2V4DN`U;;eqv)*!Q5i_A>kw^wVCtX4nu zzF95(dywb%Pj9tS=yG2-Sz0?(Ta^iGmxQ%@LX+qxh?FIXCg3h6B>72}Ceg%fX`%G* zfoS0Vy#szXyV_T#{N5$y_wJtGKL&ZUPU0S<m8rwispHWsEtPJWZFu=nK~z6=%WTcd z`u8Bu@1Hnzl!ZCZ8qEaOj@8z%gtcqJ+QZPs2$Du`Rc$C^1PP;`s@8NMzXo}J?Wn3X zO~|`po?p9qe(mA<_0uB;m%cOx-c{Xzq<jeWZYT#_ZS{t?ZNeIquy#bad3ZkFB&==; zt1MylhL^2*qj_sUBM_Fa5S}lbvOV$FO&zH5C%?)(zj~_!HU8vXKhLj0o?kn9enr&Z z^>+g}LcZr$H_xv!&#&H|U;RA426=w%sQ!*Un>!eW_%Rkt4wV@<s1)uU=;q#ZvhJ$M z`e?H(T{T%Bt(Qf94N~r3JF25Kdga|P&#zrQzxHtb`Z2I1GHyS&ikM?A9G2Kuh2oCC zpISP*`FFqj9n==)zhVl%Qk}w&`LRls$&bZ9Cu^Vl4?7}--+tJ478sxWtlwv4g|e<g zcvBz{*i?|ue*(xikN*!;jz4Jfgrh4bA39;ul=$T1DyK{yUpZk?eB#uDE5;vv<j`Lp zI)40!op;~;kb`$Wbo{S&9$txu$4oln(8>Qic<Q7h;**Y=GIUtQFDrK5l^<qp%g!oe zM;v`nJgai@)G6`tmE(UkeD{NPJ9wAzJC8VY*Iy0)<?aU$8^6o2U3U4^A&2a;^YGX~ z<72VmyNo|%n81I;q=UyFJ^9eeqmP-gRo@>q^~kOHe%qpB(oylOtRoLSvSRWSF5Hm^ zjh}q<6#K`~hwv{f@WGSf{7a#Meiq8g8h_+5d}d{39dwA@?x4w7V{gl_(-QrRKl-R? zrprSn*?%26BYx;nb`M8RJ;F3N=IH6>uPLA!4F^UtKhUjdiodWjYykMDm~QcK%EU=A zff|2LO+L<Y^IBfOibnU8m}w*;P+h9ku{Eko6@nZP!H598@K_7tc|Zi^&9R#dfLm|O z8h|iJ^WX3|D>_Dh&Cmj5CFqI(?2D}dNOFZeW&pOEdTRjkG@Jj17o)Gue1}~qbhZ^( zB=JaYh)M%ic61c`L{#WR$#l>Q0l$X^e-{X={t-lc{v%SS`d6!e)TsVd*5EMwzw-pp z$QWxd0L2e$Fp9Lttiec=V*U$23$QPS>(xJkg9D5+-JVX!)0^?h=lT=f82K6S3ID6c zZ$L`$J`gT>n0ELfz>rYAWW-@I;(k_SKja5MtMH!AsCsPszXf3q8V{df4PJ{T32Sh| z%B!~qqwInCFEBC~7{NPWBm#__mxd7_)?TAOH>#m=_2*!f;JOmHe%6Xy7o1)c9MV+~ z8d*EmtcVo|4^QjrzAW~o;sIH+{VEVOt$x)o*2*0RFsszQ6;?E?c7u4u54;7&AIz$N zfA+L;D}bm>9Xu9vFW0vSUR73)C=M6_9EL;I(6H)P9Zn$17Ja|oy$%s*!`10WSB0{X zs^j|Ua-{!91^(_|#aChVEFz4v;cC`AouR&kNDkQ$j<cInW+A1U`X-o=PuEJ;4&-f6 zS0R!XDL7uuLe`vcg&t@{QA`F}A8$l!#N<wop|hRT9f+3&c<TJwu}~0sYfi&?i2!{S zE|+#IOuO5B+A&$%f^Ox~{tVM^Vg~!IRA&bDcr6wumZuiXKqjC+$rxd^Ie-j4b85>q zXm6nUAxeX&%cp~OH`OxI9GH0{M+%1EDLa6fV^eL7dsY~PDfx+km$H!DSmWw+B+C?B zakw*QGY}aV`~(T*IO&sTu)IW}S`0^f!Mar^zt^9T04iRZRjo%_f=ci5UA@8ltN1Qr z?X2!bJSD$-6W_DHFJ!Vq)ilrv)}cl^;j27#8`c0ozlXBnSc;2KIv^Bgw$Giy>VYg9 z<#B`Z8tL^CgYuRcdX!JH^(g0I6r%c!BH-ua!yEY#ai|x{{_3I`$O^Duh5yS-5#a}D zel61Cp)B;%I2-AM7@`f5RCCNC%|Qexnth2JJ_0o9CyqaNCcP6=Vf6**zz=mqaDTNw z3A|7}4^#{Vc_Jl;Is=#AyQp)J=R+twtj-lW6@-S>$-pS-{`(VRW(?3Z;>U^Y6(Lre z>47wWRW_b9)d0U?wI}IpsCv{O^GLf*b?ZDBsdt#LCM<X*6KYyL{b&*ZnNYHyXeOi_ z)zt81q#m!yhnk9n4?{WDj$!o?61@<b3&2I};g6h+hZXrCjTKwan5+o#E!6@+9IwJW zq4`m0P@O1)M$`&6s-XZ#X++AnsHk2R<&3!QF(GvB$Arij046jH26Li|@9ONwX?z#c zd?!<Ykwq9htZon1V`%c85Mo%Jj&!zL!h1}SfF!sl)C=2?fIxdL-XkiJlPHb%NJr#7 z5vE?=)3WBa*-~|)b>7qHy(*h)8c{76g=C%NIi}fhc&<fLz{N;q!`2tgz+!;cL`c{V zFP$Ny{yK)8LOleuWa2St=I|I2OJwFTFN%l|@EGx*<S`}^J_F@PwkeNs!y%7ps!sBl z&Wo9Ge-j?)r{&Uz*-fD+Sm8dsqapJ{w)$10Mp;XC9o~i15+mu57gBydjUA4waE<(q zsI}(zbJ>tsEz?C@Qu66m+@hjbjaN*oCdf-}VQ(H6Yh4BeB)hlXhYfFkm>m-czL^fk zdR5RM9nC>$jR1?Sv~$9oRO*D)7}?;%>S8lT%sH&~F|_kJHYOs%XX0drmDs?Huouk9 zu56|p47CF?p<DG~HqvBi(1iB%S{S%mvNZ@x3<o6FLUTlNE%fiU)<U=1g0--9q857( z*OU`d-+*!=YR5WRi<YeRt%W_~4L%cAW6WwN*8*Icz7}Z{Z(}X0GOR@|Z>XMw<5CWI zlqLM|0JV>pV5LyqQv?m=<HPIuFsz==szC|9ETl>y{XLykg}*k~Yfn*Btgh}+j<%qR z7Y-2-^K=#kd9ix7Clk;_RKuZKod1Fcjb0P1p3s;lSjB&}dh9D0gl3n4ngz}m44h8^ zPD{Pp4LgNP*8rZVuL-PcVIx(zkHWD9$$W4<GS({I&+56_D&E8D@hdY{jn7yQLAfrB zmgzE#X*`w7^phV03i9x|0apkAT4EBUP?r{9zk)6e^{$SX4XdRP2m~1puSCR~M+652 z!gUofv;cn@267`YqMl&JM`CY9&q#xOg(ocUQ5@W-yVYy4jlDyBv3KHSsQ`UTfaWCu zLgz_<-f;k$ml2?6Y=Ew_0m75&aB%l-1S<TQ)pJy2lwkPaRxs=!XwGcFQ#ZR>eV@hb zN<h-Nn%;y~!h9_BRwwlKeO3h;H~XO~NpIg9dRuDf?RlZMUcn(<Y-EAdb}+!TN@}Of z4iF}Fb`g@lkp=7}auL~F(Sv%a8TD4rwOc`1X*9R|^3=6E-+=R7H_b?MkF@CrssGaH zhYSe2sj$LAQXZ&iK~GfIBJF*osi>El5d5EjjTaD+4_=mEkqXGg29S*gkW&SaL{&_^ z-4-DKHh`RE1M-<r&u*lio?&%xJOU<dgFW3RRhi89S=C`A?NAriQYgI@sG@|rkeNu$ zf-%n<2n3RWGVCqpM7^*!hChs^+X5YcSh;vcb+{sfkhIUn(r|8|I$Wm~;cCuzg!coG zLyKzbkrJW4+CWiEv6=+peFCuvK)i1Q@oM%4>3azdNEJcL-ZhtB=|aB;h*JZSgf>yj z@>!ptI%<|m2nIe0RMi_Dq>E5Ma@bEeYy!i65~#qxFrjF!Tb)B3MbuR@5*R$k9^9$9 znTGST0yW{5NKKPQ025$3a`y`)`4GN&4$2BUy%uQAwD)*sv;dtpsZ(kbZnQ>v!GciR zgxr+%)pB?WAK)4c87py~JOwlQ#zy3t>=qezIS^TuMC2c?%7n=Ci97b$0$?`>Y9ckV zuE@}9=7fil7=Fa4)8Sw6ofmDl0Bu$6LEFV39Fpp{vl=nhNkJjiZ;`~%myS*fVzs`V z6+=TqsZW+^O1*KSmr}3JG`A&Yz^`P$(}Eg<im8v?<aioK`U)eRW{<SGOq1iS6Fua3 zOvaI}G9zt}k<PY9IyN~Ht#9gVj<f+IogJ*ezYYaH(?e6>9TVG0f!C4(fyxi*sbQnf zMH%NJwW*NdsxnQ6tAH~%87|F)v*o7ecV-3q%QjD4-mO_&fDr7kdIyuZz(&^{Wt!+7 z1iD;AcVfmtZZU(rnKp>%Uns66gS?4BE&-;{%qBV;Q>%fgHi)iVP7v5tFH+TF=|Hs> z7=WtG-<9fy0RMifHW7}SbM@=p^%<R(zC0Wg?wF3L{xPO1d7RrNtUeDhGcfeRP#jiW z7-d!;M<t@Uv;o$n?iKi^x2l^!<5-D0Hy^1SFT$hY>eI>8WAfB@-K+7ttC~BZ+Uhe_ z9(`-RI>~%BpI`k}zWU63waI*Sa`LNh%vYyOU<S()bx!iDFU(h8o3G|clS0@}P%TMa zGf6}8QE38dSyz>qNQjEm#k1pbsJky)|Gs;Mlreg`)+i>cb865oTYWU0S%+c%R86(c z4#T3iL)GcpkcWdz9hyeeDr1yf2GOLAB}wCD9uffE3FBL?=r<3dE3sQGRCVa+3uM;d zak)m0%UaKW1_|hh_?HW5*4as&IZ>OP&Y$g=lrX5sF>`98A&6i+fD<XdxY7p<9%C<o z#fR-Kg8`4fU%>%24{LQf6F2^kGe>O!wi{o^m#`k%tjFWgPU>IwMD=ONw$j=k-DnQd zPs#`pbterJOJS)I3&khUbqUAEKpSVeqDUX0X|p9fE7*EPa!4`G8o}r`!*UMq<G9Ga zzQEksS3?oV_~XNyMN3sD!<@(-4~_+S*_ZL)Y^-p?K-yHu>Q~<cW5Pgj*pF|3Wmhv$ zm5-H<^m5j5K-6Zi@f_qM6c)NnnWL4>LMx9a3%y;!X^v7KfUU?X4P{)0zUtYDnw##; zHQY2*-5=L9d~F$NwLm>LvD(^BbJI2Et7h}nJ^YH?G*mrkzFKC!TATc8srl-8^VMC+ zuO2pEU2VQv2Yw+&&%y5;q~4kbIwZLByVJs!M>XzU)8w7fYH;QQ@hYomJal`mE+ojy z@oKBf4)V>SvTFIJ6l-I?`MOjyDd(K0J}QlH6mluQE>fo>i6qzeSt};L8;%!mwU(I% z`>S*KJX^hV9L<0+^}@`gEs|C{a2L{#L1||vAHu3eB3W=82y3HcC{3|i61g`8<AzJu zN@t*kg~$_5F4cx(W7Lu^pHakyn@f3G<Glsp2X~&X#SE<1hT6~L;Gg>qP7trkjthvN zL(1~^nZm1i>I;7LF}}h>8g2AMHuLFvJT?2FVM-Qo)K@3&F6V;k`1?Cl^&%F|HoqS- z;^5xn>SZdgb+y^B1?}?GNoYr2zh^d%MN4e)n9hJ)h=_Wa+XE2tLRVqH7B2(d9H?uZ z1L;CA6c<s_hkXlm%F(e<KFm?KLQv#b!_=dq`W35NphM6izv!@Lnb}HJgLb*9QRMJ0 z>I-u(vI*rA<i$mhM+EM9ePvP4-oonBKmu>KQ%}epPqBKtCuyisEts$Yt&7!1-K+2( zYx%+<EWalN#Yq;cOL}UIuZ$&E9ZLa%bD0VJl<Eu{wY_QkZ`AgcTy>}b6n`5x>c3Q| z9nD6)F@&2F_311!1{o>2+i}LXXUA<j*0Z=qDgZWLGxs+wI5_2~n`cywm3}`$9@r4B zV)gY3F|lh{y{&kmbwzDVZ&08Zp+izXyIO&+xDe-tV)zYAJ&20gE}Hail?5P^JIz*k zozEUccpt@%!CBrRyRTpw_{XJ+biV{E<#aDkkYrYa#7&R`tTLOR-(E~E;1<Pp^=1=n zkpWRN1olQ!`xOpg&eld{(`-NQ^{Bzux$5c(yt=9a9pTh+W`H#e8pD+u$Tx(?ApkE2 z!*NJAw)p#VT=WooiQ~A0L)G7t_e%zeMtjE@MLMuyUOGcAf~Zcw8jhP@f%w7<5JQ=* zBSeIr8u^oG&*2}(ag7+bo!e}KdsF7q_syn!tGV6t-hA?VZn<pvso8Ru>n*o2$?*js z#DCQ2s+4JVHFFX~Jp!(7`?g#WP~M9%%?j9Z$qHt}-55#;E9i~tqf&0-O-EPRRGVY~ zEvg;^187>)d&nkH&h*aUyN7Vrck<%v_sPx1k@~W9r_YuhM@xM+U&ZFI4S=+~muV#S z4?wfzz}Pr}<0IU2QsYeFK&psW;FW!&f;B*fdxrz{Rq(k+<h_o2ZjM`T%;%ZO8&ZUO z6yU(Ma1VY(vSv|U?!^7VDB)6J^}53v0f>6Vtm3NhD6|2Ozk$5$qTgJOYg!V73znVn zrd<Rb7butNJ1U2uH47#Q+Q5hjk$jsB`Dz9><ZIZUIwj}*J}yIvT0_35rsB6@vE`?x zr6FI}h9%@%mn7fvWv&xs7pqHDosH$l3q!pLABcZrEScIxb*ZBh%CXEH-Ua?5l*j#H zgaP$IM4lhQhiW}?(&iyq{ZtB!qX0y{Y~kv?fHACe;Y>@k<asX;Pa3TgJ}|H^!f=>B z3<PKEVW>;OkiMaP4fA**rm<jlJZXT*-0Xb2nR0uiybCjYk7$vVKUNRrdHH#3FTcXe z;%G5!(N^&ktLHGQn5IoD|4%+0eUC)(AdIM5Py|ynt`bNYj-!W_|F@vx3BfbC1KBvA z4jst+UOJG$%z24(7h&c9%crAM$b@EHkWI{BskE#<QFTtwDpYwYR^N`-r^BysN9cbO zm)4xD`vLCUyOOETgpUD8Z+({B$XzsBY&aue4$$3R7|3*o>D%o);Kr_?i_PFM4l@VZ zz5SbdQo>Ez9(uuCq9{^rPbQXOGEOr+iAK*P9?wdsp}L2Y1N9o?Y1@#ehmT+`Cwyl^ zDIk2CvKlgc2JsffJr1vIp>Cm$0&NY}uIi)1xY?WwRT<I~H7}q8P#s&=Jq}@7sMb!< zd(tv#Ua00ArhjiP(c*jM;p_&xRV@xzrt8#q>mYZjY+VfzZ`#Tjn@g(Y`O3q&(}_I4 zptwSmlRjA3i7d%(w6b#drR6m)spd>ez~Zzhij&jAWA&xQ6Wi&~@Hn&Ns7c7t3Oiq` z&61Pgo-Gqj?GBL3B+d!ZjY`zLTV}WcHw2?-tVY`OsJc=+NU3k2*)Wg#sWW0$mr9|$ zuW+v7BdjbRMWErGABcy|E`7bc%~cPfo;aAGTF#vMn8lASkz+%D^%fMlZfx-SagNCv zTsjBCTCDbS5!@Le+vAk?i?If#Z5?V~<--Ruo`HxB?0Q>E!j4)BHtcl<c6p>>uS>#S zkGDzK&HeesD1@eAhvM;D(t`lSwlV?d0tv<7=G1a6lM_hjwoS>ltxrJY>9^UizjDN7 z(-MO6Z?bV2!3U?#NF=AyB9HVk5R$)`D+QR`H36N3!x|1>w?M_`Oi!OpTU(*J7e*NG zQ?mT^veKM<1D4Hkhv6)_Z1tY0bKP(dj95Fs$__mVQ&x+4L9+fhR9_bKI8$ymYX*yO zhE=mCt!-$R*W$j`OqO0#*pAgeZMygh)<M3(oWts`@@7ZT-~S@_<r}hqCJLLg0u3_L zEkpo2PeTAJy%7PxihJ#evbDhoo}NA(qZ&+5JMh7TZY+pU4an@65f6~m7nCHz>ivmO zHE_M#Ghq!;=gopFWf!j;Yv`iR2-SIkCL&i|UfYzhOYG0<vzZ3}rhKUO@55FkewDWe zwK4jd><SEVE3_t_(=Ub4)TE-ds8K97$NtOP(?4kB{fRt+z;E;RAh3dkRo7%!$pDmo z9H7Pwpm&o|Rp|r#%PU4Pfm4Du9qS&UJ7YRA6srQ+16THt+Ujymc1%X3Oy`I^P?P%g zMl>pBM$B|wDbz@m6{&afu?0c7yp`s9Ju7V!CD!_@4-MAdJ<J|rOR>fw;A00@W7iP& zEUIJ(jkk9Xt7{W)%iVZ0vq;D+P~)u-CuE?@J&rw<n2e*bm7L0!Vv8%{C4d&Q{?#4= zv)5ntRn`lZc|8KPrWky-0S88M@S_1A!tkgy&N8JB3{}ad6Owj1<?-!pXhphsWO}t3 zSyN=&BbQjYQFRu4m0_;1x`l^9K#@Ff=sOh`4LPi+fS)@Z4>hF^TEN&_0>snpQFdNj zh_SU=6ewp46f@LQE_ZuWT<g*#+~d(1vRhc?vA|MtP)y^|+8Br7A=|MRCC4F35e}O{ z1Cs%+a3(Zd`WC;Nn_vjxQ~>T3xRxZiFUbYV@gNs<4P1VCvV~6c5;Uo_;giD+OPh}w zPW@BnGsvFLPH>6CA(_L;G;oKjXK_-n926`F{C1WbQ*PBoCUTE65xp`pk&FB%;!@)< zk3#jgay>1f!Ece2#&Hh(SK18BICQzjitOo{!IDff&?x#&dpq-LG?Q)9EICaF=_HoA z+Cq8@6%?iqX4YYdA^0N;{v0;G&JAQzz0Jbg!{~(<yNa_2;hLEG?gWzXc476oyW2Bb z@Ae)X=)KTmZ5_<OQbnc!D%kJFtfnNm^D_2ZO2)f<HUmE@)N8Pyq9EB-z%_rq0Qv`8 zht>SzSU85G=sK%0gbx(TtfB$R%ZCr=zgXEUn5QeWgT1j4l)`pEx|?c6jtHw&aG6+z zZu7#y0i{;qSo~r1=PPk@ini)a^jWB2X@TW|#p9xE4AV}SW(Zg>G$dC+<2S8GSzX6T z6C4O(*~nWi0_rLpU33FHVt2(V2T0plsBdU>`p)PPfd1H^RB9U=f`w;*vQjixD|ki! z1n{Y`fFPVx-B^e$*GQmd3j|-8oR*D*DnWuqM>~;#P$L@&HEBq|QF&)8??|&=IQ$K2 zYd7#mM*B!36&WCkBr-q}SJ=ql1S2n4g<ML9BJ4G$opc86N17tomY$PpD*tjQ!d~z= zC}OHKCPnxlgGF-D9Vi0G7!5;LL5)?W2NogNw{7ykG46;!27m5S*7}+Zr>^V93AGhe z2ZQ!?Zo)0<Kp;_dd>|-^?0MwB)cdwH3iuw8PQvvWELM=LQFWjY8x6}8w145E!}S*` zDI9ui&aDa8)Y+UHQ5R0E2seXUznujiJt4i-Wl*~gmoINQEFLy~7c2Te)nso^9Nfh2 zn&9+P!%@QO{}T2VEQCH#D+ZT!<D$W>{7CTv-%XhDwmw`Nr;`LbF-G#sx+T2r(e40z z)L%VX!h!mz#9?u1fea!Rw4H?|V5oN{QUGCj2@N%lvrxjABYbwG*6_|UV0?BY#MQU6 z%xvZt0}D{3wEPk*a9jTtMNN(R(4dc*cHiMhIo@udrxX57x_Ek8X>IGRvf%asf#E`U zz|<S6e5<U%d4@~?g6X%)pqLR@Hmpw6Xx-%?JOV8GkPBh42<tKAm-^v5xc@c)V)ATa z1IWj_`8;wuOP(#(c!>+7*CkSg8i}7{UIG`f13SSwtBKvK%M6Kpj>6-*!Rj)o&6-5+ zI;<|tYe&$*HGP_;ee=N^!s0;yH^y%DDv^uN*bkp4%n*1X&)zyx`s}an$0D;4`a^F+ z)R`q%f&a(eyZFkL=LcRj-EpUPGTjVGAj>9MIfLo#jyyN#{kZE`xwfyTop#&Cc6ZNY zG+UgfUHIOrJ5_c4m}nAqXE$i2WH%96!3q(gC9Gf-Kw^<1@dqHJ1x2hxfJMp*HVBlJ zKnxKg1Xw=b-|w7L=Tx0@s_Ob)+uez0`rf*Ae&_f6{=V<W|MKun*c2f*`r#kx)?a-6 zuN0^HM~498AJk7(>fzQVE<5=L-v(b3N%!V&zUF>Ee|?wFYPI}UNA||+zxzY41^UeX z)<b&u>2jgJ`$J?8(tDu3{!P77zSf|qTmRmhe+dCudgie@F{Ck5rvF`e8D$opGHN0a z9{wm)2s4=D;;4U5pU$7E>zDtv&wcLPTc7_yecc;R{x(m(`1zkW_tw9oS*OOs|5&|d zv^@DosGX(5Hv|VY-ua)4CrXvvc=AU|{fxr)mwy<p8!7d>X~9l4nn^iRmj3zI|HeOy zmKyn2_@jRVrww`K_eY@7*MI%z3-Pw`;&+$|(){ON|IdiWEu=tEZTxoe?r)8dB=LP} zd-orzS)XjBt9$T|OGW$dzA2FgZ@vB-PYUH-W5WMi+3c_4k}A#q@NrwS|D$a7zjDQ; z*{?n+_}oTs=-c(a{oT(CkN?)|zkS@+tU86?`aa#;-<x-z0-O17N<^&~ZO)_PBd#`Q zOP{L#{}Ij+YtQ2E%j<tfz5YAR*MIX{U+p}Oe^nhNMCh;nfZo7AJoq(D7#mA2!Fu%s zG+6)SxwroN7U0!jeYxdH3D$~uHip^=tVQ4wur3S*jSiN<`l}kO^(((WlD*gntd-_L zgSCG5w?-&gd%*gOVpsZ!&c*(E%M-oWwkIu+UC4Hg#nvEOPx22Rw>7Ilwr=*Tt@oq` z*+RVqvfJ)S4YGA_e{bG>5DUmAlNgZwpP%~y=+GO#P(bzu$5BAGy#71Q*KyS9Jdqa2 zhV1;GKX)E?ueN)rLHu$HqSYY&wR3O1`K;v#HH<%Oc~Zi-N@CJDwGzgaLw@5)wY9(e z!+LAKoBnbOnW@3}`E&366}6YYudwc~|9qjnYjj(~*yq96f?90#Qi-bDUJ_JY!1OAO z(Tn?a&HXmUDq(u{of=H*#r?*U!sgcKparJiYy-m<pl<7~1*luQtG52PzORI89LYO3 zU%@qe%m4K3FDbbGHI1?VK>^o70oR<x-#^Fee@DIkJ2>zwgs)%!O_WH2Y1&Su1+L%x zy%y;EuM|tshI{`T#fgBj3mbT2^Qkwk4*f@=AtZ-->y4k>y6?9>-!`gr{MP5&?#UnU z#Qpr+=iYK!hLVRrr5~;WRQ2YSzBhlP<Dty6z0aTed~oiqZ}q&UlwXZ~`|GcL?%bb+ z0Q{sfi+%xzKgA3wSMYOh9k=xLtGsa$h7bno4GyD?aQsc0`~aPz21j5v&i&ZGb?%3M z0%nz@UF0nJL5^sEhs=%`{{Fq!5YGQw%ADgWONs}~uo%~=NxLK7HNTE`{ttdlxY>V* zd#P^SG9%UiV?!k3cYjFVfM0o-w=e^XiC=o-gL7}S0Z4t~Kla8?ocrMq&iz<+?uT)m z!0GQtBs5b^5APm5n@i{Z%<E6iGih;wZ%n#2<u;YzN{CxS5%jrpZ-4&v-~KsKi(PvC zKl%ALcV7Q5$XH^$@unykNDhYr;;ZKjR1?KdmP4Kx<IP`DkKcUb&x?Te`rrNBFYC=( zvFk7OFI~U>Uk-j#-li*+Q>IXDqb}aM51gQ$yN_+=feMj8SlKHM;osMOfByg<4d>0r zK;T#3xN+_aH&Ez)7k}%^^2Ira`1|J1?|<Wc7B6zu-~M@0<6sPxTmb*J?EL@0&O2|s z`8D4B>2nTF&W$(Ot}ndLNWY>Uf1%j<U+dX<c-H@p*?!-HmI=T1r5{u?{zT9CKV{&D zdd9@6FmCPV_rLLRHDl3Hl{1#fzWzTBBvFX$;rG9<K;hR))}aLy$_b$tTirpK&rg>- zDD(Nt@`c*L=Fj>Lw#?_dye4q*yz}`3`uXY`FLZynivOgzihud%iG%xp00^{(zw+9j z`vJLiUm!~J%^PZ$zteN<jb5aK*Z<$ao4?k)Y~Sg>Y>Qb`?>8^nw(r08!ROj1ppelI z^7EhY?|TLaJ5Rs(1zZ>;58U8_dO8?<sfh3ni@*2Y{^BpZcJ-|{=5KxP+i&unykGy9 zskc|Z|F5-SY^D9>j`ll6r_23cF8aAtAC%9(R(yZu?Jr(=`%hna`~2S9?|$dpFMiKo zBf-t<-+t}w^Xglky~zXGFZWA6JoRt+`ycQ4zN`J$JKB34-*>hD4?5c4>-e5TY3kqd z{LAml^DHCw|7@}Eul*};fAKr7y|%9olOD=;Wgz`OU$*;;&34P<{OcX#|5V5K<-C^r zS^mBZ3je>C`YB_y|G%a0i$4c{q2v35rSHpN<6m9+zU(LK`2O2V-<Pqr|L)TFWj`zP zDWXb~rS@gC=`SpOU-q-yeo%y4K3-~HhGG8A;`^Ir2gPr@xG&u2@4WW<kA6<>#TUP> ze&*`uUr;}PM*Y04etxKaPSwxB^8Ndd`tIM4uD^eOqhp@`R{?)&p0E9u8eC8F6ZN@1 z&DZwSS9;Dj+UNNri*?uV#9#ZKzmBsCK`SMmP(9W0MCtjQ7V|9Ow)95sf|D;SwJ-i0 zbbU`sM)j}kzii+2{Xf^y{(Q&x%lE77zw7%y*U`_v(DD6S9p881(I4(;-__5TJKFzP z$M+AHzb~9^zPkK<@%JxveE%O7-`_8Om%kn_;8VlXmABu$^0u+}c5v<OJKy=<Uwq@2 z&S~I!?VE20dv6=+aY2j}kloQeE%&Rb@L&Mkuj%(mZ@<^di59<)i{BNUWI{~qJ8%5r zxnEMm^0lEXpiV9gd1V<M<!;Eo<?l;6SJIKvDeR|pb6F4M=9<2oE$?^1l~uf7_FFnl zec0&tE1muB7VVbjd%ffP75<~JaCNQQUh1dxoGItKJnnl-?MpwEFD-pv{5kl^j_*sp zY`K5Gqy0bb`2LSNzW+i2-^=}fZ_)loir?k0A1Xd@&L0U+QNC9ir};|#E8i>4(&f2d zd;9#qRDZ8%J}6SM3`%$|Esj4&UR(KBzb6Ge7fAhIe!T|J>dFZ~m-A9D^P>yDcHyC7 z*p+^|@Mu^2azB>m^G_8MTmJr^?)bi||E~FTeg8cj{dcwR+P4xumgnEK-Yz=uqaE|< z+J~-ret$<lUF+?dXV*S|zN7!HasQc)_FesdUq}0{@4L>WYh7LE^`|<<?OJaaztBbh zOZX^%7sCy@#{IJ$^XZy@*FEampDz~umw3CJPkCP88O;rE*=~7#UE_DbOBWvM`u<OM z>{D0!Khx2^q=U=*QPMm1<FF#S^s#BX<^Aa5-?qJ<U2xgePuKTd@YHobyUw$#|E_!6 zg}=JmclBSw@$x=*?N7<KEw}ILrwfjLssoO?*7X-V+IR6m=eKPCzjw6%TOHs3a>w^w z?SHPLeR*$|_w&mg?MwYYauAIloWFVV;}6fjtLhw_f1FKcqsjQZx#QS7#+S#V2M^~5 z&(6PF)jv3I8J6*7!~U{iz4zWgsx^>Pe>P9$m!#I;wqC;E@jQwTvH@KTo=_AZ8|H`e z!R*;=NTr9v$#^i$4v**A)4_0fFi9Q_j>n^?R0o)5gCsjRkc9pTKgP#ThX<oanf^%I zy}Nh!zBasf<7f7V_rG>$e>fZ*%^yy)C>^TahV#Kk<5`qvSLx)Ebh5iEJ@4)=`YJx} z?k>G~d2lz&#`9@3o`0xjc4hMP64T$^W!7akYLwmGX3NWiXg)a{CH1k7gUf?G_3f3( z<X~|9AbK!}C)4TV$zU`aeJiWCRbN~l#K(D_O|x_`Ihu1;gIkkv#+)MFj@W_^qi1n8 zxHmb>*au^9TQ$-X98H+yJe6On)ylW`=IP{kem8n@`SM^IJsCdE64~)@9@E!hG<}p! z2X`K_@X6t|XdYdX$$z9CtB*-^H2BKFBxWXi13LLQOZfic`RIV7+ubdG=@yp<N6~nc zJYpGFj`L6C<fkjsSwG2fmZih|;CS}1zESElWR>Ms?e5+jjkA-EA}5|JNICV6-%&j- zz<qbOfcItCxg;>ZyDLC1kIrT~mw}k0$!G>p>C+jF9}K>798J?Dm{;Gupeen>T{>TF zJRjs>?<qjNDHvgz&5jS|gWHb=w`YTUqr)Sx$*sx!`s8?=4(?>r!_iDo+O=#v0@$uj z#^WrJd&4Fk&z8QKW%F8#Juc#$7W7uU#vglWI=wOeXqKr@JlcC4jSdtJyE2_T%Eos_ zM?5<aWb<tQDOGJ|gHI;M2k8}szix~lM+c+y#`x%XJ}CZ>yEM2zI?U4Be5s)HXR_&p z$6Si(@sZ5o_WU82@1t?{^oZ$a>HZ`iT%|P4<Z$rgvO&ke;GM4@3&!~K=k0F{Dx4&n zMJJQ#?yhbwz<f02hwR#=ci+3X*xRDrzBIo)Xzsh3)$Z<-5=HOs?xoSue6o6J7e`a{ zQQUjV`v6XIbn<(UvgqN_e5%J$gMIxt_{PS=R&Ug2TEoB#Kw()M_sUxhJl^O<kX=PI zR7=_2qDd#NVt9>ES8nabZ=MpC*mS&Q3b(;+-@NN4SQYQxo2P7(y3Wn#TY+8C#pOYs zj|P+35QrPb&*s@|pf`}OcX##oySuk%1t7koF{>t~d|#uNtuFv?T(+ZVD#+vGY#K-N z(P8!Bqgz)&qGt8?wbAU+;9B;0lw`N=4em}R^J}9iH+L$(?nF~K3HfwuGChQB7K0Zz z2I{-JtBEM|_{XV<G~=S1UXuo!-hv3r=aTT6UKiz6T}spXTH`2r1XGhhWUk1b-JX6j zO0&ztQDx&v+4R`9SU;x*ZLPgfe!TbWFouiy*`F0O{OxZKC>oVb$I$`I9CM!@Cm;;g zdMA2DaV;pnVszl5_66k(_L3x<&GhG6#|Qd@Zlgad)Hysp8qOz!OkNotWaGij=ow54 zEf!d>PEZS0j8U?ujT`*#d*xDQ&&KR@y&;J4@<6?!fnWY)4e8@(I`||S%>`Qvr=)4m zyJ|yLd#T<nkgRS|^s~FW($RZ^JBs?M)m}QaUM~-RtkLnh*}`H*)9DC$^B@~%Q{a0t z9*#IJ{q4PZG;i>wwf>41fuUO4o^4+LYV8o#H?D7At#$om^_kQjwoe&eJ((W^xwCmR zoePsOIe5&4&!^EL2u1x8>En3(WCWkVr5hYS(WJO`F=`*HwulH%c6Wy#sTYS=CtQ)I za2*G5@hPYS2php+n~RSY;*eacAw|uY$E^5sR$>ITmfA>HmTqI6V_(y@!X#_k6<B6X zyDkh=;IhuQugfks&|H7h_48IeR>-lxx2{=Vh2c3y@?7QuYI|QaSqJfLZ!80PTbu3R zyQK#vrkKRR(R3onc5t0yir2DPGT0kWH0!Fdd+{8u@!{woy{G8&;GK6g9`0xYLZpe> z+oNdyaCi3(Kh-xdVESu4>Y~@tc<@d;f2d!mv9EgQ`QzaXp_E@^`7L;O21i`<4<&|v z-Fr5hXNU4g^L@+YwEy%)2(t8xt(<|{Kd8aMWCk#N*%%CuU})z`Z*lJ-62sv7F`9|t zP~`Hb4<nfL(PL&(I}P;$+avE?N8O=#9(^wPh<9&h`FwC!bT5OeFbInAe>9#v86#JW z9*ht9jswgR6at89>TSg+)n|<wWq0?wuoZLZKq0Ils0vj|uD+!QnYNr1ngmeV@mR@4 zx|8c;;PKMCs&Bmw%?>Y~udQeP>?lL^QR5plZzTj4+*@y2Ed5G}qh$HRp<SOjI1bT7 zq})nGsm(xv!D9POn2q8n;5YPWqDUDI9U!kZ$J$4YU4}!qMC<xJ_43BBqFJ5GgRgwF zclX+0_%pX`z{=A~rr^HPHQh+<arVSjElmGmkVIKvMONrLnMuXa{lV4SAKkjYf4A># zzi7kzv1R$O89KI;XRc!g`-5_rk~`zhAh=~?kw(+O{;j<$H}|jA(NzJvTH*AO(k~S= z53BtNtF!Top8TRG=8*ed=J-kAr9o_`sk>hal1sN9old7<Sx5e@95#}y>aO+SHwO2o z&#q4=hd0Ir+nCQ9lUT+9o%3J}(9exq_wMiAy1G9&h`#k~01_OI<@&Od6QtB9S@dX7 zz(hQGn!)#qXf2ZJWl>zAc0+R6TyZrTYguragb1EnD63B1aU~{{NL6vRd(-3wYL8-` zt9<HW{--jB%dq%k82E!rFLf5E7`3jl!AQL1DJf;m@*MR3zkqY8f!#};2sBnBOlvf8 z<sRyv<Dk5af-X}tH{F=B%5LOZsj)9M0%0)<{IR@=4G1sI2QOKly5UWDRc3p6^PBSO zOt}}3UzKUriSVal!mBsb)7P(lMN`}GGOD4+ejfV1m#Qn8p@?|_S5#q*9y=D(P^1>k z*+$gpIU!~9>Abj0w#}T*5-2yH$BViqo6o5I9speRdk`978l<5aW>%g?DV+VaEIxkl zes*w#=vCLUu87s6aZ?Su(g2FLrUjFM)zOkQ5*~csAb~gzC*ve52Cs`(6Q$s;6y22^ zTdmX)4%)wg!WKQ0jo9hjynXcpD6(k;scmI(lm=Gd_}>2D=H9*g!&|pM!BnMMmt=jV zi=b>tH=*xFaTGd6YP)gb+WVNrhuPE7e2CV#?7=h^I$YDNH7F;OrLG&escBob>G^TI zKlm3v+W%;OaD9B6bu0aC6ARVY_eGo5%h=ws(lHf`M^~#tGuGRxOT$#Zg_ZWdx2NjV zIycN!`@+6Ej+sS)6J}wUhJNPnx9#;p4s^s`S?;zWXJ*-k;oC{<gvfmjsIIg<NG^B| zpz;`2^5ifZKQ3GxZqy~t`h*vwn!)PZHTg5L{M7YR0~t8U@+{jQ9FE4Kqs0*X;f-5u zD=K92uxe=2knQjzKMmd7O_IRKeG}p(5+E07gkkp9jr&7^`nC>Dt8gV@gQA1*9_sK> z@<H}2tlkf+_Zi2v(>xC>H&2*$9J6)P>;Y!sY&uLahYWMhS2k;K?f&h%_i(om6XSVw z!dOnuf9dL%&gbKI6<iz#@0GjW+vxJ3n$r5|TUPsQTs0fHt(FxgnPX>p66ImWZCz;Q zWWl&r@UxU)UKkbaoyCeZ2YkP~dulRvsoj+hPkjp(68LkutibkMy}7@4>!Uk}P1tLO z(KsFA$Ac$N{pKnaOCpw1bh27$hi*-*T&35OSgTItE~Q^&8im<R^d{;Y7Kj~x7X6UH z^@mOL7y9<??ka(ABkr#GMk~(O!go_qviurP^$MB~8XH<Zy00{V4SQp&Hd*b+(o2^I zGqk*s=<v`WR|0Rbc>>%*+O_=<VqdrK)OBlmN%f|!#KKPwvS@sK<QMQFl)`sSG<>da znx-FwVA=O?-~K>bx88kkg-H|Rs8%W7nNJnvEu?!_kuFDGrq|f9Oee72BoC4_$iXD? zK%?2|6XhLK0-gTzL||9Gdbw~Xlz!RBn&u-$KYV#GK0X|Zj}8uxgS(&H6i=d36<YZ| zh1CR^zUM?i?pVHW*k)?^=DyyK>tnR!`e@aAV)ekW?Z!Btur2RTCN2GzJCYfZ@40!L zd!`lI0X$4Jem20OF^e8#gQHP~iKdjLM7N7#RDOM9aAPLE1JU8&26lGs)^v<bK&$)j zi9MtMgqq@fic0;liQmrj!LhO+yz}**r{5@{y1x}>(&+>ID{4InXBmmdpf)oo<HNYz zB4tD<TU<QfX<m5m{Fg7E*PU);4p?1oxy+AEcC9wO#rNMB2mx0vlnEAtjzb(kemfq$ zryLHH<>m4q&GHDd#qgn=`1KoiVT|wW-MWD{h}Lw46;zp4y{#1tFC6>v1@)s~#`&De z7wHAltaSwtX1;G(xtZ8W=DUdl3m(HvjIrVXb3@df>49Jb`KxrYs5NLjxTLKGirvz$ zKN-y*B5vp<2)f=IKNDY|C)4PNKSlpGOtU%uX9yU{!)$PM@9O(lG1TW`nQ(PgD^E9e zRby8*mL<5J9po-tq~+UwAPj{*o+ZJgV0(f0n%fwpx3zI$*eD)yw|94u`o)XxBhSHe z<KRF${mlj+?0@YZ)}aU496oP2<j+AK&E|u5k3Hw&d44qT+v3|w2-D+hM@;1uT5Gc& z-}k<K8DExfJ%g3hy3F3T1I0Wl+75CnnK&@r-GaN6kH_ONn|FKqel+9r;2Qj<@P?}< z?2-b>jljWFc4T+AYJPdZoEq+)s|zpB->hx6^Dvq{v=5^r)4U64P7c-JVia@a82sWG zTy+e921FrFqB!+@2V0pXD&Nu3Kso`a9~py3=HRh0cx(+G+k^2Ow@dszk4*cnxO!Gd zNSfo7H#)))JUU|Kyli4%EXZf&qCMf$Pftc;F;W*!NA0ksjov_B0g;tpChpHzp|a^{ zGR541o@vgn`{HssW|Pxm%sP)HhAU+z{e-(l<9+dB`anEL^!(~=3x2GGcrL>3?nm=H zQ11-V(ey}Dpt}3|wHtSt5-I>OOo?MzQwDD1a$v_wul1Zy^|v=-uKM2JnAPg<q+-1K znql`$hm%}**$m3Ka^AAIa#y0GBU%seNE<@|h$Y|^cw_)`kSM2Ge99xCYs)|*o!sVK z%|mxI5TA;L<8e=;``FFf$KdF$9OHNa+`l9IO3`ZB9YRA+0hcv}gaQ$;$?dCqH;4D` zU%UO${W=HKib7X=(Uc8IqL3Ks_^5Pd-Lk9g5adY*>A|BX?Xo1}mBGri>btvw%0fSM zL1dngYCCaY?W*SccPop3TW>sG=`A+BF!mCR{-%c#Cxm8>plk0yt`HH3ml=&c6bXl; zgJ=5lk@%tLZx1GTsO1y=m$;A(W}b2-)8EXJ$x$ZWeKS~Kd5i|cE5MDe3ESX1P^qxd z^F2O)?8%F@(FhsPgB872oe#eyUhK7gd%I;h>b9vt1$*B(dhE%7E#Eup`+0Iy`Wva2 z_<MKvesXkEv@4<pEu4{7{RoOK3ooT<mJ?K@N3VZ%b#i!w4-brW2Vqe2E#82NlzM?0 zma5db4gKuyE`b4aA%@4ZN^@JpJFTFcl`eEc-N)5QO6*jY%m(9VJOS0{`>1^&t{rRN zO<a4F-`f3~_l8%$I+#beBtMZ*A^9;?Kk<`B8p^BpX@avqk44IqM#2TZ`<`OU`Q4B? zn~y39zL-g^CuDr(>sZ=jI$JDZ9HInvcgKZihGOiLb3ym(n_`*mJ6@VujSJMXS>j>! zmnRrz(-oZE1bT3&V*XBhy#@d1X;}3%tgax!+_2I(^kUy}3<uQ&@(<)b!*7Rsa1@C< z{UA#pAT}Rnhl4{2g&PvUCOX|ilpN5wXTx+lIU-6<|8<Q&N;j1n=ZZIu^ebSO@)PMN zOK<T}>wi`e3S9QZLS9`00fi%4U$_iqRZ$~^&@sW6IEyBe*u4#k*+nsR`a4ma9dzhv z^JoZnXzo(+MeX!@cDS*>eeH-Wm^BA(h3}p&nzP*g?M=_%W)|gVu>W->V!;V^!@=3i zL2#agny$YHXEpvAUGu@iO!@Mb0%Y69A|!)m?t^najE+th%M7$|4_^ltc>n#o`+L`h zH*Q_OErx;Q(eQza@4UgqLq>m)T`E*54W1wWU_7bhF)~!G)p|0eZVU`j5zf84Tbm5b zn)Z`rVkeL?Ht%}<H1&Pe)U;Pb*kaHg3VK>Ylu}9EmTH={EjG>Cfv-^0z)sD?O5!li zt<Z=g5i4wKuy^+>mD<wg>>McQQ%4lNHWqqE9;2)=yf8GA)JoIH2@)S=4G%sp6%GYD zBT}v)?Cl+WOh;*AIZVLJ{WQo7A46>SD`J!7mDtW=Ckb;e!}6cnNLMm8P>tDEh5iqk z_ET1M@q96*YG$k7yw^Rl=`M}HEPOZgoG?#}Bta~Tun5eK7lIKVMKoB*KPceRW7PFZ z<8c4(*M?Vb-roP}{_0laL=u#78DaGbN4a>1(XGgfd_Omw+&0ZP#_0q>ZahrTgGgY) z5M6Ti6idMEJNvhKhMGAtl&9Y{o#xA?Rezg7?L0EX2A`y9V&`#!4QCIb;`W`d4X@w0 zxj($Sck3&w=V#?J2Ql-R8Md^RUZX6*o!pA!Fp1-Ujl^d_=X=<{^>M=xUxAS|nFVF5 zpln57u@U--YsIdYg$b?#VpBnMIFhLB8@E2*yLqGX*01_<<Y`#7^NV)$7FuW`11~cZ z&q%!lpL-O?AVPGRLkZO=;!D4>f1j0KyZzztqg#6)@7=g5p7*Q3BrnPpvW&J~EVH#6 zX5lzi>Ic|}f+&gug1-yYJt193j(k7(aPP*g;oi;rxUw&N7OLf$j>hz5bD4r^H{M~8 zD7EuEOfA&)2Dgekb!YD@`znXV%1R2K3RlsNuxcmUpBsT2+E$!~aT*vnnG`~JO(^DW z!dQ!L0fPUulGf+bXX42*e>z|p_rHqXYVST5TP4T%XcdnDRAKdsY1ZCh8eVQEzGoVi zi^ogkiIIWO)xiVNm6Fv$B{>-;s0s%U#>Zj|AbrT<NxKt<5`GKpF$x+YaH~H?v;F14 z^}#1Z6I|M;?J@=g+Rb2f_5f1L^jW_drdeiM@QSWwMz*y-IGW5xPlvOkh$y1kXMtjz z161VCOf)yiLp007F^*V6#Rn=y_Hd|DCGeGQs1?sbD@YhYAg}UIsq3MM8ZJ_@EYhef zCeR#o-oD+>*Jp*?M}ayAnQNWLZ9RokAM$d~k)Od}%TVJNx+BwWsGmG<c;V*#3t)kR z3&)mm0iI@Ohx@s+BZPiur)XS#D0sJ>9TZ|n(dmV++{Z9k10vh2{n0$!8bkq>A#^*A zP-JFVXu1LDwDQUtYTqzYLMWb4-ANuQ%q5p}5TomS8hAr~4Rzz<F0O$)-bI@CoZVgh z_9CGVk#SRe4B9~f&lIBVpR;cTdWxam0QgRM#9r7t^|6*gub>d7(>!3y0%5eAu%Im4 zO03Lq&~&>==)qbXACV*^D{R{dM!q>D36nbf261z3Rtcq<(gMtOJb(Sg9=^TatR#vx z!+x+jW7Dind4&P@EYr0@Se`V=@IyqMbyI?J_rHmzYVZ|hl)`^_iWx{!rreWIbTR5( znWWDK*Cg#znL%ds01emek{$SnFi*`Gs36iSlGb7Hadd!FhJ=>tza`9Xc7S<wFinLq z;n$38N`pDUz=wxe`$=)be?*`2)0U48c`ej0`7U#!!R%o)h#o(c|1A08npR%?PSWB7 zx?}z1sC*PZDZWX+S$ueWP<$BWhpI<9dK@2)%Ew2Oqhvf^H0Mz{-h+HxHH%RD>9HOk zB?pJc2j5)0f+4(k7LVr9!GrRToOBxHI~MV<um<Aaz}LxuVa&n7w-|abj}M`mGK)d} zbT%D4okhg-s-Nil^oN=Ll?;-@qo>Kk2c{PfBE;(H{BSU2qw&wd$|wQkTo(A@X=bAt zb~xo!P-7HDP9BH84aIiF!&V-w*M+>#(H(4{GZCE;V(0n}b)GNGoKHwdPy|o5>M#4B ztyLnG<A^fna^(=+rW+Y69c<ZtAN4NUf^qbC^Z@iAo2mWG%)0A=tMs=)*~*`0M+e*j zHrh^*UXsM{6NrMF!siyx)^E)p&%M5=6On8U1Mgj|#TL|gueG4Dk$z8UVp=B!beyUt zv3I1+bcQ`$G}X>)_vX3BYbvT=#CQdtwsxqE%?o|Ix#?if3uAcuG-8~)5!dsMR9RHl zZlI)>>eU_hZJfgQ@CQ*ocz5kcB{D9E#K!HV`=<5yjK?BMUnQARt~ReW4IBt%Ysd*3 zZ>yq-gFl|+X)^}E^6aM2tM+zhr*>_3b`;OBvm^Y*&W_$q5tP?9E#PXSw)*Dm?5LY_ z;p&AC`0r!>TRTYkqFf=7z_)ov;6uG5lDi{81z5%L;1$<+SfUu!tLLX^lJhjqQfFVq z9W0vk;gmj<B2&FhwoJHctj1@IRu%)jNCZ<GRlFr%VIF%iQxyi%$um0w{*F<D=>-O@ z!K)xt0V$gle1MRZ2eFwZMx6N(s&rJ;e7~NfZqku%Si0ErXk#qd1V@51J`18#?O3-J zqIxl>0t3?yPlg6tK}JBT1e=p!uV5->^x>n&BE?|<jH1x<Gsm+{34|ygzT!Z)k+^EP z3P(SByuiUkUMN5pbZw(MwTJ`pVl$6D*529rq?o%&B6<O(lCl4U#CDO`H8DPzz=JR% zFx!qo*D?GI186O)*-6i^u4S^aZvr@O>KJhvC23{`wjH7R$iBJ$y2!PCKU?IvYL&VB zltIYj&)-Kc3@T)0*^5zx71NxR;&?_R1Ad5iU^<*4BC!)rh{4_nEf0HhhB0EFZ2R>l z&#~vHMOaOzIVEPDCb@^k%CiD5%=46s-)yq}EMF?U?L&Q<+*rOGA!^DO$4W2gr`%r4 zEYPeN9$*iK(JUcSguVB01wc`s2M``F&)ECcmahQdc-5Q(+lY)T4?;h12&aOt*N;9e zaH6l0zo2|}LfS#sHv-$oAHu_737GOMCD|1MRPjq!nNa4<Xr_LN!hL6_c)TYiDFn_q z^IHFyo}APP$g!B<N0PB&XQ!Sh#iAD_tyJT^!g5ME$Ik$7UM*#7uDr;5svuP|Bvi4h zOHS#ZdhzANTeQKJ7Ib7=On1IV&g^}*_OwdMyCj4vSzH+dJss$7hWh-40^UbT+E-+0 z@(2=yM-NV#9zI%e9@`cs!pWoc3;bgYCTkDn(*q@S`xyaP1RfufS$PZcq}p$AaoXYZ zq(tgDM?C?lDn@+K_jvHZ$0t+WfAH}c61$hQ8C!svEPuUR;M*rtLn#E%r{verzO$n? zs;1o(#BdT-)dwFdj&ekaG_9vHh*gU%@^wcsd~1$ZQ}OI%g2KhMD6ReeF33#X=Oj&I zaX>OdB!noCls3xer2Fn{a8{vN6X9CbfEyo5lT^yay5y8mP8@OISb=F;WGW(=U5=Zv zda|AxmfNEZm)$GvQ8=IBeJ#wXJ<~c9Cgjxbt81R@zMeL`aHI7^%DY?vkQo~>3QO0? zV#5zDQe3?_0NVT#ufvWD-K*`s5cB349MHz-K;u?H1BD6m0Q2H7!?X!+Y#DKwk~=2L z$z2wt*q@XNyK3@+Fhd_Hs}9R_w8o-xz+SrrXNXeOe!BT+O3uz|x7bj!Vg_WGGF{Ur z93+5nEwy<Cc2p}31LI{Nn^Jg{{R7RcJ;IXHC{6Kbol4cBo5VzGSP3C`7QtkA#TU<B z+!j~vsO}S~@F*85CK*#^JHDBxi5U`Jrk<>yl0J;}?Otiw>jVy|a`i)ngdyKJk!16o zozW4j<<Vo6u4GjgNiw{h9hE6sfXL=g_Fd8=no)pd0_&bFRbJ@W*AW}4<65AGr1@YF z$@jFgbFZp;wCPBJnZ}0YJ7Fl?lpe_?9UYnnHInXr>wdk!PovDq@hBnt4f(2+l2)%k zD`9nt1bkprDr&9ikZUBtC=G3G>kip<y;y=e83^REPjG9nQ<JWi~4`>iXcC{;YEF zA=r9nrwq21;VV<ohEqsVGXpJV<gtq~H^+P=Q|MvabbPU1w`7o#tb;x6v6%Hy5{>tK zarbM?9?idGaRG{a((6T5;@fHFT8YE$)sK3{ym-2El(cV_*}BP&6nkcphGUQ!2{z0k zXL^>Q&pKV7%B>f4ik_BRkG;L~&<4W&wzJqm5NHZ#8^G&}5e$>eaEbR!!Ds}{W<;fL z$=B;$ePLJm)5R1Txf!8;b`k^Tz&E(DCuR!IW}hihuo3dV0S0QI&Q-)ONNQ(?VDHhK z$VmAsB7G+Gy!a$ETe(t#$<Uo(mNyOZ0|%xng-}HLI9+5L>wJJS$%jddWp+TyOZoUH zdp3~VSlJUP)vGH{kV8ZWi00}bO+oo`px6x_Q`?Qis@aUmn>o2Q!z@Xm6cNsQ5`C|p zNrqVRrnmchw5LSte&KST)C;X3-y0j-w`C{Eue6qmZtdvkk-ge6$iHj2vFFNeZRO~A z>R{iutz)#9)HRN#WN;%-f5RL147FIV6k*zeq-ihuwIK8AIz@W;1j6`{v^}y+#nEr? z6!{7P=;po`1;i;Kyw7A_zX~tXq=mh1YjOAG-=fbnir8Ah@0G|ZHjWytiUHYNxA!uX zS3(L-s<@K({KDZF?ja0tOYlu2NqvH94fKS?v-KLF@;072%ITLz7H9RU#RRF1s97O5 zRw_R4c`nBUt#w$os9>Bq4jfRP+O~tE+=dRz+e)Mx9%U`Q+fA(~Gtdtu2@&3sME>Q+ zcfSI-d|N)~;=6s^|M{)i|3)-;ACL7X*As4iXQ#9i2)bRqo}k^t3sNsMBC3kHq<;g- z722($`uYT^?eAbtF>ET*tIUtxBHjry;Pw(#RXHM1qc&vqmhH%bn3y%H^2D*9xhDF~ zGc!ZH{JXqxS>J|<`4d|*wvy5c*K11-jLaa<bn3WfnuZC$r0&*1X>NXHIh(>R@ac7y z$`U{IBhQeGIAJVNIogrxG_l#q6()UDOKtt;%A`e%1}ZmlKasC8i9qN+D%EXcG)|p; zKKTy4bl3GyF>>C3LHiWy5NfnavGN<by61^ypv-dom@Kn#gnQOYb#?zVgVkE4*k=H$ z`eQEfVR~6gmIe41>J~kb6?epxurtGRZMY88@C<w=UbfkCb0Q#&<=LrfOFyd@rLL{U z`_!py%b9;>)wb0FHz1XzZgEqa&Zpjq(DJG2j#WNSrACgW;**tw;mej*d~@MZR`Xq( zU{r6GUtBf8x4M5tzGD-Nod%?1w>(K=0AF5s)LyuIouIi5-N<}m2MB$@SuIc8P#j!K zA1<a@mPBmNRj##?HCMUOWM?OnT8=1g<kyCCkTe7qnHWI%)B=tPz>u|wenz|jZR(i1 z+L^5~C&;s%o!Z98VxbjkK$2VwnJGL8Ju^TPlDiqf-$9&^1HBSpY-(7V*2h^QdX@X~ zj<}AIjTFt2l_yzX*=cN&W5i9_7yamxl)Iz{ui;@qM>{+9j#gJr@sOPz64GY5csue- z#&gvd3>PGn{B+GEqy|791-MSAC)H@$uf5QO>te9@I;x_uTMy;=u7Qs&9<2sRW7usq zl-icYqSg&l+y2FNCupB2n@vQ4l|{CJ@G6^idTx&<!3sH*Cfv{>gNI#**H#Y=eOR^2 zSEcp7`jE<!_vYznyt;#}OLI{3TlhNIHf6yRpKS61rut+q+`Mz)!d?E`?ADQc)pN|y zvPnP^lP*ekrFZ|ru^Y?vb*1?6My{abE2hF?l&5mAzJviWu|Q8u-;^2kHn=e2TT;RL zYUkqJv#GC77+5)3cTCSV%rG<x&1;W_;<EP1QH53YM=5!rwy?bEm48mC{Bz`a%|VB3 z6Djdy#Qvh|4RWr?CJs8%H+67j{cC+|RE8Fv&azv*yO7@`hAb!x@|j-YwOQ@2DHVPf znTxpOm}A_Oh-Gq7kai`8y=}DU-MmKR>n5{v)tXJaaptB&iuyS<kP@jeF;$+{W*#^` z9>gKGEKerYY|=X`x!XF5gDF*+@=1|j+%4*8uYy_Y<+8b4If30qj`}Bd3%sGT73#jJ zBD1q|2gEsgT9u^Suyf1yY?AG#M&uf{Az@BTyzueX7X%u!v%?7%wX!$tH=tCHM~@U+ z0VJhZh+u>goVO-i)G@6QE)xS@>O&g&7Z4JmIzL5B8hR-c_dKb31P+2QaxjInTfLg6 zoN?_Olt(``Mt62<HAXkwuPFAt-1URpiVTu0>T@^=(~?_p5PK9>K}j8_kT99Lx)rS@ zP}Q9cv`c~lrWyxU(St^D2pE{EHtB|ob3MW^LBqc3Cm>-kqU_x1Q9dGQ$&MA}PDBcx zK#V&pz_t`nr9r!P-RfMDst-^DH;=SFabysy;M!EO(r4p23$8ULQ$Bv6LPu2X?%UH( zMrpR`=0u=9ZVTBFUDph`DcY{O0JJN|`JhmowmiCcUVph<`gwtkH%J`e!e6>>L?klY zmRu;bX>DVz8|p+{DTQ}xyB$ivrDwV>K}AxVMjxg=zirre%TU=S!yxxk3tUmV35%`O zJdkFg75Kv`?d(iQ^)-jy-=4uoZg`9)3L5+!A`2f`+jlgKyLAenu{1w7>@iC`DyQW} znul3Hz9F>{HnW6!&K>HeOiim^b=jiSJ(M&R#>o%E)OS*BCHk(_F1W%{@-|#@t!8uA zq((FH;y<gMk3&t0#1C_Vf?P}!`m%YNrBYkC<p5cH{Gir-Krtc$&ZE$=d@D@#{Cidn z*;d3Fk8{hy=1po*_^+Uj1E64*W^*eki6WsgCS~!SL`S+t7klTsxu3wcQESd2b{xFF zc)UO<-QD?^!4HSAM8~;)9-7=K^62FjRx6-SKa+mS<+vEH9*T!`9z<4Znnvg#;5dq9 zlqZWZ!BpYi^uh5VjNQx=-smw-oDVG*RzGx8pGdGEmjD_4sPUo@TSo_;RqOA^e?jd$ z43-eOxxrmDkfsY-tGBZdx;7B;YM6E*5Scb%7?~YLWE!OG4;l%fRfQDkoRsAc(-h$$ z_szh_bK7N4*zq%F`I$TjG;^}lcD>LmS^jb<CEL@_#gnceNsY|*(hz5R50I(2_~W1m zzN&NU^nQ6jju#Qj7YEKCe(|Nf1oRiK+_}Ibb<?#>Kgsi1rdVB~HVm9aoG3FrFM-Ew zaMksNY|1?w7MbOIE`tq93R0G{#61_C_HxOnOu7)$65a^yz(Y~sr=bVKY-(kOTr}=@ zRbAAiOq!r}edBEiYk=-TivwsHNST<!eMMN5p!V?l<wMzC)2QLNRWd>Soz<Bt&Blmg zI~2{jA-_Zf(sxfiqO8sXm<Hv+a{c(=K<=IV=c;$O;7J%@=!)Q)l7O6Z`u6#~^s0Lz zN}18BVzDgSu@Vl7dY@Ka@Mks7cEjbi-f|Q<lu-%EOX=nWeHOX_4Vv*}qAQH859&<3 z#6(9G5L%RSxp63rrRKJrOu>T}*hqa1BQ{Z+t>Aq1U|MGi*d&~C?4~))stv&ve5BNM zicjc@-u3pNrW=kCWI<qfY(^MR{xC1d^Xaj|PU>Z-1E|=VvI?W%dfr(q;si2<6{E?Z z7LMhDRNV|9lzrhEY2iUnUXlJj;US?m++?h!hpWV$Y`9@~ZQ)`Qhc22F2k$L~&ixu+ zRU0!$k0`}T?_|@%(QHNtt<LPY9=g()oQ_dsvVEap+geZL)wrgmQ7E!?MTc8$xQqbF zA+w3;w|$a|2yPL;t;rBe1KiD`ltDJ^Jw}4a%oysCVHGc!zED$8bub%VV5+`RB8;H( zz1dxzW3}V$5>YJziosGb>4}kL5)1Q!MxLl7WSxSB9bvkiJNyvkkK$bf=fJs;ayWK; zq$<AON~KaU)Zp>ejq2Ab8-{0b;wA+LZ4>a)U{wpxS34%UAo%3#ux?7Q`(!kKc<cB; z-KGz~(W|4jB9;WD9IAHLvGG47Gp|1U8aY`ye1TzQ0p3i>nUe;<b%VsUZI{cUfw$x_ zR|N$}3kpt56i{e|Bno!Xv#x@CJ0I_Kt$9UIfC!Vd!uBIKNnFDMV++XFR=wo_O9bDH z(iqc>NnJeT5nrER&#Fs7!J{NHG~RKuD6<ozkS|LXZEMZcsG*s%u%iS?PUtK2!zl2G zniTNlDsb|zB2+@8+5MU3LxxWPtKs<gKyF23`T>QBkz^vb@b+42rM7YTZWoYR^u2mU z{kH-Ay)RloJG4XUW@{SlX&Sx20PDtRg?-OP_9ov>0;na3vQ+fU<_{;trUDI0A?PGz z-u8=cssAWE(n3(-nIM~hAj;wK9Q811E**iVIC8-sNV}k#^5J%Unr1dmphRWAZti4W zo`fLLEGNr`FyPhm!Syl!|B#f5*T=WVNmdPIv$a8vU$vxc@btqlff*T2XvTCSRIE@h z$}$H&Dli0+>glC?{BGeWe-w>J$?onQ`E`SO_wV6fFF;8((&Z<L>?)uFZ>ZYqE^K}F z)Ma+rQ-{RGk_<Eux`_@@%4QnMZdPF8IzwE4F_=bAR84K!;>bq~_aa0yk%Zw0%ZIXV z8M~{Oa(Lf1v2s~HL>vB3Wa;8XYcz2VqHjGj?VJ3pYy!?`Jesc!D{&GKN@k`6)*{<E za04r0CG1I2k9K!=nyHQ1-MyQMEESFCYKt!EjZLzH19_CIs-3K9cUP2Xe2`xsM$h6* z)1%tA_vUcX)4S1=%ls4XQ?BxClq{gxG!|c)p%gVAVhEAS+6U3mk-GN}sml&|2l?h% zZsj3@Z%eyNs{XHHYMIlsF~G4mP4t9b;2IUMX~jLFWm$|87XrNLO){KNnZOc?rV<0b zic_|1rNn6-0(Vp8FhVGa;uw9MojZZhkdC&m-eDYOhmK5EE^CgLLlSveY=shZu2=C& zPPrC_<y$yv1fcQQN36?15M>zFs|H0Nor43@7A#SrtNKFRFfgzX5?Gx@MpR=&+R(Fi zJT4G)mKzvtv&3-86@ZJk!jMaeoT|#&3XkpVDD?G}<7nE#dTJ6sonU{u#!sP|PRa)$ zgaSA=ip3Ds6pjI+-YJQ%SZd+ZXol%?Se8J=%h15O=3ocQeW)#t5cL+TNT@)wi|Hw} zQ3z0lU@kZe$zr<jDd}QU7;AM6VH|}NwgGK=ux;W8FLPR*%30(5{+%-t3&QDAH#S1P zkgRykoqNUb`RdW<VQypzqKe@-@BoMftqV|Emfc;nET#L{OC(V>8YO5^CJfL+mprZ* zB6sR~%0*lOOmPCQ=mH$sMvp`?ha+@R`uA{ljI2gBtW=x;GLt*tpxQ<~shY{-T6Qzd zQ`fsO_f)%&W}|OqVV=#CheeN+i^2N~Pz_<Ku#%zJDW6sdqCO!Mc$%fn6UPoQcBO`c zx<oi-^+aCMp4R$jz$Op#sl<Q7QJSeq<~KVq9NV_x7|MsQ00331UCYelp5noSrlD&_ zk?Z4XvtZ_{YR0hcl}T85x5IdHz~1lf-cuh*_D~^_b;3h}F3%^Q3`|OvfB@UZGn?bp zhQ2<H4l_NR@a)gUdb@7sp)LtBEX26$aON$nw{WR-TCm`s<KsNXw+|j0ZH;KR%3MA* z=DL&R9*s+myWF@<*ldcwaaU5J&w~h223_dZZ1!2Nrv?c%?mDqO@yJY3iv_kP6JO6= zzu1}fG1Z>w#J(E^ao}ZAjN*h$^$T23jhD_{tYEq4<vA8H{7N?ArC;n!Yn*3bz|o<s zu+UoDeuye-BNqC_&36sw9Ap-m??G)&8l%M1Z0V^ojc$w?UKkp5(y1kiEyV*USzj|O zF9ch)bJ^t1g^U<ZfUhXb3b5A7YOOF<FYf%>=j~V_uJI8rDPiJc+v}M31{~IzucU@w zYn)+(ZJJaxC~A=-Vo@M&$r-+wd3Ul>q};Z#*C#d+!O9_YEh}~A6W*MoA(DdRv-nAX zWlfAQZ5)lU2}h%qQtKEf0u?;Z!YRYDjDVPhN)K6AU?N)<9(<-TJVK>6AEL}&tBp)D zN_Iq1V8#*&QCR0Uo0b7_Oz;l}b7L2DF^;tJk)Wp{tsxWI-Mv1U9!7JV(J!8_ro6j5 zr_?e5DK+0iZDOb~nx0NAY`RM+l@|uQ%*gT6z!3?b4V+O?`C^~IfTvkFvEGSxdj1gh zt#+$g)dzU8#$j#~34rd`$X5`XR=>6-J8llMZk*J|43OFQyG9OXJT|e3Kr4oPT}L+f zfJ&cvgaZKCiXf!TjtZF(N2lFgVp+sTX<e78LERA-@0ZlZup)NrW|svCTIj0lo+*k+ zUN=Hyz==DCNg{C15Bvg)Rcai4ZkU~RcXijKl@@<SRM6{sPN?=mMt96Lfnj7)Ke%P? z&7)d~e!f@=*eU9iMNil)tuniMVNVoNrjr~`r|9B`I2Gaok6?&p6j$Zk_X4ygINop* z8co>jGSsv<23@*QEkdKnHA5EVA%|K7VMtuwiIO0(g28D6?5t1MPA;1C4(V&J05zAL zono=#!?Uv3t<+oinp=jM!gl)NdJbBYJ@1`KrIlaR;@|}7*jY*qXuKILuZu(%v&RUc zW-p_iFE+Wk*J`ut?g|z5!PBP1ovZ8B7Qv=vcr8{nVhSB#*|lH_178556#CXm=Y(ot zYC|>QvyT99?bTL9g)yF(GN3?w<yB1N#zO(G4$+h*fp}r$Nv*wB1TG#<rzC(!2B;K- zXE?4CxE%uc0-u~n54w=jZ;~tc6Djpjq}<&^Oy@!aNMadVV3>^r^*F>|NpM+)XOz#e zZ7rz3D(hY>TzKcwTt=EXKQ&V7czAernusCm1^QQWMSX%l5e$x#g+3l=W?)*Z@?}`l zP7Q=>M_E%47%rX}dE#aKrp_k!UKV+##<nwBQB9FxBtF5#NOjnTxQP(_jT8y59*C|{ zICxejS=eJT|KmO6G<=>4f-chbb6Ba!uWaJKjgJCuB(|v36&YXQ_FfU}+%Dk9ILA>! zK1!1WGk?CqR~Nj&ielo`gNOF@rIAOlX+{MIGvFQ<yw-wqF4nh!0^^lg@e;BUpc6*d zvm=+34|(Rh3F1frji1)_bty#Rj8Gxp&n(-;mr<0qYZW4|%)tqBd#Wl=AF+mj8WWQq zieVv83k)=WD0~Oe-ck{&1~RS8G37gKGfJf716d*>_;BfH<(4dAf#wiujAeH*?`Sfb zO~%gkgXn>iYEK+LAf7C+#O=T^Q3o>^4`g%vnp3Vu&Prw5@P#OoRIExMJx&o~i<H6^ zDIO?z&lW=eC8?cUN&)M&CRPSF5Csx200S$ca-lV;yO=5eG8I*-8DrTHPj8fqGe~rx z9O5if9O6F6o~hHRJWcEeDniGS8eEiY!U7ljf#{m}zTwEWev~|#%}t9DmOIZ=;tT_a za$GKPXg<c-p3X1gwD{inFJCV7QsNx5yW2K+s5}=RiO*Ybe3VA>Y^c7$spWV)H_bbH zw{Bb=UcLR%t^59P$cQ7+2N<x9b`C=lq73j|%-n?^<jO#U<MAxYv-8dQEUA^cUcNlI zDLc<*Y`2M~U%ppuVlbaRQ$D=R-lSSuk`ps$Ij-oX_6Oy|u3;`#TB?g0L<IU)Af#nj zN8E-PGD(xzwI~lrQWh&HB2T4*HT&;Bj6K7}U(Af~`HfZHh+^o)n~P736kx<RTtdrz za+$c1_UNunwb3}FIAoZZcwRX06E0@J@>bPd3JB#doEWH`qg?V(%!of#NI-)@$j`#d zK^mZ;SlrG=KZbU4xPrXx&WgTB<3ctOlCI!>?7FT9B=V%(;JOC5?g(odq8F+Bv?7CQ z8Hwi*#6(Q7^s;zdt!Wc6mvVO|!KwIqIYe{C9b#^)a<mJZEH*<poj&0VFAY59@q|IU z<hbHK)g_#rbOJRY$%-u;5y^AoQ2P$Wav>x=N6$53#mjB{1<`<*j*1mt2rJw7UjyFt zm{`tuG#^Fc%OQx$#;J&?$uuNtE*FoMwu|emB3;uFoY3eCsSB58KZRezXIlb*n@u{A zM-%t0phyKDMS`tDz(F-D!HDxoBmK!%l#>fVoVAq&zC+>ipzsm9^saK;6dhuLn8}Tm zO~>cIboEPuql>5SL0^BIK%?3GeEHS77aGB+o4#~;@X>hm&Esr~X%$+~O-Ja^l?oVa zq?c~$xdoFWG&&$ZLdHo$C307@$;L}LZH2k%;toiF5q@Vbb`oN>mK5e2Z&@LF6u)Yk z{4-Lk<1v@mI4(g+@Q%((Q}6T7w@3L-05_%#+lVD;Q0&9Ov@*^@MYxQW@_pku^{D9U zp}}|`@9Z3pN5mfIWFV5DvTKwS-s+~4QH6Bdc7}}-(@mrmCOu0>n;zi-3k0LmHEgV{ z&83%mkTQE-jxbVAtVzpOZ5n<~9wefEERkswqfo6Z<dNmRk48th-0k7`e}_-1_af&E zE!h*v^sz3asYiTp0t^jVit#GNiA5~9C4bYdbTA>hgqR}RV5>t9yu3B5LiyK^gKubo zp-b?kyU;P6Jg`jLqx51;@KrC%l+H|kvWTQZUWfwfiIL{1IP20OTRaZpXi5n|D$8Bb zAMVYO0oENeOkW-lC~3#!F~MJTd7p}7UiN5EPVwspUpG3Cl~_{14}we%sP@r|d`L(= zRieCg{o=zJlDwCcl#ZDa`mnqz&ALpp+3^8p{vzAYyYF2*ua+yu7s8GvY^9FmUN;=6 z!idhv3AgtWhY^>DTLre|ajqW2D<9SjIqgu5GCWMl7(@grSra9Qq2<EYrhhj(TB~?S zLxX%|VP+F^j-b(Q*sk@dw`9%r!_&ef*fq_uP9$cwVvk?lk<E4*3njW_hpZU^(sSGn zFty1R`?_Ef^xdwzN)zc$m68O9X><yns3$9R)?%q$C?O<y2u4DmWF!_A^|~&s<A@cK zXhfom2E49hsU+R4Xa@$^%rOo8?<t9iCrHH~+ih_%Qto~}ojijL!kfYLa0rNU5KJT? zqs23ssc`IFf?KT*TbSuEHF0mJ6lb=UaFKBmf|W}Sp*Z2@FT?RFc&Od12jbN|3H#AD z+BAyL<QYhYA|jIGvO3`YUS$KwD745tR-^G<+1ljrs&HDm-`VMVsm#(q9>K$i0C#*g zNM1OZjh+r?N6{1VH{6jw?#X8%+<PkQwI$6$59LfF66@NIAueD<#MU$e?Kp-!773ov zIB|N2T#|6MiDQbh0enz3;bgz$<FbipPUaobuUQ$ji#-w@p~h>oK#wGXqKSI@L~ar? z2&Y2nau4oViXnH2+{+!;MCkxpNZ>?9*i#mmAyih`8(ZF}iO8hq%3LGhf1VSOcw!+U zFTJ<MUS?TP!PrbNo5A~wlS9elw7qESTtX2^Jn`ryj}}=;i2`QEXet*2HxmDe#45>J zAZ|~H#Qm@>D`pQU1ptJJ;Sy%d6o10S1lvK0#3&K9<i%?hb!V``pK3C!#pwE^)S-vX zOea-rUSZ3_2dEKcti$w9q?%4pe**L_X)%Zc2nz|Kp#(U2*m8A-?OPOhE{Skl;UIj` zuPooT6%5s3%G3;5eM3(^Wwrf+`IktC=`^=|5nO55#KQW1MA$vq6p9p~K`o=f0(0-| z)SQ_lHgjiZ`v^;e^lPNW_R=7BNrM7^$4v=!vI~WukToU;2bo5f3^^w(O3F<U=~!3B zd~o6Fg^va6ZbfP%$*_q<(?IVm4qy7rdOQFxs#83Xb0CEsQ;WcFCnG1OO6$?Y#_x7_ zU2wCl!`7@WcFk2A5<%o@hNp8%(kH2=Eu&p}u0i|;vr}3EcXm`hlADvsqvNCZ$pyUC z3Ah%~dANk7l1B|uY#k!90}>6Al0U(~2H(8Gps(CACP#(tYI5pEoT}Xr*nw0TTzo%q z@dT;E5SOKr*!iRkR1(8QhN31pT$S4KAF#YMPRXlLBvosIOG&&}5*&06xNby@Mwnhm zMjqvO_DO=u=7{Ci)(2=^Oy#`=LrA!TVTU5}3qPv7w~Cq9t~C;`Tx+SQPPzIk_xb!G zzCnE#qE%(x{X*ecw;^IFXCN%#$q);<L`lVIWWJ9Rf$NoosC$A%p28&~Tz7jI<*myL z-F`C8(mq_WeVxflmD_fjV{*jEnNF#@$sMH1-=b=d0!A&1k-l+(;avp@s_0v27Aurv z&`gC&?sT;{ldBhc2!xEis7lxzTgZf~$^aoW`8cB??z`lf!WBY%Ahs+Jq<6LZq)u?M zkigEZsj9e|MMk<xMp?TXXSkipN8QawQ&PcK<s8{v2mag7e8WV<^py2|sZANgTmyj$ z8#LkPZ1&kSH{&%nL<!A$2gRZmoC-Eum6a(ZQf4xg#_SOuM&!*!M1u(uOJh--ap6MT zO7~9&R^%j7LU0ePY{ObLmn(nC3R!RQNx;I98lNmPw$Lq*tCd<IX%-f0jSUg<^K*J( z7Lw?kx)LN!aXrbJS4w2<+`Q)-cvXYOGuz6&xXYEV4Qv$=D`$KLL`<6zYP=qv0+~S- z5mGo4nJ4yf#p|u3vu8EMGb<4MO3|+^DBq@~vh45_tLX`{FRS4p8}(fHCaEmTV+YgG zgNO6sqsM~95hE}Hx|puX|0iW?%7-rzeV4Y{wkz1A98K!q&v{hj)pAvB;zy4c^;U+3 z@s=GiUE+?Bk0aE~l0USlWZc%e4+Ct?#R}G1&l;fbYi0vnd-^8>ytUnyRiV|*1qwAY zy#+MN(J85Zi+4&0Ry>KKK8qt<8$?BbE#@Ec85%)^b1Xv8Mmt{9A(9E2yp7^QMfOrV zlFO2*{7~!f%4ZmJZc|WQ;meD?s)}td&U*`Q!B3^&bcUrTUp`gc8a6h&lYfE*73PEm zH<z#=1T4iV1eYYkv=Gmz($(aLt?Zk^u~P~nA}}B%zc;2xbhFtv*CR1uJl;pgRR%z| zOD}~J^cMOKeQ(dA=U#A9stC(otg4|DGMy215XiNgrNilDqU0Rb9(dG2Bo)5c#t`Qk zO<o*7pr-B^GIdM{om!NVOKe#Sb}Y(~kq<7G@GLRXFRi6V#%S_jr!Kvp4g06Ij5|@= zvlqkUEHq<sX)Uv0HO2QIbMi1!6=%7VWZVeyIF~w4c#37nv8^pn7s!g;Sbz6RUEj;4 zDG0W>&qfEIS)y4jaBCs7aFAMiZ9k)&=!rLOgN^=_U6LiCcwrn`U-d2~+>C4r4mo^? zT6gggqUznBfK=&Tyj~%p1)Q}z_8EYvPF=;8yopVv0;nHu%rP2Hsu>wLh>N!X->(O~ zCRsW~Q_UGNA)E7Uq@qf)G2w>~seqT@!kC9Ksm)0;FF}>^=+nAGmBV~#QO;8GRgr2E z6E&3~Tr}OvqP(p(;4{k@EFtv`s8)G3KKQs_FRB@1*F2e`@U*SBs1o%=O4+3{=i)Yq z^J`8DQu2F}gzM#-b2rBk>&{@Io3^#la&yz~D|2icOH&_cZ?1**;s90fFiRgu2w`Gc zxW!0_J;qa_(F^r^)#N22yiKlAV7!d;D4AcS6*_@FUA)8#LgQonKqW*CQWKx#NFojN zvzNW`6~$O}sKUA5Oq^75mr$5q%<N6~rqk6oFZk)YR~`idFboh2PFh`x9+z%GXEt<e zehS=@^3YBQx5wj=TF1*9u{|}dOeC7!tH)$m<U+J4@Qk`b3Jfz?<+86!K1tpPwOOa? zl$TH!1ON@uz)`}ZjN{Q-5uJGB@MtEHR^qp+yx%uU?Lid~63CI+(S!q`NY(Pz6)gQy zYLC7FYjDzfSX7eALdzj=nE2*gGA}iuRxz{f1Kb-uKnZex@+cdx8wC?)?vX_?k@Uo& zvl4mP4H9i3UF${@cTXY{45GS71h(p1vBhX)&RZL5g&)7~ThwErM0QNtk=89-S%>s2 zis2rNLR>{mRd0hz(gZL`%7y0HY_X1PI$gUCk|4xzG<KA^77-Gt?3=?WP*_=q^jyV_ z_lQ0^V6IhJ{~oS}W6C!kJcs*my)1Gsy6c`Ip3aak6@LF56RB{OO$@Q=mpzJhT-CfK zvBqpjNK#eZnD7zmcvIk+GQa%86R6(c`DSwJ83sHHhi_sf5tBk&WkX#9!bDnUu1Cn1 zPqq)K!PJDQ0->pJ>vF43zT~wRDx;(*wVf<8Bl<uxLo{boAiK(^dcvpu@#D(`9g!Ac zrJgrc<chEDC4UI1=&c?qUv+)%rY`DD-Id89EM^qtL^M%?FY@ES3Ao&~=O^C+K`DVQ zLRqlFo930+#MdsAK&#=y5m|!J1^^0_#H55F^<(f-C!VN$`W*A88sKO?8)Q$TggZiq zgMImUk58r7UxhXunX{+gFpb44roZw|q2Q4^+9~<QF@P}lsHxyNO(-ma0WaLWUX^yg zu^PD0-1Ef(q#E<mqJ^t277^f@8zr&n65UOCptW&&M1x4#4?-^UQ1W;!gZ<Y}iZH*i z$mP+ER{I>nLAhmaj}vxKsUQkWQp;SSnZ-3ZsGEsAfNEPpT+N&uDkRDABtLkw$%#R` zl+#Z*(Pm-~K_EF<#yv8G#U8;$k;og(WZ5S@)$WO&Q7#aQfe~<<5fX2Z55z3c@)>M& z53d#GvFAIfOSN5tK*TP8+?CuQrwg{?gP=K~0!k2ORB0y4xz)s(8l$qN-S*rFp)|hZ z5x7Pi6uOTkZe;y%r_OR@9+2Tt#UY15%EK~K%=(#Br~O=Xnqs*)rIOvmBRn;d2;@4Q zUO$T$M2s<7kg1#SV%*QAz+s&jub-sas_m(1lGrijD|7sI9h@52o0_?#Nlp9bpcuEa zB$-*7MtIvJ?Rps*;@6T)%eS12vJ>Pv%qbXA0No;|&DVR^16}NAi%H<=ljSz%xDZgK zrbm+z?d@H4elp_b*yN?5v`%hNaV3@#U`xcUci?Wqu+eOq<Vi>^buw^7@i4VWvQH75 zn-uJXvpFL&h1V65IEBIyXQ=91lBp9;vcgWQnnYpmDA4VZ_LG1yu|l;%$1*MIpGavv zE?O0Ql7c03skm*Ko$AGBuAqd@bd^i)$umG5J2!%l&&WUpM01h)FJ2@L^)8AP(k;fB z;DP4WwyIQ$EmH{X<D$yUx*HB#ZiIp9%A`pBvW3R03VLr84qB_d387CIEvTsI5v5bs z&RSqB#i(@jEt__-D=gu+MBgP&o&;pilsnP9!pEl9jW*8cqQb;c>6h9cxlghxqvRNR zr_ysB11BNvf=dY)7mZG^a+C#lEMG?%uIJMA3`lzDz)z_^73MA(@w=$Q0v=6IgU3c^ z*u?mtVaOXvsfjI*F@41nP|$30>7*M+r5Mj3u^QEE$&$Q!2NXyyg|HL3zCR|%=DPc3 zK%V2=Cjp*o+T?m#zR0TYGUxSum0o*Ymu?=I)N-Y282qojTAQbwZjoPv@?NT2u2@bQ zFg?Z%KCc@mLU5<J5m{?VHeiU8NfQUDakBAaN?JwJMPjKQfbm=@J`+gg8wY-6GptrF zrwq4WO3SBKp#e(&tXo}dOk7e%D-FWjA;DP9>Y{4XsFzzL0kCJK2<^i26r;_lGA_R) z>kMiSQV#QnC{2M@mvmtyzKNU!vju7#!8pa!np3LEA4nd!TF#-ss7I!9d3JU-n9gXN zW+ZC7A-`lgsBv#71E<VOJuK#Bb5lV(9yr*S?0*tv%RBP4b6!=9EqcajG=4xd`(62U z9bLHE!XhP)!Z15Ko6cFlX|+x}Y?dniM&@T5y+#?uslY&~<y-cw2j+-i!V`$1(V>H- zML7z$Wua%zx-?toIBTy<N@00K8>#F}(t{Pd>est^Udx4357#!RKk8C)ET$M->qTtc znj%kb*T{{$xLu7Z-C1{oLO0gcpo6?@OwF5UUhWpT*~o%T9#1^K^8gTOHt7cBf(919 zwpGG4c?Kq8kR{Qw67ud6=RnR~x#X(vvJhP7mUK?!jCc(St{bXWuHj;F4<Md$`%bV? zJy(rn&Yn$VJ*5~ZY}si<S!O^w_vmC?iJy@=%=NkKr0YeFT)r*E&Q}+{xFaJe$yj`@ zzG_^M>f7o@)V?XMK=sY3!+cCaXDnGLywEX`nsWu_7ejZ#)<%3+6M_M9YM+u1N6Os! z@OqZ;l}#YuVB|A`YAc8-QxYSFdJZMe3qOQQ8%(GNj41@;nCx@t1{uO_7XU4T@nX;u z!Y$FV*xFD~QIEkC_O{7x6{lL$v}zWnf?9QtRGKFYUL=~ihf7B`-{W%wjJumvaNXCW zj_X?oJ9Wq>5jOR4)6AE&t5m^Tf&A|2c8hc;y9#mvZR(3)(ISh7Bu8Dk3MZM$8Ql#8 zY#%1i@llYQc&TZ4(ip$};5zX}&t*YN;W!>;YDtftQZ};#YL_od&pw^-_T(NMQji+d zv3F5uEYCv?Sd-x@|B&KCB`g)J_}+9HtrhNY7l^>c7K%!|lH3(cvH7579%wC;b&50i z?_f)%?hv)dr~*<GXI8O8!w%E0Z6Z%HrbPTl$@du&wz<4{tDWzSpVdYARmlsli%j;0 zZ2w8(`S@#9{%-QF@P02a9i~H`3QCtClOgL@N&K}EO(*NTo8?zYC91E7q+33%qKRu1 zeN=eHONC<BsKd<MT#*_|5USww<k>P$Yenk>A)idMu4S5;6}fpN^@N&)tW|fZ*14ny zSvL?Vi2^DF*)iU%WG!2vnDz7hNR@h0N4)v?>n7l!0C#=r6iC4#*I7Y2^$DEv(BwEW zEHuhFy0;(^x19bfZj+1Eb>YoPk`$mgTGu{s{oE%nE*WneTxZZt(tnGXe=nQg%*MCJ z*N`T<G$pNKzG=mFLhWOGitr)D6K2f<Qj~NQO7^MV<L6dc7;~XFE^w4$>+6$RcZQ~9 z8Ww|OU<JMr7i4nLZ!5GEgDqu@RzrC!<>qj(N*_mL1G}m}Y_&}w`#6X~1Q{2_g0Bq+ zjZC(F(Z64GUrS<6B7Br>VM;kaaJ%dohq#;oz32VR7FXNEGN`FV<$<+8L(y&WY+G=# zCI%sC-@N&&bYum+6^lV7rZ=mf%1~aE8s!kK*h{iV3JFzIW_{1H8E!2l^JsFC#Jyxw z!}Mj5qZ^NqGR3u~hsv|k`naY`^vPsRUO)-qvvWKt5vn{BNBl^tkrdAwCCa)A2>OzL zU~;I+NICde;RtIw=sEKQ;$1vj&@%QyNZN<dvp8G%_TD@#>u$@A)XROyj+9h`B-_Wi zF6b@F#ZQ!S@z^phL^^r9+>@Q19upX4bP(30<_SsiNhPO&V`VxUO|pj}#lIjFB<Gl- zb{9X0CJZXLXcG8pVcSn;9d@xv8WCENI2{<7W4EjSo3nYY!s+S+b(U&%*|t!|uF+@X z!sVF0?URHzCYzHu9<}JRCxGP~+4J`7#c8y~8JQYGga)KU<0O!(HjVc3%wDKYJE6Lw zpWxbolaP&Tavk<tUCr0QRp7vOSTV7mrdT&tIFFjLd3oWeo9j;K>OOSLp(udX*QBlv zXzk_H)d4We31tx|AcsoRlj>NV%HQRspSC(6Mbq!%BO``virx09e>b1X8L0zOh&aA- zm_TqSpyJY65bWNp9_&k5EeS0nQxfX=AX&k81qaZo4%h~Kn)k!UcqLx%w#Ix_IH<U{ z^GGpV%DG+0<`|<D^fyc6i1LG|Hp3hnr(g~Jtf-QpW|IsbPe!R4tif}c&TJkfkA{=S z*)%_xJh2%Py`31A9+IZ!K<BfCp%g&Hhl46#)m{`01XC~76Da*zntku==pf1M98P=_ zModbDaqb2}uVVeq#?ooy_n6_rkYJ|@f=KyRG%THUZw_`1KlmiO_v|p9Xyf4-8$6LS zOvgYy>;d)!cdU?y?&-Zy8WE5v%krYs!@mKgTEVzzmZW=%&5N+=qeaYv?Hf{mFEVjI zT8W!0E@Wj5QMkTmxOL-UXoVs7@IN7;crIn8o9ve+Ox**lHHK1oC86>*5qcp1+*}d* z*DXMC{c6?QdfXc@a}*<pNrxFGwg(`!5uWa)btBZ1DWgpaMnL>28-k;Oo5@Zz?J{e& zqI*7PM1lwp#Ij<eg`mWID2$rG#ySY^o@Ngna$_s-!0(tLbClC7n%O=&)N_J8y6LmQ ztq>KoBS^TGXA$wCIE)gvo-}SkUEwoEx>U=icvBQQRzN{dDM7d3$xk}(7mAHt3${9; zjvy82a6?{FeUy1v@IxT6zeNanjw-^&Me6h_d-QPK>I64T8NXq|{yxFoC$a&HS71{B zkyswZO1uK~0;qHBJ3cWmE>(-10M$A1e!7}~#wqO#WzW7YXhTaajw<WOt5<NsIf$0( zO}LbGr7|9zpHGm56d7nXImP@GYxYwk=~|Y45=w{Y%2M3B{1n}NK?Mqo+?F(K^FjhW zbGbY?!fTs+h&9Gr>#R^%P@+&jL`h2$(|cJoO&(?~9Cx#A)ea}S;9>MkG499~6dZJ@ zt>6&hf@V^D&dP^sa2@vgyo2A(5I$yEeGaD1)qWVwlZQhgW6TAWh>uE`dWkuey<8BP z%ICglBU1{s(z>R@Q*M4#q!Twk(f1uoh-<sfZ+0+BQ2pJLUpK^;P}*NOc4Gp`kKOb_ z>4s=O$dqHGVMKU=lA|ldmM+FPzHcZ!UDczd=d=*!nmrc1nH1;7_MAIji~-nzDbu}m z5sOP|AzG{K>4Q*H-P2QDQE1i|cPE<8N72FlH)Vl)<+9xDo5ztzl%!SwJ*EaKvVfRr z09!q2Sz00YRZG+Ro*d#0*%(93?8;&jWp-5MQSxkk)_|YRRGh&T2X2JdBxwoJNUKc6 z$HB$p;POC5o5^A88_8&{`l>Kkte*@a!dEH?sHVZUYAf^vL?MDbEDM6frgRqk3aOH% zl=Q`_p7aZWHCM449108+bF#gNXi2JwL7~-?mP0A3x-IR4qKoR4!nsz?UVGNAoW=s& ztKms=V+XNG@pvK-P)aX`-vmJQNr7{!*zqL=M}b4yE+B8M9M(qn8(=c!axIDlu#FC` z0lrHz0t??HOcv^zEm|zVieas#Nft9%?bP?YI7<xj*HH@4md$AlTPR{Ufu`4Sb%hlU z%cg^z#5L6~h4;X58CsaZ@jMT7aK8GKjT3S}r-M3<9|+-jGL+!_1Ns?ehez{g(&cD| zj%aZ2=wLJ_<AX}1dnti9aFh5;>iblyu16#W<<sCs(ady?G~yU?=Z3LVC=UIcnrN{@ z;uHW=qIjE4H2(rkdMJjl!=uSK8_#FD=;F$^$-!iHJk7pr)MWGOcDve}d<m)*s<}N) z6(%XKvZ}BuFk|zWN#cHui8;4aG4(_YHmk_P^_vAYRxw%UD5hCkGsAfVFvi4Iqn_lx zh74DGE<<~|WD_)Ak?V(IP%XA*)ugIcct`KMOhKS}X+R1aMQ(&u6}%7!2~@gV-<tER z_p`Q;MnWy>C?N0)JE}<z@%_Qi{%mn#-~RSC=iEG9?{GBMu#`ddQ1LhxHG-vP_x?aX z(%0l-K7RKdMe{D6*T3I8|K-a?)_FDwQ_U1Z4v^pM-{xzZjs#dU^k)H<dY2R+p2a@# zeQ^n^Efbh2+7oO+Y<6sh367%#j_Q5YH8YQc)uXDD*y5<LNgs0hV%|i_A6aPGErU2v zr9~~C$<PIKL%f#_k@ZfOz`(8Gsv3llu*^vEIK!hH4`!I8r8X_}V!5`=deB!SdqE_Y z;Sui!NJQY`+2wo6OR1W~;ZZpOPiH(-mjL+&i>tD@?d&Lv+v+}Sa1Wr5u}ii{;)(D@ za%=ZM4plP=em5Ga?XK{B{anKGn(<1(pVFZCazYL)xgGU2cd+wa#b=uktS7z&{;OEr z0{;b6ShtB-62I%n64$KTNAuBS+<IvjV{c-zCvO^sB&2{V?15yYX_)MnF#Kj+kD(EQ zv`sT0Bm#Y}he|?nsEApEXKQBNkMiJgHL}4;Fvr^|N0kS&YjaW5lh)2RqgS5h7PiOg zu;CToOT2-TpbT|$i|HAtn>It`Fs*A5ICWr&fyc!H4-<^7fPv7WS_$B7uVH=SfEO_n z=vJs>k5H^TKT8JPaEXL-s5DGqnnN&=V$e@~&-$Up1AS<)u~0#v!K4tBV}fci5ef3H zp)vva_4K@;4kdqL8WEMU35Uq>NJwfby8da&>uXOPKLYGUQIeB|%T`6`ONi3aY2i4u z3178@_KVq*{t|XNl1PIP6S4+bS4*VZVfW^)1Vo^PSVkbhM2RMdfaSzx;H{CO;BzJ4 z71Pc!^f?5ehU6TI{9KG65T_0R(wIxLZPF36Z<$W#hjR&{jE^5E&XYeuV(?1|etv;t z<M+mbNM3w6S7PMlK_rgZBs!Z?5CkR7;A!A3R!B2f`6!vjlPQe&P#AW>if({e3TL*= zPDmOER$M&RlNTQx_2%xbeneNhyL)ML1f#E;)V#-8ue@+?4(rrNSlBgzjGRF^#iTJr ziaMDUZ8w2;Fk_!rBDC65Z7}kXtYF-{d+L{SbUb?~o9B>l$-wI`V?e{z>{kI;O3Ajf zqu)biqh9Pd6tx?QZ*K0TPc)^I1>)>REyNt+wOER})@qPd-?wsp*w8W)M>UJuK%}a{ zA}JFu`I}8lVN#hPn?BBP($sPpt2SXGC^W<-n^aeoLetBQ7@^ygw85~Hwo{`rSYW5P z-{5@%pC;B-jm|pOU3<?*u%WQ69T2t{Il@Voce9IWa3?q!2n5?c=AR5313jQWV}0sL z!Q`u<cXu1g)BDqBR5_7-TEu2=uuPm04=3okzC|UcarQ(>&y4TKX_}cab<rJGEsCAh zX1zOH5jF2Hda9{{K}xVJP29w_9Wo{%1?xwrA-P0P1t`d!$GmZ0Ha!a;Ni{&b<f7Wg z<d=;MEIQmB+$UJ1kSVpf<<4mfD}9p^$BdFR_S^`wy=0W2Z6TtnH+FW4UpmTk^_CTn z_s~BigdfON16I_x^e@GM<2WR<57rHWjcRjQy<1R1ovc%G=dy16N{O*2r34<P<QuM% zWAV7WXxx{L<IIbh;v@jhILea!r*o<)C^fIb>Q_l3Dc+xj&?Slwd8k}&WLXM}m^0oS zQUh7nXo$fhmg#3ES^r4N$ogu}%Sq~8Z&|Oe`%y_Ms|=-%<jhR?57yL3Eqo7FT9qAZ zXdE9OT1y!*D<QzNo=l^oBT)&>j$_$W7&X@<AyEj|kxB4Py@8zm*_ePK7%mY%CbZmh z3{!<)mL_1)>n?$)-ZJKEh`xb9As_!_o0`a{0-#mz87^-QiN*q45OK$^Gp+!ct4IQq zfHfodhXf}=ef_MYd(C6ug^fM9h)0kL9|ST8>?E0oFA*L-KzN##y}l3)v*|aKm1TAX zBJL#FsEu@oI)?SGv?^z58XENU)lqupy3yr2=~v|vRRFn)K<YY<KEq4<REe6+k!XmX z&0Lb-)&ej#vcI%<3g4Eb3Dli@Yk@5Wh_>~2>Aq#n1$tfxy`}+~htHXfk{LRs$<Z^B zXT|gGK;KUV>-f@Jb`F}4$OnKZ(9*8lcy;$TTcfMGkxaM?B!ki#855SBw3~Uzwk@@3 z3}bgOgfSvm7zD0?nUDYtHfq5|ZOoAh587ZwZxZsWZCe__b&ZbKLS&JMg=|y~vM0Cq zxko34pmX$4_s(qO>bfv6Nf6+9>851MD97e$X_eOesqoiJipgp{jUJ(LsP2$wk!XEO z9098FHr~punES@)WI*!6l*F|`7#U~@wj6zlvtK&5#z+Q1rbsZPugXZs>~A}g64II= zv+<$jkUWBVum@0Z5z%kUMYar$;Ix1jO;(!nOdw)`L=ylrg!xl)9iLW@y41MRYneeF zD)QIJBdvjFQ{krAU_Fe7fiNb`3K6~BZ1JksfK-m7c{8)dX1nox3NJ9mtYrFkDSRp@ zTUYmn@1Y{q5K_$oh+YrSnnfPLDRwI1dis%u&(n2O>6%SjT~h>7oC456#FYD%8m*<f zP~XIQQsmdzkro#k8&3|)EQe@pm1SgOv0|y}u|ss0lPBX$C_Q2Sevl`~KXzcCFoCIS zY1lVi1$?breB#-<nB%5m$V(%_I>e0U;pk1$_8OPovi>cLy|o;eO%_2vrGx{K+7|9< zT64UpyIW$=8i*3gEHJveD?qxtTNb*yafnKxOOp=Q+xJM_gC%jZb&#bxTnk>cYjZj- z5mRNeCC#Z5N=ab@i<CH6XsPF<hp$lYyYDr^VT$iA58mB)ksq>;rDN#&eQ$0_bMO~5 z<_Rjlt2K6Cq`utgC*GU>+qvaks#4M;7z-IA`x){v5`HZc@cP4(ZRpvBo<|!)QxiV= z_rRMeM>W&dzlS(5@C7#|C-Z`dY6`ZfFq$@6Y>p*f_=0=3ceA}Pi<N4U{LnWHL_|FH z2@p1kPLVKM(HkQ}q}d;beGuFaL{RR_!=iyVRDvbnhte1OAkSaKK6KxW{&Q9L+%n}_ z+~UX@OoNSrlC`1pi4z~?WaMYQAxW_L{-i{qQm1S|q5@Hr9xy{8QY20w#W|afA6_V# zd&`H<J)=VT;$}}VYvA%UJk$&++Sv?EJP~)flwczASu|gbHVew@ssvJ|b!DRbG?k97 z*hl;*aU}^UsGecsaf^Lii@D09>04hP%ecY$`<|S=C`n<j)r59-YS@}6bphj@9l6vy zJDSD8Ur$&ZN@Qw&{OX0WNG5!hIEp{Yo>fvkAw^VB#FIP<;~WV<{PgNg`qtJB*`>Xq zHq{PpY#Xe<CFOHi=M2C^dynlPL`Q-diX3D619|WwuKrpGDtXf7U5Lc|hLf{EZ$qgk zK6dEWi^o)<L6a*!c?vx&yfYiA3G_R<2+z)r{3SkoKuPgQl+=#+MzdGq<B(wCA#a8m zlM+cgO&1P{O6|70EARDyMd4yx^KMx66M)TL)#_nS#hXXFtQAJr2<3uH`bO$Ifah$j zsw=QThcp_RwHtHVWoH*vW>I=%Dc*Wvg4?rD6`To^7eP<XuypZD;dQs*l2z681w!wn zQ=ft&#gua75<_vaKuQR_IPlpVGwa<xE6MCeVZnYea$q&uD=Pt(GyK$F?`k1uaIru2 zWs^~fO6ulZ5`bZzS0+tWQuzgNBZ}M9T6XM?mOXnC9W5D@hJ`C-$~3W|yO>?mAVM45 z(YB8Z5In6%lMp!R0QQ2KlnKeJ1KizX{0#6NkOv!ggO|Y30d`M%GDtX%wL4FVIEsQC zMx}Vx+nG*5G0=G>*6(@2Nvv;J@^P;^1(gExTG7|TyZ4AJO>F&KJzXB$PLkuJ5n0_u zrQCCDeLA*&5lX4uy~a2VG1|kpnoWi8^*xt_bEfIwe{K`(D`Jp5>YG;g7A~&ZCN|t8 zBz6o(pnz2OiR*AF+HAO+jAnDOTQXtbd@8jiiDw~EiA(>@%oIIRiV8seI7*`N{JBo) zY_-Zws5~o<MPxL}VZOpR;Zx5$$QEDTnr}D-`0N!b6c%x6qjca95_?e3Jf+SRS@^sV zvbk2J<{0aQ)lzj+sPU!5qLjVMV!~WWfBI^w@%yoIq1ZGu72Zg(RokVFm0-}~nhI>= z*8~QY>)zGP^=%?5$vX>r5>R{v84r({gh0=jbE?=OaP(I7E<Ih&5+X%ve*82ok~@<B zA<Q6B`cV&&T2LaP4O@*{IGj1ubTM<!b4V$J|FYN~aX4E;jrvtIrlmAVcrh2$m-^a- zfSFDnn&fN{f7p71=NpVrpwAwl30on1H_S)MK1@9$oQp7fk?D)-ktO#ck9&4+oyn;Z z7B+TLtih^e-2?dZgt9A{WC*NZfQ>sWfRK_|Mno`q=6If&1hwAk3>Nb}65j-vxRA1y zNx~&D<A}>A4|+DDc}prEPV$}DM01jW$iY`lYLP3im~|cX1HbP)KQb$cf*FiNS^qdX z(E9ws7t=!5Ee->@WLS3++`?9y^(>+XEH>93DN??k0G{S<1nh%y1_uPl5Q@#yx5&*G zxa2zAACwPYk%ezg`CFV}4C0Z4#L3Ve+GHlc>r=ugPvQ(C0&6!e?|alEHH<MvE&OdX zBzy)$?rk_z5wzEGf0hw^c1Y6)9}5TM&LnMw2-L7CKBWl^@?Hl>*N}91a<bdE!Csyw zA}P>nWhO1qs?<;QDLUYig_qh3a_btV(xpm*D~WG=?%9@?X)R=(=57RHEiJYnHi>44 zebc1OABsU3wesP~4))aP$>wMk7u7@u<d8ao?Ab)+WKuLhjEwrxc51(#)9rb5+6TY+ z`U`=QaMPHZ8s-M|fqe`6|EuN~Rv8pFK&YnkY9iEf4bLxF5<f{4EeS><0|mIab*)7P zmRk-loM%IMQTV@*NtIIfuHhsk#Gt;){-<3-UM~3bNw#TywjgYYY^Qln!PvmTHceEq zROYV0tH*zeK&m965?E;3h)NQ+E`Dfhaa(yx0+xOBqsJgokNMeF!Lbll^BjE|&>w*U zWAZariWLb_gOkk;g`K5_2#LSQk41dED%L@j0RC9NPCU-C^tl$<6i`p1#=#+$@}MRW z?BtE09*I`tyn5@a%ky19Z`8ZYi7BDRi4hVd0lI24n7n#xtL35CI(t|Z4QU-HKP^;d zK2_Bt>fTWI5B8dSs`ND~1&FHxDshEwOH#JhAFQ6=uOmoPs7RFvvUDCJFx(6!*F4Dq zV$xF<&SPro8?f-!XO(&j98afNLa7E)dyOfCG#X2WQWA-v8?#7Z7E?7YRffNnc72Gk zo3X4R46v7J)v=dl)UcNvq;iF=v|bqhLH#6$OUTh;$FRd%>ve2;wO)H8$lbC$ganc6 zxMeb8OI=Qb06sSlEC6<?O$ESqZ`UU2X{qj-R^3t@HHoMjKu$$i7f`|Cx$05}`|Ino zl7vNHg(CX+-aI=J28{}H=}^5Ox<q0nFzOI8N}WiEoWh&>>4G$Nd7^!GA-bu5&U5Ml zxRyut_u&60?@f5?xURHa{S;ro2$F`HsCnQO1UR<bpTBluLvlK}_rnEIqeYnFVGc=K z>LCC9K5GwEyQWih$V1vmJBTQ;rai8`hIhS-TvQFy?7YWE9asIKoVT1*tU}0es?bl- zbWOBlRj+vbdD}0>W0eZyu%=iPl}ce9PTMHN2d$6WXKMLj2lOQR0)sGYIdEfz7=ejY zFCRo-o~hB@a@iak=$8s95U>~~2pBSiNfz!;Ly3BAexaE=I4-gPo}Vg8kj;`+Vb4}q zIkCZpqN;MLy%Hk`;-HYke-&(a?osQ+HzjWZFC=P*^DWAyZlV_7&(t78ExjOb)xsh} zd5tl9N|{@c2o0q>z_g}lk_^E0fM3BN)PGBw`Zl743E?m(Aea##0;BFH(SFv`Z?mH> zx2kp9T~fVEjxZlJ=u0RlC2LVCEByvta@Ks^pxVx4_xhen^S^@3UO3bRHj<`Q6t;0* z*CFe>zx@0vV1cfKxflmQMFfqEna&Har0Ssgi-mh^rqTmJ8g}SKU9<FRejJt!;sI`r zOnBN1z1p&ld?31|ru0OjY?dx3hW52766k^8i>akd#bB4Ogc5o^e4CJ&Z32u8RZ(+N zz_XRY>~dTaHgEsAr5_E$l`Q{&DwY{Vbg7{mW>lLxyy6~0r$87Vv6?4!Kv103dOV$i zb|~x=6)x=24khk9$HHN`aG(zz$wC@ZUKhTYsEG@36kF1twoBWYxH9Ra5f0{nC{KvN z#@RERsC8GD1wyZqEF3$S$3=?1+gk~7coGy8ZDxfEf5`_$z2IZ{<zDSmL&5WM0S2#A zFC5#qrvQ~6+lC`hmlDuFYJj(|NfVU9t>u+f2Dy=!vt_ZKP8pOsdT3TvXS?c;8JR^2 z19&DWqZ7iX7N%Jo(fOyLFnF$ESUYAHtyMchBVvPwNEIPy>T(rQV~rj86vPJqbfaVF z4#K>K8?g2>3N}Kw+K<jj=?;z_on<X-gMdCvf<PP;6^06|L0lxYkmIb7AROEH4K18G zLR@Nu3X_~VBEImYg=xyUx`i6y5$!w>tBX0?L5uqEHc=u-ig|8|)rn|Z4PhPK;tfOl z^b80o8V}MoNHdR+C!Xoc0j%ec^>u8ApHPe0e#ly0ge0RrXoX{?#@*#fGU7>j5q?8s z^E{jYIdrhZaj3^2HK+yie_Bp}V+ZutOb0r)tq)f}k9hK5hd;ot<0PP7b}O`$jnG2= zx=U@lT+?%4Tt(aMNx>-}fPuXH><JfKZ%Y1pAm-=j-V^MkfBuAhiZ+DU{)F-<EhLbJ zx;bsa{;@NwRHiOib|{UX0u4CTGPIj8rXns{=TaK~Bii63_a}g7;pn7xl#k^Ris>QA z{f~ROlk!ig_ofZvnBwnk>ScJPZOZ@gpZJ&D$s_l}5&L-?FTk<GJj}~pXA3y`{l{<! z9Q*Rarpb0@0m^Vt=P0Ywz?Z54Dr;bkS>Qo!RWiYiP%pvfU_&I46Hr3sktQWY*p}gQ zM|!(Exin=Vpy*T35S+;n60OQvdKwmjqsQ)_(EIu?tl1xf*w(tFlbC<VR6kln+#mop zkOD+)1V<$T0M8E@&bV7vL#f*>dE+jpgkC{O5V+f$nB1IyDtGzeQU0Gm6%gd`?hCOw zsFo;82~4i8kpB@m?I2<U&}jHnqA2lL)P2hPp?!X|{9hmLQ)bgGq->{DDxx5GK~bT? ztA*@eIUxs`-KXsJc7t7%$_<<Jlw;&3a^s$q+9s?7Dy0WPw7Dgb``AVBfZ^y=od?2O z1-KuByG+Qtf^`*Z#=u*TZM&MBhqcB49-ExySJqKNX|$A*tQxHPpmr<<^K_(rO#G2$ z6dnQgM8!_O^rcGH0DAhMCUirw8TZ)(Nj(aP!kds*apvW)A}d*Z{0q&vrqm6uNhtCt zb}UR7{o7nMo!2YY3RLnoiQ$R~TA#2laV!NSecTvyu+TDyi6)n22$f3_3U`c#g+A!@ zhi7@a{xSnWA);GA+0c@bnq{ffrhg~|Wrf<{*p447BK~DP4995b|Kn*8YG`?KO5Xx# zO-nx(AKV%Z!m$hUnGfd$as*J>9+~6;B~7aU=;%0#x`Jrz3gbzg`7PkOW4Gg~PJL1Z z#<C)SY)qjmO45+hwHzpgsQ32bZ(5(*F2sA(b_IhbPzSU$iu}bsi~Yo??PIsb$rs7? zQ8A`@BK4vnPYWm=Or<Xrihm9yTOadU-8lcUNp3xxUr>?J+GHs?nm#UEth4n|Stng+ zssOZY9hF{G!?gTsk}e#*v9_1}>Q>T`;fVDS{uifWz&;GK04IK)kx^Z_i|zottD*cX z97R-rD)_5ZTHgfkva|F=5U<XJdZ4ikXbzSdDp~<vOMz;QjOFJ^`#N@$ynYNhg)t$4 z;RAN1L{FI%H3G;r&42s7cFo+SXjDj+c~Y^^qd@Auqc|={qkhvpK5P{K%bt=luM^S& z^xiNlBfp_GDD2|^wLuro+;>V9c!M4EuR95&e0)j<3p5PUmk_8JW6x>&SQ$*EFlqyf z&oWNpT%t^;&Bs4pygs~FM!Hf5K7ypy%V5nVIM1;n+{UZv9^3c@9@d}3Qe=|5pTLfQ zhtUtKwuFI+Nf|g$f7PyZ3+@4qSm5bFSp}rwlm6pN^v7Mnn_p<=Iq<1|08dU^#8nFT zp?{luLRm*_0e4LmWFVt+l&A=cT{&WZ8)Ml!bfLAa!xk__9mlQ5xp~q&|A(#K6Q#^f zlHyZ{MC+2uF;#&W%Esxk&zk*z{K)hXnr-R2lkVqL8rOA1`Rf4jD*>88w(xJf`<qjR zw|iH5pA&To6CdJAze>Uw0?&UUpOdw@HYhGL`9&lC08W7%m?~*;M9YDJY~>F)dNucg z7;XG0VkyFlMM3&e$~lD;Ccw37<Nx}s0$vc6ROSgGI81Q?f!`5ch9}Zn!=Is03;wIA zI##Z%DsGDE@=j>&$&F7!Bw@-lH<?hNbmKRDkkZ)i_t1=8zz?sB1SE|QQ4Q5Jc>&Qt z{7r*9UfpNCoN|xFCBv<SxPZt8r8zlN(_{fgXim+2@yi9BJ3oJ0{6hcuSmzEhcl^iI zt}L!bCUdlJikhzHu~!6SI|Nt~F|2<A{Vh68?YNg~4J$Pd`MGY99`P?Vsoiw&;99S8 zq;Cbs5UpVCjt9^Bnup!#cMC*B-PxT$&EuDFZDRXESHy8PIJ=MQPZ}wbKQb)O&Tc<l zSCj$1ziU38oe=<S`clW!daJve+p{wPVV<3R#h;2xL;lHl7ikpdB!y*V5|xQmZ;%Um z)nD!?<$Dih=Dw-V&;NMezGW(GMOe8=OXP<lnd=`hzkSEWYleL69GL<}gFJ*75Bjf) z|9d4vE^VM_$c3r_r{63chMQA*$`|EF|HYFuvfmT)#kG=xrHS_<D4=7c5Z!DmpKHj3 z5R<ySRNU}A{zF0xhfE9ms=2y4KmW`1E#}Xc{Qa3n%x~H@5t>=@mY^L06)|ii3xzeL z=k?~6*)6Yj)lV=9QhE6Ly4k;e@qu5z_+|G~bN%Aqs@?VNo%KfRr@q)%>c+tenSaxt zch`TuX9UcqJ@)z6FTQ_IX|&ykuZp|k;V+@V8`_Gn&z+*mw~(?|yAL0B*Jo$@#%%ew z4fK-G8Qwi&@27qS+a8>v2{1!Qw|Zk~eg_~JQ}i#w+qj!?&o0cTZSDEFX)R~LptVMe z)vFU8p{1qy?d5gz*S#<|_6v7S<m~S6w9L`xOUV5p0~kT)`!QBy=SRcVq~!VB?RRqS z)(v?yaaaUxmcom|LFd|{Q^Do8P3r}DS~h@x$R8RHh*@l<umU4McSdB<p7V2QP$$oZ zEz(Wbr<eXS;}sX}zL9#EsK105A;J^BjJ#x5*^72*t-O7uQ;4=S_cE!G=wXOWq_Hbn zo^0}@jnA?NvLtMy*pE|>z+9X&g@>m+YH`u~WlC{V@O(86w^^C?$UU&O%A5V(tn!uS z;@!xTCW>0GNmDeMadTIUg6e{;aen^gyE`<@A4e+NbU)w%4hvQ%R8viym&7n;2Iua* zXmp*3XSkn2ukq?Oz~kq`0hLl6X?0$S*@I5Z+nVS^gn2pJ^cfxG_kUO&73P36@w`bO zHY5T(krK`^$Qf7vT*!#)zbKs~iCwi1O-@9|*;&iqzPj8WrS0WK1?0GBQ5<rrn`oM; z&U-hV&=6dspTk%O*+?4-x#`S=I^wKF^w6d?RSFr)m_Q>NHEH4t`_%et)j=-`sCvJW zti@e}lGyJ6)@l&E6V#P8xJB3hUa7m+%|~I=rl20l6JG1#`im&|B|+1VcdsfcDyc?i zTE&)afsTE*hrv?b*S%*t+N&JfLR@FQUWZ;KIN%6NppDFdn`?$}{Ym{c3dY}X>M_B8 zDsJT4-+cb%=U+=d9{2qSd{PX(SOL1hL%iGGEAIP!b9;XU;r(0n^OYifwAt1WHJ_h< zU+ixiM)u8qzuUhyI4&h0)EMbOeA!<A{&)QH51;+}>(8`wIr7DN9<=`B%)?D_$B>`` zeaT$CYl=Pe&ohf(%~^MEcOOINdol|bABwx`y`1&fH342@PE*)GgmJCEylF`(sy$s- zCaPLrs*gb<TVhNBxfQP+*ZPH}Hd&&R?EF|$%4tiKrb&(=O^O2i(V$^*a)m{kVEgj> zS2CJru#X(cmnsqSG!xPZi3i5@G4AztN5QHS;dpk>*`r=+T>Vi-dGI(-T0j#K0>ybF zBNmJZ@%fePpBP^DThXGj5D{2FhD;GfFc)Y!>WW_Wj{L%O&f5FyO3;e&*Vky<IBKr0 zx++ON)ep(%L5B!}nqJw9uO2<@FZDiJYRlz^o2%Q*o1^_#=Duz8+1c0E-(6R#8jR-g zcS-+0fBW_4XvIpbC;<agB)!}50E0y3QR>A+tV>9)>kv#^clDKS-HEpQ!QCMgefx$& zhws@HsHGkhP@L&?iHlBOnl&i2@EN7GPBn66VBn)r<1FSvq7{@FTeP@}u8RNu1S=JP z{%7+^ok9JsWs}n=NVtTjtS$-)^@S30;`dM3qPDob^8;ElZitUy=VUFjkg~yHi$pt7 zLu8U2c|Nq;9y-jy<t|ogt{;5+-Irf{d-3jvuim_Un_gVdYF${4DkgPOWL{HLWnH2- z{Z4;OH$Yj9m$#Sy-MoJBM}P^tU$92lpPgWd<UT)eubC=H5xlz;u1LbH76LUVN~oVn zj9t@>upd#l{-RW0F<U>+vx?|p6U5MGLIU*W#qbuh0yeL|QM0E_@CKjvsxoV{GWMIK zsF-cslpHxX#r0(+Z<2-Fjd0#w3bKpO@6!@Bf<LOO-R=Fp;qSHlqW+x4+=eK>)T&6J zlJM{j^g?xuqnH?Vko!3k7DXA)>v-zL_3m0qKwK3!H&_u59vE>-ST}JU<w4kBpTY!J z1;S*n+{8yN#%|2z)rSZ+GGNZQ|2&{+B==S*tVa=SEK8lf1;kh)c`1_sPghtMArXMg zD~YA(uRVO+cy($BG<bU*g&_!nz@z8_sX_?#gX9`p+Ro@rZHE9eqiFFjv!pUO0me$c zyO;IOJ+_BRWT&Az0_APu9upn*>`d#hdi#F)`I~voSsjyX+OxAC_MhYy&hq{4!v)6m zZZFf&wl$K6<(1(g_Zg`E@{vu|%$U~lRVT~&`4<pF-`;9%x?cygW0@66ln{Q2i!w>d zbipTcysVk`^W{?gJE{oBq(P%R-Aa)>ZgahO*qrj1OraUy?x;boA35YCFS#pBp8~vQ zG~S6`G6aXzcLz%*X+GXi%ZH^9NwEpU4emCwd&F+mmrl{lL#-Sfc;-+#b{t;ZEC2sz z!$W+uR!;Gu*Dt;ml?lycJS^&{K5qH+`dH__jc|9@e*V6=eUDvqA^&2xN{)?^YCeZf zn4$Val$S@^%-m;B#sRf`BsVGx%zvw1`R)$Kf@liSf4=#D-X$0K7<BD*;_j5ZX*t^9 zicZC)q%QS)*EJRrt#%LfX^`4veTG?+Cpop*Tzz^tJ$m7*ar^y!621J4KmPFgCEh06 zhs|oL9Nd?8m&FyD5(C9?843$LwHAEQT>29}68Bb85ahU|yqErYakW!nS&X&<)Ik`* zUyxAm9nD+ar>+kI%7eFfU#PqOxZ9yg>o=8IUbUo1#Sm5z#nLnx12?^z=MeiQ@K6QK zG`E+SCFQ5PMkc$h5)ZDf0K+{`lM=~nRG#5lk#``|-6#DLdksFEib#LawDf}~b6q(~ z7U<cTIu-cnkNlnW@S`%EbdeK|h^hZ&YoU|;^15z58s#yo)lz~mB%uUj$|Q7G?O+m- zaSpagtG?!>5@B`fmJ!LoS)6ASsX+Y;SfbWW*NCQcww|48p6bHc**DTp1g*60o9^U= zwNQ=S=l5|*8M6Bros;n#j0&Xz$etoiCU2q^pZsuCy2L?zjB0)aV!-^!NEoxd+Z@w% zkatUo^&@M5s&(*=M+7@c6s+#*WF-Z=+Zc`DddG87Q~*wh2^NGkHGt4M)fM|p(BAs~ zcQ?)TcdBB*t*yC=?ZUpNTwYd&93O99e0_P<I1feg?`X$^e50vi)D9|<B@NI4!OqA9 z<pr8{k1q}$uD}BoX&9G9oP@psjwoAT)U^1*d@jNX(gX=o3Cu$z<OJ%9)4D;IY%4K$ z!60E~5>rUBgb}o@#Iuk4?Y+1Q@7}+*$GP!wcabS^6icrS)uV*X8Oj}=?<3A<<2FN> zQqGouOx|L2cyvMBW{Y1`7sekn)aABS#x(kOPYrqJ`<g1bDP+%*zJo-oGbVRl$<;c> z*tI&_kpA4md?Qkc^!3EFxoAEXN)-X=jTTrI<QU^@42|WZFY8X*vF+Qw35=MLe&2k! zQ2-<&e;Hx>3}-obA2}rKMJt{L5<9>LCbRh!jEUAlBVdqIBrb>GA8rJbNjG}REMDm! zD?iI(pB_<J3(R>W&>s;!THY{LI^rRpafPtDaJdtezo<o`*zadKbUP)H+13vMZD?eC z9B6-;cnv0RA&y~VE8pDy>GJyi_Pgsw*#!Z;{~*7>F{b=tkedmIMiWxuunf=y+#BrP z>4Z>N{j8Ko+@3zX<s=tUkwrEqzkg*s80G*In_X>$SnUHpyu#aaL4kSoO9qKhOyLu! zV!5}}K%-lOJLKD^w21smVaPT*GH9WUi6Z3;vq&InOp$Y4cSY}{@&4*W*QkRLa1S;2 zd6pzi;#FadQXn;3=tz>N+3KcPjltQO8kzs(Id=y2;az<I;zXQ6)SWkfler6;zcFgC zHK&Xk^jr~Kc!DsJr6tcSSU|wG!WxJknP_#La}uowsAOgKTW;aKp2UtzP935^(2&o* zce;PK_+A>EWf4woKM-GZ!<Jpnt{N%-S~H(lIY-gWLrxOP!4hK*Vg?!<S3nDna*}Lq zh2toRynqE6v&Td5@!}7bFU}iCN4(x~mgH?7Ck0Nv3{HP^))i;T`bV~45`E=!(a}v7 zZ(hMIk)*gAQM|*1#pqlYe5G;Gm>&jSDJy*Ru^7yN3pw?}UoP+7UpT<iD63iTUI-@+ zby>tWG`PbGfBoJ$DC*#L+8)OhLC1n>LoqlDiS)iNs-OC{>5~Z)tokWI&;T6eAzW=0 zrSW`ptvnAK9V^n`+;oyTZvre+QHr+Cqqu;#LhXC^O^J^8N-#xBlPjDvXJ^{gieqT^ z-7nXT7BmYQY(}$pauW>)McD!(rfPMFe=R`F*o&i)BN`QJ;dacIO$^KZBKZQj2ils# zUexrItWo<#8RJxcLoEyy&c^*pL|cJ5W`yVN8ZRy0GizH&aL9a9ovh;iqL-itsKSXV zoCI+R8cYqUob3AK0;R7HSv#h(DbCJ-HY~s04M~~SD$vx~8K5aKB<fGss=?|kaL)mL zizi!sLD%M?f0(gzza}0l-Eg}?f=QO*<Rke=;=!1MrkQGm>fjp2O5lB7+^Qd=z7P%H zN%Q{Fy;#me#;B?4i1UU_*9Ji^(E+)jW4UIZst#&Ym^#r0nxCr#7&D>(d0L}t`e;*e z6yo8Kd~b;k_ovP_Z&uR41LomjZiwoE2<W_7zyHI5)7xwt)oh8X^nhd2KtXL&McTuZ z00krjn9@LItkdoP{&!jK|M<uGxh$pgbG;IE?`6cDMU-mLOSe5n18<k;{L+?L{<W4A z6kv7hq2)o<39OPG*$LtU$^0n31P?tVRh5^8(2;dx=crO&-rwR+S=6O2c!sr?QP5V@ zsJINGG!M1rdrGBn=q68sw!ov43tkXC8=)tYs}<HGt+1iFX!W2+*@%u0mpEA)0^at$ zv<27Ht$MXWyN{`VIb%LtokOqNG!*Nn5(V5hKVIH~R=KF}R3rgDc_P<IBb8^eN_<|E zyH4XWl?GktFaw@BoUwLSb+!oUuj70CaNORK^5;3Qh7i_1l1Lb;!5#8ar95xZONI3$ zMtwr<#v|b?5qtA#91~QdK8lY>LxGbqgvuk^OS!dZ9rOa!J%V!u0%{Npd~!(<J?^uP z=839}SsC+RM!so{&p~OPN59WeHF5S-g6PGp!@3egijB)1^;R9h4#jmWC({pdGC5xX z;4Hj{KDDfCPChLh)MU;*7!o-~qJYyQ8583vE8r-}MY9Lua8$F@oW*nVV4b?u&4TJb z0&h}MhcV%NTfDnlfXd3sXYQlX971i5CW{LoDubFMc;>!!Tj7CGmm}<^q@dOTN^%xP zO;AWRp_zt?=iylz>n!rJPH{tG=Vw%@PGhr=o~sqkq9ySr2isDiRCp3S>9>Zc1?T4n z?Ab?6pXeh)iGKhNG>Ws7H5D=lH05|5fCzD-Td6tk8bA|kky(&wWKmm(7(GLm!_)Tk zfG?x~-RL#=R;hd+<6xd|nD!nxsYbKyovOYA_|<_{P#-)D^D?B60jg5STAUjm-HM0K zxjif&I^{{?k-c8D6$}KpP9;F7b=u(zw`vWL2v#h1fb2xd$cKEC)}Vwn9!`@<bbfBM zgv;v|-}?^=lm88WpJeMTNLMd|i$HwekT#G)_$1Qxh&FFm4pJ&2QffA4f@&`llkaJy z?ZX=HNZ$%KVHn1FDAjNX2<e7CQu;o)RjxE9QHH!$_>&0{mMJQPRa9p8y#D2eoq25A z9wVK@CLn-E5*z3wG88#c4ol~VfVq!{QKEhcqJ3WcJoFqow&w@rWI|dP1*{{&E<~gR zG&v_HM-AQn{gq(~T5QfNO+ZP6khdL_(rahM_C^gi|1?M!lWajP;TFPDQ1uZzX>LqT zyF&Yck}Z8#{G_lK)Z-~)_!|PE+-RjpbT0fFTY4!I!L~Hb3F}7KQB{d)FSU%EmY#m3 zj@rt$jRCm*Dum}C2clQB8cCwJhK#w)F=l`dh&_Nlr-5P|G6lw5F8mr}9y%+bU}W0} zzF1gZk|@V9?TqhecWxG-2ehkxi>%GO7s3J%LS-$4)}``Q^lNm(%pYjPygGD1rM5GT z>z>mFTRTf|s`?8v4QUX`nV=+-I4g3=?K;6sAL!2dnD&_qEoBb`nMTq=1mP5C=CPRz zM~cIvc9hT%u~qUK2O0Pul4(%2CF;-b%}&`c^N()fR53OUt79M58)8Xu&8|r~eV?dd z$7eb`pwqtB>*2od=;6Nq!~c5w=8LZ`zWMXl-#Lj8APtD_#JH8=`6CKAN`yFQ?rd-0 ziE*OaKl~8f=rM1fGs67TVpTgQStdSNiC?l4QfNrZ3h763S%c?6n_hD9DYnDQ4sJBW ziEFD&i5c0>%j?GL?YGGEfJRG#Ee<tSPbL8c)p|8<ddXR<umAdnFGbZo6rk7E$;?oN zxU7f;7E!>#L7hQDXoFiiMQG{Z={@wZUzDWCMoE=oS_ZV)psZ(F-L<vzY#Spx(PNQ+ zx@@j$+{_XYfzQGBF<Ibiz>y)${N2^AdC}eFhbH^#eqTtc9~D|8i17jJ=%pY|{WL6v zdygbI^oa}~oparuYYR;wX5BO@uOmaOl77w9fTwL~hPq-Ow_XB!J4BUDUh~x=qxQ2@ zit20>a4rdeBml9rt<D;cq7&lIO>um4I_gWW1UM{dhzdX~f4WIrA8shVu!qh^68i^l z4*7M+D|mHQwJqUZ&<A0VL!GH!E$<yYq3<RWsRcO@bBIV`SRMLu4x-eo3|>rlfmmTf zg&Ig=>Y7{4wXP*Dj+k^<jW&h`g*43uv>O@QU_W^i3k6t26ecBT5V)f{Wb*jlacZag z0pHg^<-Z6p43gsMX8@C-yh9Y36l^Eqa39}fr%}DvQjLIvb(opJKvzG}W;nYWiJlY7 z6-@=5)W|4zizhd`%iG;`^z~KoW1;~GJnCVD0$eQ#Fak=6G?Gci*!^s-KKmc{#lG&u zn+ekTHIZq&O0AR%1_rJJjSj9nS2<+D!sBQ6H?^Qp)NgPc-Cy6WCXh8$aVv_lii0pn zDuKA$MY|<fRQV8pQxz#fVXwlHr{_RS3iIr&z?I}JNW3Z{K|+_3G<Z{%JwD?XJKmTe z3lJdK)FClWl0o`@iCXV?N5G~76@pENoxrYPfUS3A^!B-Ui}M~b4N$|&I85UdotCX< z2XgK~6R06k7v?t~!@rCPw~2&7gX=#$K1SR%W^^rRY^YEd`5>KZ0@&zUIy1(Ga>p!O zYL&fW0husuuiF3wRx21Nu==SYsjIJX0w)L24ENW+>{YfL3=+UkO9)Pg9KqoC21Q0L zt$s-#wx?<Dcn5kv%I1?8tn7Ethb`nE)V3py*_ZU8{;~|6-TrD1r-lS1H5?$(FNI1! z35n=81q%Y^M+|e!8@XT~S9b3Pkw%8gg*ZHE73xhwbS$p%X#rc}g;u25n+~=s0nT&T zssjjlCcsdbq(s$V$>>Y=@$Ot)>KfHdVWA_o7)4MV8=)~?t4j~(L`-8LL;@jKc#hZI zm56~JaJ?YuJLHS7>EhUkiz>)##JPLJfk8C~kr~3EjF?u*3G+GeL^F4;JNxeN?AW|d zcyk1bpQIiXlq$)_Zu$9;kr(4`ixbidY9Jp1#2Wgwl-e}qtoaXFn$pF?>&_2keO-uJ z1gREd=BKa#P}CXsZvo0hR7&RtJ7#OsHhHawf5!LYqRGP=Tn4>xUu&h$@7Frhi60SA zW(%F4|CJX0pnIUj*dMz4`cTN6m^#__j+SR3q<Im8QXtDKbj41dovcaQ1mDR%=Z=7O zZ7mU?kdi}Iz6YWLx<KeZbtZ>#!2onaDY2k2-G{clWU>b&RU>mIegudQBt}qyX+jN0 zbbB~$6o_xWJ?6KH`c(6t>V6x9=>SE@S|*#Jy#y60Z9h9R1Y2ikAh?8bsDan;ZYNk> z&>NY2)j(q@jsooo$Og#%p%Oyi*oz%0;b54$EzYXCjMdjt^D(0k3eJ~Uo)2go%&(BU z3i52WkKN0Lrk1>DRWGEb35ZC*hEn~uskHtivSQk>$l%z}B1Mh#Ao6O$Tv~>vRlVO& zj+I3J-uysP!IBRYo*XS9>Qri^(XS_WqU&U&Wo6XTX*dV?hP_i8$(gaNYpXt!EtQe6 zCpDZ~1;YGJ<$4*nfZ|DlYV!YW_Pf8hR??#J+o>_N=e0#0BKQ3Q*E>3bQDe0Gckaz& zr6U?z8>Y#!snF!`Gh+o;Lds^k*d5E-Sc%os<{{E=Fmqdy!#GjvxHmIg3uWdxg2GvW zHA)^25NJu9IP|f|WY*R>;Be5gWl>kuH`m!8<AcQgnthPfR6_zJ#axS+joN)~R+BP) z!!=UN=csKVNUQ#9-GGc$4f7y;A8<WZkpDF$erAm(A2)O1*$e|BNLl+eD-wODYpFY+ z<7aI*CC~~mC}HDZ<9m8GG#*!V)DIvQ9b0-p-n|^b1;<eW?$K;)b&OgEkYQPM75q7g z`k8vjy#keLkBd~w%|Ttg%cDon6jqTqBE=wwPkQL#alc@M)Ktt*Kds^_CfWl?4Xp?p zm#iJwGngV315h1!xF+OX@9t1_P4-vl!{7!XK-#iRD*=}EmnX}8Jf*OZx$h#86i$11 z9SC6o_Rv0_wIwxr2Q(o_CCPk*)&oazx3q?0I<BsZ58^Q?8Y-3MKJ-@spkq;()fH*F zp2~$ox{qcgVF8bxL}Xwh%@aIMCYmu>D3&==UY_VQYjw0(0&92OPI2}str!<o(?WG9 zKjb)!)i3Br7{fACka)pr5(F}HE%yv@iDro#DGgd4H2TasQ%Bpu-kW68GKA<gA%Pew z0IIKH>llu<`S-q@|KdnVkqMuhtkqLBZ(>p~5Yx;C<p6s5*Pp79Oo60~SezxPI8@)_ zNT4n`aH{^9VGANzEvpS6o()DYBL@XM4XMk7CT55D#lZ>KJo=$0UN4-IA>~?B;{WpK z%g{rdr%8@XCNI8`LrL{NsALZ1E|HZsU65Oo{bQ92&l;t43n~5y&5k@Wq4bfV)|t*^ zGSsJ|G>1t#y~y^}T>9>#Eh+qh11Tkg3O-g*63NMzR56Rt8RgLbup4L44;MplDd|lp zVIYwTB5*|-;7wl;G-~B=dq%1}YJA;Nk4K96b+@~Q`ABE69?~Xjff`~32V_&>QYOt6 zSBl=+&^P=9Ekp(I^GkR#p|I){Q}@jWoS@KH*Hkd(y;2|{!e=ZxuUfcsFL%$!r9))t z;f>~|di>aTyN1<X(bvq=*mOE3E^-J+<2<Ie0?Hr@V~eY7v1_K$hYjgR^i0Ge*)V3d zQ#0B4NN;ynKg&txGlhie5XcSdtYRLGw&^NW{TuA!qL3B|iHMOBP-$vtSW_(-%;|&~ zcXlTBmxa(zWx?cdLVp&ifkw(HWLe@OaJ^ng5U$RB5=qS&C08fw?T@ynU+)pUYE5VG zwb26EwVaq&mlZ$0A+bb0wcN5}C~5Iu;kiN~PCQ)4LhPalamRB$Zrkmr59Ll6Wn{$r z5zf2c2bq~BXv^u%1tdhI<-OnUu6am=Nf7|3!zT1g5~3AB^PvY`4du9!pz}^K9Q_sG zH>##c&g_)&da`J{1$KTeGUohT`N!1on<7__SQ7(<r4@S?LN|ht5uA0X@s7gcG-Ev2 z46&hIIkF{6>>Eaw{s<8r%AQX??20MJ6Zrm$AR4-?J}M5+|I#rcS$Xb3@+`zUU0(wD zT*w?@uaW;&G|F8g$KK(-sEK|)vYoEAloDabL3u&?2Ze5)M>B{iB8R4i_reR}T7WdH zEp13nv$;jz7dAQp2H`5l+r(MU0PAw^a%s!ZrdsP~60FXT?CXlwsJ(VTlxZOgU~gKv zhLC<qEH1(G4u!9{D0)-R*-WmAa6oJTu+B2{CMpraA0~_E2w(bmh1qXv8Ll%~Co=p% zua6Pn(6i&JA;&!}vlNtqno>u@4D|SS8s><ADUxq7#e_)lYViNGN+Sxoj$f0_@;(h4 zTJ5f`;L8(%bGQ43_Yw@ztWRC;JQ?Mq2EYJ?abjA5%g+ay9dIn8pp_ix-PP5#W-Gjm zCu2sMcIzO6n)KqDx-foX9`9zw7pD)$7Bu74PwK>~Tc}S6Fa{O0udR@P4(?cOAY1Lk z2TCJ+<8aZiWCO?vvBOsmly~abR?9Nij&aHH-+roWnQu{nx>;jov7AVS$HiRXhDrkb zP~Fw#A#)n4C#(H%mzDRIS9I_;|EekPfBcpd+f<6+Tq;gDDC@|YVjDy4##Tn2nro6G zk8$pZgl<LXue|)78i4b2l)m$Gl)lwwJ;%Pz1DH(^yb(!Hgh$zshZVE&h%I`YwX24S z0Z5zRbxtz;KrQ*=ofl_39Mp?@-5Kz+7g^eBnwCCloF~xIG!*`hai37XMhXin^L^%( zFP-VSwYny;ANAKiqfm|vd$Y0BDbqa)dxTY~^@CF-o@FJjC6<$DY9aqzb$PT^RF`nM zVL=5Ha?t*hgT3z^XE-GpXa(PC1G0U)A)hQ!VLJS7|JTdf;S^dL-TwU{`8XKps1)Eo z6uQSa=I+BlE!u7~<zMW7y#K%!x%CqfV?X;B2x*EV+$mXy<3A&f%}2UWszW03<C{ct zP;XN<_X2HX5P|3;VVFaOAia+Zz{JOe403yX+)zit)$apGqpnL)A@Nu~<dEFo-0b!= z`h_`kYik2KR!O%EkQYUHrF!V0jpG4>6F@R$lHO|?HrGEV6k&mNi%miaML(q$Ae>}T zOFBH*26f3u73E5Vo(oqKaJpMuZEBdsa+UW)7u?NT66T$pGwKo(nX1LgV)X1yp}q&O zJvBinZ3@4yALSe`{J!V+kh@*8)`yr-KCAtDA=UYOP1eQl1iS^tj#?iXE?!C<NL4)> zE7aG!2GD~<zbRAgmuE*WDj+d|DmoyORY*6rlUi$yiGEx1PJJ|2pve0>@hw1xgZKiI z2+O92io!nWuG)_u(Vx|A31<*l^Eu&;gc@Zs#A1#7g|?_jg~bsVS)-fX1(Un7awd2> zc(mU*hk_g_qD)9HWZ+xa`M|GH&RS}Wpv9PL^I=uX-(=e~`1mwd?@qg_%IJ#1x0*e9 zp_fX^xPYh0yN>Rw-@<oN$4OLBA{6A?T3^?j;Dmg1^UTI#VIJAj>E`4eNB0nlpcwdX zLBdu9aW9I+;n`F@oc*-!8Daq~qu8ruDfryw2NYgcT^>BtcLAZWPw<6a-rdF{CM#`k zj0o{uQXC$YGfxxb5u1eZpMt{BeuEm<0!kkiC-{USO@vUA>Y=Fi{09k%b_Wmr8hQsD zV5l0>`{4l_QB(!$ODSZWh^i!&q%U~5dRu1RWt6}+2D>-N)1rptpEW$R{j}2@_mo>7 z>ChG%&Q?ENgQGIAP%(@oab~7TC8oJY)Uquh((BGjIDhud=EIVr8v1<%Wl}Mw8mQwX zuSbo-lC5td+$fr`6G}-O_&=MJwa&4>tPb~%O6Rcc)UW*Nvc$iPLn&77dN~t_Ndut; z15(#ORP~`d_iW&)N2YE=A@50RD2D?4y#QAvGlNjT=*E$|aH-cW<tdI@kc5o~n_vU{ zSWHjDhq|Tzayq-ghf!F=3@_zc8QBOZF$~m@>-P(DNwv$hgZ@I%2mxxLGDnN|&})#p zY|`$kvph^qAhkZv&bB(TU00#;F6)4kHs^Zk>I&|2pK1tYl97|8DL~EDm4RCH8e)H| zJ!1Gik8HW@)v0#~)7T?kMb<)9B@~ib@D6pFVZW5M)Dy>7I1mFY--LCWQw0QJ0lZqs zk_UI#<9*$Z)L-ib!@OK-z#3I76e(l~LW$it{M`RhM?<&YPzJ2Iqu&4jsrT!(f4B&C zm(_Dse9~CYiVS}?Dn7O*00c)*ZB~!IWo@dBbTmJfDJf@baz}Ne9=y<Xof-HLW?0HH zqC<o8X(Sb9c*}#EGdzFxx^}q`zxPC$rc(ISc0A;pgt`G|5it4&aV0jQ%-n-pd0<Hf z4KZG-?hs-HGAgI)aE+K5Fg+8>bm`ezORPRToIiJycB>AuOuOoYITF)+I#L90u8CZI zDL+(1MEycG6d6%9_0ch|K)+On{n63Q{jDVD#Z8R=n)p!#l8|GY(rsK=>C)!CkQE=W zCnZQFFvJU$5CmSlf|825$3Sy^I9S1qO>bLifmQQ|V=AW5mMto#N3;J~3SQz^y)Ld8 z2pp0sK_5<G>SGnSh{iWPWs@WhD=nfSFdP*^+|OKAkfL#}nQM>y{xl}xd=zJWP=Xf( z%hCcmL=)Kd(bq3zPA?$Qz5Ma|LdIWhFFgs#w@Lys+BZ!hpm*}2DVj-M8=4_ho@gxk z()@FAvELUeC4x{p-U65jFdPcO#i%PQ<KY|#;5`Ff0HX8UceoTkmU3F{)ehb2M?%T6 z7FygQXa^MEB9IXawZ!P2uEF8KSNq1_ZC>lOA?PB~IzjIGR4?Tm(Ef0_Zf$C<ADeZp z2hbMZ8T=B9r|;oLTRI>qf<k9?Nu??XTG@Ek`kMRd%<uT9-FYTHL3$_fmml_@-s%Oc z4Y6T>c}Zi0Y8NW_dn&D|z*s;@rU*j40$-b7ij%g#ynU{DS8CoFj<|C_|Ks;veMUv) zm+abBlk&y*Ip9<zo}6Gb2nbJKdYbQ=qMJ}|5G2Z>!uGrrz%CuG>!ZFH{~{ILS+T?e zgit5<aWYZ_m@T5NY<}62%ABIN-|iIBv6hH?M&4c%!oDD7v&=O|T~?d_(7Ol`DXa;V zLJA~5@&JB90YC9Bx#qlUs7*XX^`4K?m#OdN)GH22aD_L7QGZmF-s;<(T5(kQ)qVv+ zB1~>MHCqZivS=W^IV1Y)Q7<*it8Kx52OcVKOl<>MUWn&sK@s?p{x}HtB}BX7l}}NC z;o&Nf{DV8TtkWea;@X|iUJ`!6$Bc&+pd8xFy4~r-dX_%X2k+UZbqjDjiBr7hVlgA5 zn4jeiIIlmrJ4{q3ryxX<fQTi(gOU^$5^F?%XABWV+8)*MwXUgsT9`QlEweLorkbXX z=Um?2V5V%2=%Cdl5w&lqxWg8&k)+d*VIPm_B4HEjtG~xN<`%%zX6yhc`GiNwoh$|N zsGW;55zGG7?ik*Ex@kDd{@7oArySUwpHv5ZObXId4`W$Huw_u^2;K=mUD~<R$(X4% zopTSFge-qB3~4OUYm6im+zV!}YF>4A1&PFjG~fd6CSKVYUw^oJ{bCO#c6CuVAD{!E zsM77-C;t4l`LU=zy|~gpnyW?yx?cR3_u?ya<2!Yq0VNOL0p+lJ)9V+z{pF9BXxw(< zmu`RkqPn^1no^tFzr4B8`{{-LA;C-gCZ~tDb3xAS%P7n#WeeVxV3m&)QCgBafU~c+ zdeLBu4)q}MYxVxQF$D8)Q0DMeG=K;d0ES-J6q1ZOt{l&5LBE)+=b7<ZTKe0E3`IHc zAwi%Fuon^~Qn6@fMwY&yz4*?JPIJ4Br{&j^jvf&`F)lnDsxh2@u7CHiw`Wvdgai&W zd_RLaq^&44%K0EgFogKw^7_@ipV(z$1p2ZwCwAQ?_zkD^MPh(<8OUoKh!jMV)GJ}7 z=_-)O*VF_qoodrJlF5bjixwUQ0qNX2flog^Ut0v#wSrKkiEtgXLaU&2D@UI`vd#$n zOw0zk5F`is0IVHfyMEJY>x^(-5n9Z>k`h}~>Ed&ALKPwDx^eK}_M^^me9>IpDia<P zf^#S&3Pj9g;9FL=Xf3x}-%eq)ExaD^GX#N8>KfInJm}zsYG6tNZ)ab%ebWs1v3idR zEGu|4QiaM?ECtpWi7wRkW?zi%>Bb19TEVN;!d`KeyZ1<b?wgNyQcuK$pnmxL%PB~^ zgOZ6NBLDaOTb_ixMjoZ5K0+i5(U?fs2+Eej-?`qka&a%D`b7Y&VJfn{k4nEPcqia$ z!UPhJo!qthX6tCnNa&%88l)l;0F`=-haGMDfO9tRVL3GKX-lY)7(qe;I0Lm(rtcU} zn{L8pi8bqfo^!QPTegLbC97b-PRVHLoK2lSZcUwjRGS>P7lk&OhRjZ6URii86TIs7 z+BPT$oozx~0$e$Upu%sx2#K@ttNnSb*RgT1b&fJ1t0aPESk>ess`3ykjxuMFX&FaD zh|A7qzBrf+4|b9k&^=XA@KK7dv~#>pJ3jLAWOWfoHFhqzj+QEC%7QWuo3&~0`!6=} z1Kd1VSA@+AqS>$zG*T8~&CN3&p`$)*3~}Kciz><tQDKc#aE{f3exA8cc8;F3_Nsy+ znW>*NF{Bo&j-K(`bcN>I%NsxbU({-D_99u|DT%5;x=M#Ib)bFx&rC3<BB54@)--Uf zyTjz^OUdW+bKVF7h}VX1;kK%8`?>1B=yP3vR2W_)BGA1H3C@&I;LInruk!Gb>Uep7 z2j)gwusHP#WW|X_xKMpM9NcUo#y(i=G9o=bgH#J|mRh#*k}g*r7+8X1qWVQn6c82( z&_BxOibqYf8-1yF{vNXk#gnGM(R36)FoiUrcCG@7RA^6{TzhqysbN!X0`;OfCUnxN zI+*yN9LjLFBG|*$FDR$z(=dCnZyH#YSe)I*Ls>4vKvsiBf8ggMxs@FYg9v$UAo&^h zRHL26KP)Alh2rn*Oq+lGF+HvGHN=~ApP-y?Q8pn3eZ;XSKt$YtG@>5~Kvw8jmmis( z3^a%(f)X0R7FV%QVBl9m*EVayolXG`GGrl}ri@|K7ODZ91aDsa7lFG2Xd#noI14?} z98*iGgoP(G&=cZ>@*u*X^aq<>&>xTbVrTvz<qdQe9&`%@gt^cgiGwCIZdX}&{|3p= z?cHZ){XP0a@Df0dLA*W36@eQ|P0g?5dJNhW$SekhPdz~@YK~oxxYA_d{2EzHG>SYC z7)oHCqWGX1B}ZR>l6+>ILjh9)qzje4C^<m1`+GT``Rh?4+E`-B7K>q$RHlz45*1Xy z&Zz6{rBdTlUFihVQgFby@F1NoBvl!#K8bx2{3JqU%%z9!ozBkc{Rm?Tp_{+zV}X!` zbQM&19Gs~y?qwEE=Hz4{E|7={N{mDl1T#TJ*RiVHhCOK1-mG!Q{UaDeB7-v}*YPMJ z!E$6haeaJKFc(t>(FlDmN+Xtpk+nV&wtEYwOBM@QtY+4g_3_XlRXaw1^C4yl!k!{5 zXnz2UvQnItGiJ#{+x95iz@M{Mh^aAbagoJL0qHlLzTVp_ze-~rL#CxVW-j%6LqXvS zTdXxHo~mV2Mc-*oi1P#c23!{_jyhA1Z;o1VS~e>0!PxZS#3?8%oTwV4iuFjFJ`e4F z|GkZ|b%@qTRxhBLgHa5kg<hB+Wis>u!4{HLcnE8uKxI-9HpW(Ye3y=DkuhR89|@`m zrBoXdu{FW!)3l|tZaAaC>4gCXP5}EQf<cF|AN84RP`DR?xkg6tki<Ok9pZl?U;s-L z)E;uInpDikDSd{uz;&5@V=_VyDBHs>$iF0gRP!CEL{d(dNOIuB&XM>MPA-t0WGa<3 zT_wjoZp;Ja47A7H*_r6?a@tXG{`zP4MATNqG3{*&pJvkP0I(j3K5D0#61VDu=p#%q z3dwi6&hVhz@G)OXQV6OWl3^eyV##ak=V8imzppv>s8>Vrl-4KaKMwRqd)yODN?ZV+ z#s!WmJW42zDH4<{uZK^H3C}(J1!x(n>nj?ZBq*_e;lD^4KeL=p5B==R->Zd>d%+|V znV77_R1SarhfdYgE_G9<cep4XvG`UMM3PHOanHnp_pOBFvKzGnp0z{=5SVp{rz+vQ z77jB2XlzA&$%3JW-93=pqmHla2{vJ_@P6+RZlaSC^CMPDmIsKMN}AhUm5!fuPYymT zX$7$NL2U|>urdxvLyjO>EGjMjKI2C{Af8eyK`H6Sa)lCME8)PyCzM451;l3~^4+N4 zLx;_X6f`U0j|v)CAKHfaD8{gO0)F>@?lTQ4AKO#nfzn=!CWz{!MxV&@kPHVToxUW4 zn`=O$doKJ}bBJPRDEK;h0ZffS?1h6tOb-f4n7|4pJ3z%DYAKyZBms*~UlIl^(}}k_ zQBDH}wL^$JGtK46kQ<V?aRQnpIiIZ$twqg&O*0dAgHwY7BaxVp4J4MBNW;jS@mC(v zK-Kth`{sp=KF4%}!Mv*x(FgRGpTCh2oyr}Bd8bgy*%|mrxrI2SgrA!IUZtosWOc)M z<_B;QQVi4j`PAhT^#wWcvr560C8ZW3D=#&_TNQT{VPc7v(8HvZ-OaSPn=EG#mS#C; zH3dgGQWGWT9Dm0l9eZY?>m~_F8_z0os!>m|c19EZ`#)&exH5Hy&saR3j=NF`32bz$ zw0v{>r_1a6+wU~o-Vbo(QljJj)-YItx*+KpPb9QdBzYhN?ND03Wmx?z(voOB+nIW+ zxO+nEabl@I-)T>$*+4YJ_#MX$-)4>&CkhGT5Lm$eL4KD+x3m*QUOvB`87(p=xh{@P zW=p1j(g|_C!aHT>lHx6-vQV0k0I`&+mnqN}<;jQaUc$_N98$TNiet!h@fq%$4*;)i za}3Fb-e{IQ@aF2$uy=j=`S<hNY$*8TU(32MHKA}yK&+5N8Mp?l9Hk2*>QwEQOeK+) zyPeLl$~BLRtHKsFEPBvtoSprtxRL$;&F5c!{`KP<mNyg+WRFQoWlog_(=aumH^m(R znD6<M#C4MxrpAYWjEs*+>d(gQR~?cwsLzWXyhm#gj&IA^5u(PcH_JC4sbf=mrA<KW zWfZYVAewz+@k#vwxkc?H;RPmr79*i<Dr|F9isMkdL$CTl=U)Dfh@%>kwGmL?R=hqY zH8`^iDEr2&BvtFG-Cc>=PC8o)^w7sa=qIJ*=}RFjxo8BonHPDMX?gup<stMZikUrq zjF4cY4_1BCXX=OMDa@XR2PwPR-CnAaO(=J5E!E!PMi*g{vBT}g4mr587B(NbGyeMe zPxp6Ji@3THEI(raWJk<0&V?i<)*y1uTzoZJgfA(ll<8>7lW*?T!wj~3DRmg7xFpF+ zqQ8ItyTR}M;~%nxMvd1S<ca5Dwbkq!DD@#KY3ekgF6*S#LkQwiubb8O!de6cJ+)Ur zT;WY}++-_uWddh60brP{B4Pc;Anqdr!%d{!{3dvE^l9N9EV4^QbSEv`>MC8XY=Acs zcjc@ivs{u^^`)itp~T0^ej&XcpCMErRmhkKT5Pai4oE2WkGk4x2g6UP0I*46?lPbB zh$!9D?qPBbufMyl8ac1N=*}vaXN;Y#R3vqhk)XzA-|+yuJwlnGt{F&{fQX-D&U9B_ zndWUeYM$XN9hi`m42w$2)!?@yP$h1d&UV!>l;MFPqlOnkSVMoyr|O`K@K8Z0O#l`R z9X**YBEg?h&<?&{0CLO39}?jbh2Gm8;00;w`fEn&#{b@3UMp=wC78MDx?az7xeBaK z9LjMZRDAGiL%pPjz}h)IF;NN{iP{|?9Y``RB@0$tMMK6QH)@!@CoAfrz7#x$Pf3BS z0nh;+A%~yo%?o?6J2IDqTe{m@&?va!q6jJU=I1Td>=-X|O)tk;Btow^C=oC=y}Cwb zEjw0F*0eSST~iluM^MBO_5>|~7oS`e=wS-e5~wpwRjOM{G57DOCP;<BuZp`u0b2fY zefhV0ARWZnO~Ujg`X~+B!4PMDEaRYOQH3Mabq<>po_9&uq*zAA1gO^<)HPq*`muG; zb;6<!eYmBNcv<9e-VQ<6(o6g>7Rj>|mz`p-rSTDknZ=+cFJG@zeSA=nCHZfPpeU*> z=)%D&!#oWqc?Na(n-}`hD+oduPw}(Ey^DSN@#5<8Cxn&yJ6Rva?d>nMS|(cpw^Q1H zh}s}jGj1}9FT*-Br42YV&ckFrlR*D?YJd`2E~?tVO^p6SI;EioIMfn7qynUxFj5dd z1nE{obrGj5CgygSLt|EvX?>Uezqp#6V|n&_k>^*GXN0_uz>7+XoBbX>M$M$i+Uj4q zBvEW0S=%yMwMSk+3*{1h5p_wKi}R9X#*#$gU4Gz@**K9Vcg+Wqd6ckhDar$hNL%7B zYLrjYUR)KHGoB!rO{u(zIz|N{767)!$P+Zvt)WINZC$2Li{HtKFBKnDMu3P<$$>4B zDlVd&imN*Mq&m#F8uGVTK|lOJ9#dctP#|(n;727Rlj^xORz{@LD-2aStvEXqmE-J8 zjyVkZ=@|z`i&S+u76p+bx|+DURU)(KY?1g5`3f9qIW<M7?7=$5-=u*eOufUVXFXHm z)Um_AD(R~j$_7%5@I_KvNjYdxC!83=vCUU~R^IptWJdg@PM=6FfwZN8!6ioNZh9YE z(B9?}7(>=w%i)Hu6XGoOsD3Eah756cb@?m@Lu#rlHy>4YGO&dZQ4mIuBZWC5=v<do zI#}OPvH$TlM7@q#Sei16=uMo0!l*Le1Ft*v2zJk?ztHXqe*rc?-1uHhQF7cnv!AiI z$9|4E1QH3%M^lK;QO+E-)@OIOBlf4b4Fgytrxnph*L~{IR1NZ-CLF<kq@<%s{1_&6 z{D2Fr=RZ;|ZgHZ}ZK{k?L6<KRF{Jnahgo;^KyQqbMBae{VH|Gf=Q!LtulT4W$E!<G z?g=>bdtVJnuFZG1=?tWH+shJkyuw<|ly9D$!IA|@90lhrN3(25F&0&5osHRTN=@Qu zdP@QHG$5{93x6d9S!#qgIG8AVq`06NFp@c<GK8rGHxtqa<;`3(J%8MoSUssbaSp5~ zeG(ZyY#H69!P-l0X`!KOZe&aQY@X)k_M&X=erX!1iw$W3*kUSkOG#mjd<+Hmj_z1c zUbtAj&X%4T8MVXNk$;Umy)I>+V+WfizLl2tHZYAH7&K7SwkccArxaTj6w*%NK9N|c zSzprB=eA?19hwHzYOUi8V<+RF?_0GzeM|IVcBAzB<Y}b9ID4z`DOKr3p${7!*;@!7 zH+yTfACFu1j&wYXW}E{DmhgI!Gf9dExpE4`i}Q9sE_6teZ8c2htRM$(7g2=;eJ}UP zfg@Uo95s!2#J8shh4Vo#q^x3{q5l*ahQX!}YKbA+P8%R&2ww?{AHtC|EG(R)W(_#m zOUuWa5}=0yh)&`XiF|~x5u(%$@hFk3B=Dk*Hl(LXLQbhL#MT8*4rw6G>)2}!40GS> z!%>9DL=b`y#SL0EavI205tGJ=9^kb*KUdO9tPiA>-LHi3hFkU-#E@+<-cYZG@s!4L zw2A*xwRm;YE_SBt$;(N%Hk_6je#;B$)(E><;4_NEoGGR4$8e!Y)AYsDoR?ioN3;CA zr&I^zt8yW0CFBy9*sm((<fD5wZ5cfquVVD-IE1wvrrwgOh!AT`f?10*=+4`GNQ*l@ z`@b+}u}W2VY<S9NR;$bG^>yn6!oH?S{iw#KrYPtz5Tf+I19+*yN*isZ4Wp*ELa_U3 zwUwk&<6wZ`tp-S>5>DM96N91~I$T$W%#GDAQk4rrE!YSMFQBxr1)P)h84mZ=1_opR z2SojmtbiRQ8`vF^RVnh=qhF#G!^O88=(WNll8071mZx}EA;S@7!4?&Fd&dT47S-|# z`+UCH+A%IQ^>_PP>Ebqiqn4DY-T|4tglD1U!Lm(i$WVcnV?qc)#nr`CbN%97bN6jS zDCjG=V`Na=qtU(QhnLqC=nP68$aB0k6cGyqkUGExo=jxV;10FWo&$&7g8#yVg<_AU zkPP7Bu$R}865mgcw5GUBje%2nq)w-8j;<~ywzffOoYZvcP)FibI6I@T#3S()KBO$M z?~{OxevRK)eRG1$l<zziEgeuHJPsuWQjlZjX$OK@y(_*-a!V^Lx;oFGK2t0OE51sj zHILA+L!s%$k`y5Pkwdw<-68oV<1@vXn1E0><S9=yxdXctsZMfhK#G^|HO%(uXL#^A z5?ZM~5@nPwE2%Ng4r38(A%&OwsMJ*7*C{QEbwkv(Fbe91G+p4EkY%txoa<{k_S0?O zVfS&5l^!Q5|G^+2=V|8!SP?L}7Jv`m>CMNYx>GE=q*2J<-|^{htltR<A8KJtg%A=I zVHt(5pQ3~usUl~buXh__ea~<GX6sSM3sfe42<X&92iW1-J*?2K4}Lo7gK2*P-HI#( zDNsXcVnU(x%VOY_bIPW`99k43o!lJjD=l!@1cR2GC(3GiF%$q4+~O=5u-GH5ZNN>W z_4&Do7=4sH(OA2!E9$CDI7)yjk_i)FcG=d+Y}<5ZB`S?q)(+Zc|7N|rr@+qz`0$3q z=_~cGH}Vg6&E<lSyfDG#06PKjTMYt_!WRWPPj~guROuFLT7idekK>yQ7Y`Zg9tlNE zGww5|xzZ$ql~64@V#_?B9pH+Rh9W;y0e~9EMMi71x*uyeeK&O`%oq6Z#!5+{C`1@Z znvm>tUFde$>?QZC^<^K~==I~UE}$}nvK?MiuqU+4F2BPIq28fW-m>H<({LeWZZDwt zb0G!)CeY2_gBq0GCf%KyN0D5T!b{i99u7eYl5x0zRtibXLH`n?HYHT(T$lGa%5G}g z+KqRHvqzzScoQsX$fvd@xs{NOq<Y$mhr33}LcPSzrque&a)p)!OiNfNVMbY`81xdM zFDzX%2(eBa7#FG3j_yhDaJ~^7A_L>W+*R&AiU|1Q?xT!I{pniWq*s_^D{vmk53w@b zxE+;nDBToA!f8qtyI!6LRl=-b=I`Dsn?g|p!6AS(54c{un)c$W->J{NG(QBHseYk? z($e4a^HG+EzV5`&2S~X@<KG6rHpZ9G8hm0nc7?IY1-5PfAP_y>GIcKKC3e`!99sXe zIw?gf0!j>bSPg4_O;A&xtj=N$+>n(&d7PTAS;A2U=SNPVTGqYYGx$_B!;DQ>QtWd( zO-8_nBWP79e&><TM!Z^r>z9)AR0>1tXu}NJ5Z>%=WW&{<p)m;vSotu%({6q*pl5kj zF9N!{fo=*u%L*x-dldvRz;qRsL9%45N-#16)SB&61|>Mxl`eC9Kq>|7{9LyBJC$9i z*VNFAP{L(8P;ODTRZ&Pr0Sq@J=fgRTTB9{)J%J9bVx|Tc?S`R~sy=Os?!%GLAY#nO zbJ32U`}lankBY*&FHZB2tw^Ox!1gFt8oi+AViQH6Qsro0(Gn;IQ<zfWD5iH^7*eJ- z(V1!AterSr^wbJlo0vSPc$zU}z@aFcScfI*tQiV%`z-iy+bb!&czu5UHGk=Y!Unr3 zs*4O_N2-5YU0$A_zqzf7o5rw44dcY-ebP0c8%_;*X~Wr>byc37nH#}p=oWmr`v4?D z1g0c`{6z`Jm58#uaul;fq*@1WgX0jm3veNvEsao@tLzjl@Z{0?aQL+6orB3ZXN#FZ zP}|h^HEXm!Lk@PBk?y;ClAISmY$)$3WOk6uWx=q!<4);8nCr;Mo%<Y-5t$aYiHH3a z6C0tr3T!x1PsW+A`KG!s<8SOz9g3vbQSXpUz!0Q#B^6<iV$(gRm58H?vLbMDXvt9D z+KhY_&Rr|82ZyHS7kg@WIhEZ}ZbK|uj{*@Rcsbc4?(AwE`4vee&KYx9fhM*=MJ6G! z4I;=nk<H?J;tdCOhRz;xCdGVrc?qsJM=0iX`V84aWEMyux6YF`M&Rj7M%v9S8})ia zuQjW%jZTE=Dw$}9T^98ZI*EFu*hS>2Lt7P=R3Vlk#A=C{bV{BGyw3-u3*GBQ)QgnR z!cat;oO)~(s@+h<I7kxkeE4wLDssUjaG3*LDWMRT?>@egv<I!sxqR%0c0)HV=&8Su zal8BOm+Ph$ne3wbNaPfR87^e%{86Gv_e(t+tIzv^(Sa4j$3Uk@{zSn^;c1|TP~oGI zONKXX{J%f*b&j`jxOR<jwP_6&S{^geUu4WWP?1IY5$2<OAKDp_9l|^)Sc0A!e7Ez< zP0_A&($7o$1RN<rAlR!R`V{5fByJl;>Cg99N<&hsEp<E`?yyT^6^Hj<;i9%rxC>&| zW}w`7b6f2%RmwQ4AuN%Y)NUklE9C>}nJgSfOB0DCs@XDfQx)+I2jFa8j79}|2dyOt zVdHE801WPs*Dh(+r1_EZ2Bw_Xv{HO9A?6JtAY=3;GO8~Q^|L940+3*%su*X~Du5&c z*b^QTv|CgtxniGR?_BpLvT#|c82?d%Wm|DfZW<g?_HK&m@=hu&`RMmmn2_KPdbBc` zBI`|X03nonL_Md@W#Li$vCz){^*2n-71ZAna|_}`B!1Os$+G1|x9=fa`{@D$rM;BH zw*{ny_JA`!Z{T{RMT0wJklZkcTEqh!s=I2n{^Lg3-uzAWBnPjxd3EhqXpKXTPtvZ5 zxZ(_R&dx4`ml)I>^qlG&OD`80{KrmfwBbDYtxD3;A4~&Mdnifbab8!6RPJj2w&aGu z_~}8w%Uef-o)bor`x!|p%8?G8wjKaR7Kh*f)FoT8iUJ>dt4{OR^YhNya?ZU2rXGQF zzCtn<WzCCJ0a{}z4z{|CbwmAFH%IDsq1fKag06s-22eUj1QTH0#yL8=XY0$g@r3B- zrIc0(NneE44ASOG5?kery5Qpa+e93>@4`DqDkCMmE4FT3Ymc8SbCT&SjJ&TQp4tyl zNKda(n&Tt6!OfMD{SsEGH4@b^W$v==ntN#{KS+clR1HNjq|qU@R5uK~60V+52zE}f zJT756B`F2JSVTbp%`m7hA8LkWD6GlR5;|K-tT)UZy-^H>x_As@f=5R|=_i%pJ1l#9 z8-0Cw)#NRITwnsKr5llG5TqfIrBnzIIU?;<+bAI9>bdMgbB8T=M{TS3qO(WP5pcjl zpq@H@t8kEv;~`$!n4)SVp?I;Bjo6lq^W*jX`8kgJ^Yf2{W#s4WU2&I0l+(MzVfnNC zxV+xUk844;%U?e1>PCLvU)J*DM}Ayf+)yc8{<Sv`Ni0hKU0(gv|8-aWbSu9s?k@4A z+P_@D*HFp7KG<KYzjVJQyIbF_{-S?<0VRV1H%b$v!Rp6HVd38w$ld0umM?w0_)y$R zqd#7h>Ma*Yl7fH9KlmHTAT-=J4|l(O@lI}fBk%fJzse}qN)>UUEiJK@@x8BK$mD;) zv|F(>_msWo6f_$RMViQmB7YP<)mT*4E^Iw&Yxh;vq%pULaY@mqKbaLM3A2Y<-{;=Q zNZ6-dzp#HBjDUN~DY{KzdNvakE>O@YX29O)x;^;Rd|!vD+R${p9Z($1KD6x=8B}); zA|EaYn7&C*#FXMN>GFaMo9yzJ401r9%KF%PFrkn36PmLRzga_44jh$LOqD)W%2o+> zeO;(v^ja9Nkk=eE&@uqh(M5b!2-uNdJ|45l^;NedEYJW_GC#`WFefz9$$cvkquq`2 z!;?TpWjeBCYQH7NN-LO8I7%^<<2gd$_i2eFcNiWsN^0U{rOB>Z8ZS}qv>Wmy(>Ua1 z5@t?N&m|fv3b(bpG;Nc0N#m;3NqgdITwZH(;s=+z=q-U9-&eUxXcR=hIE3mH4LHja z7{{=*Yu2!H-KcnG7_>=t!VZttEpBKiw4(&`37XSJV$GuYm>JP~dbyKNHxmE{NtpsK z4%0~0N{~@3;NeW5k)j#OfgwK+%!M}m5`BN7Z=dGr63j#i4hbasZ4<|R^o?mGz3+xC zLjX(Z$2#keQW+@bP~pOlP<t6V!uY0Fjw{LNyxp2me2|0pC4?~joOCe)niL7f!m!Ii zw|u-ZhF3eOVHe%#1FKSl8WurC9quSVjwKCB@D#2&Sd|*DXgnWmi#7ID#Y~|%$)PI+ zY@i~JUHVw8uCO}_lvP41lo9q)((H6tYc;AAgOO0y1|~O&f-SM&wi4JDD_X9oBthf) zV>pjCWfH+)>_zkRJS13w_cQ_K8wx63UwZ5p+yE)6w%=0rjnW1MCEqY{y8!8dJvrta zdOcZ?&LWvE>D3jIr$Tf_B~I*MnB3{PyF!L*{g8i({0EeGGBx}fOd&Hg<DZg~@;~m2 zy-sXb($uK)3HVg)tjVP0C?z*ya>U`rrak(S%mgkj$y(LySxSm38_cmOeE&PPv{poK zJECF|NJs>u(507!8DUlT?3{lBT0($PBsoFJ(Nu;z{@}-4hZDJRP$|WAN%4x(7dyrZ ziWZ=Q(?a(le3&pc67>aEho@Et`$nIvGdV`T!uuAI*Uq|yHqN8kSI)Txs7UbQ=1V>M zg&E<v6?n$#asZDX#tGIDiX)n`j(!eW5yOLbA$tb$18}>j)hUI@OQF10SCnEjTsMQ~ zt-higq+|nyeG`uy-n>l$aAqrg$S^HcXLz;>L2Hw|3p_Ut3sH9LMS0279c4*G8l)Fd zz!4f961WFP8HoYQ$Ls7^P-f|_*fc-Xy#lM1C6M4i%`~?#yZOl~QtgX4DT<7O@#1S* zS{vQx8BwyC5QZ7qlZ3z9viDC;R#g9#&!F2L@QM}$5k+XAOTf?~JfJ4UUbiO1WfEC0 z6jj+(QF8G{e{+4;yRBCb2q#&L;1_x*nb{4+xhYK4!w%$2qF0`u&wXfqs@yo$;;30K zGF=Al0C|oN-h*_rwCuey(^0cet!_mjSOiYVu~|VW8nVB}E$ODZ<#0!6z^Rd!R6L&D zihVr|)D;ariq%k?un4XZh}^+Qk(N{tfY4!)<$;@(zuGsmxr-sSop7q-y+Ji+)}~#w z(ju?#AxAV0{SX?FilPO0p@=$%?7p|!E>+vkHRm}oti(KpHC;kFL}sB<WQx3GoI7iJ z>8rDnKrcG?5o;mM`4XH?^uC0dho9Q65K-sDhzhwe>=LrbUAtm3_O?s2BXIJz4voGV zg35}}5e~N)vl(5>F*Q_!HrS-IqS}ukPQAEk_8%^9Z(&rtUERk`3OXK!b*vwZfjK$c z?c=%)nu4Tt&O<8xn0UmtW*~&1mcXnkA#`uqQ*rN;cZ5){K}awMDh_mfY7Ho|B9d{) zfg*b_sH+HeJ7cTZJ0{}C?#=0&ApL+cA3&ZL1i*E5=I*E;eM>q$O#&B`Sj0|2qhKhO z#X<K7NZb&=Jd|E!aZs~w?vegWexxc?xSgh)0`o%{izFYY*AASLGY`Wrg;SwMB7i$5 z)nM-H+Fu>FSNPwVBwW=A;=J)-RYYw=%#NkH9oFc!X(ZG_r8V*Odz|_N$Wl}?xgd{O zM&u-NqhBoVL2l9tBQm}Ub_&pdI)jwJR5%#Sm0?7NNvb7l6CXMZu&ijM@4e!5J^5Z9 z`7>b9Vm~MNvcS2Z&kW^`9Pi5_X3!BvcA$PMYnl-z6(S6MBB4YxQv6u6b250+xDI4? zsLMsZ0fCgjkMn$fK8MftwvLp*1rv;I3^75q;aTb}Dnsc4$bx*_tGu?v;7W6xmGO+W zPM4L<@WZE@1}<!#iAr$Zh#@R2pibeuy4^h^CbFi20?p^8HH#1tl~MITnaEtS>(~8K z{}ibO@N|*iTtc#oe3>2E?rT#0uEoNknH;YLk9Z+Y`#2SDUUO~kd(Lxc60on6^#F>t z<-A(d4J43pey&jExSKw~V)Ee!esu~pp$U=mP@YRR48`de)P$u5%r0iV#PuUiV`tQb zh1d3)!}uk$ikzAfiO-~Z!6_GKS)g6Q=Ne_uTbHO^=9)VtHmZ@!JYGm8d9_I(FU&IX zsc{yA;WB|exjOf3zkEpB62BdF>a!3ovVQr<YO|kmW}hq;ychu3D=J)o_vn_Jdw)i7 z?vn7A^r@kAd7ZI=k$^a5ICAX8xrV{|S~a(~>dCmuNS=iOoxrX~QXlRdb5Wi=;3@%g z)RN!{dj_OcjZ~Nzx=OUlt-ZA!skB-Y<C$AptFtre$D#>;-zzSeod3J)D~Z529%^&| z88&I|gy9z?;P?%GAi9wA8t^f7N#G%d#gkMgM$^5)j;N!K^uh@=I}zhg9}G2EQly-! zF@`Hn80EO_FTWs>dH?A}t%9zE*xQ!B?;8*~*Zf5-s`}!(ARdZ%;$8xuUtR9ssE3ve z1(a2L&(f$`s`KUf8R_I}FI3Z{ZQR4KN1RYpfyC3(KxmA!PMaMkYlpFp=T@9($!pyh z*~$Z$4oT5(S!KM!)lj76XJ;CpY%`kVUkh03RSlaGsrcE+l80dpHBKLCtIh+HlvRh3 zWaXhZlad=rBJ`|H=MKaH2|XCF8R_g^??tlv+u6;V*-3D54?#kL2|fZGlqp5Qw1Yr( zdsBLVfLL{j;*6-PS5a@Wsj4h#Szr2+<wYGUQC({WLSD*4!U=^m%t8iLYtmb1A#U)D zm#L5MD51_c4=>GvNHIB>=9Ruh%UTp5ccmT>1o8!S`)9Kg?QC1UWo8Soo7DxoJ}6nK z2!jywvjeNE`|9jRb-!etboVW+E_;2ry6kTcuP)ycvDu{*!4Q!WuERdc>kvZO?lc`p zaJw}1VvrYbpwMT^ViAf?YtELmKTzZ#wogRj&F5x({Sdf<i(@UfFdlc`u{X$aeE;bd z|IgLMezz0AAUKY&B#R%dg0n)(rcl{@c$YnI)LWwO<y&4wmIu6#*LR`{Csc@yLvhl> zm5XYELepKAhhqmeD^1mGpHoRTLK=cn)@VQ2L#a>#<_}#qz@%3FQahq&2stghFsl-e z1g-+yY{NA4@WMWBqE}M?@9B!rqwdRr+uW$dz*rH?K*}WG$8qZ_Maj879qEKZ!i+Kx ziea8b%qmpKlpb=$!osQN2F-$+0uTI$h=vwjV#Zz2Ozjih56Rt8v-)xzC33gCF|_;T zU>do4zDQL;b}#?K@db6Yn#WTH7bXU;2en!#nX4g@E8L>4qwQdLLCf2Pf$h^4a;i{- zuz6Clv>?%q9mnP&qd|wGB~Hia%8x%4pUP(P+jn;)Am6<$egW05inDYwYvW^9mwM2{ zjsRZjsKyV;>Z2HB6H(od6EgLrqx#aThkrS7C}1vkxLRbSq=FD5B`D*+b|7GrRlyBt zJKXZuJz9=j?c7&MMcx8QxA=7;G8s6+bqUq+c)sffT(+8<MS;#~OJA9W=zCo$#f7B? zKr19(pI9=#bM~29+9vV2du;GxW_{zkq1eZ~@`?y%9|@%DZKIQ_wF;=Gk4oAqm7q_X zn5I{JxDnyI7g!Zo?oPt`@JMH+2MQTJszB0jz*B?FnhLd8bwW`xz=Hy7;d@d?u=&W0 zA>M3is{;p+i&mUTphP|92e9PVLatz*B|c24&opQvs)>10?9IJFgVt0Vmhuzg8dh4N zVuB9>+$sq*RRzhvP}Hj{WEL2;d_vpy!_K^4eZUX(a+JYyVH;n``wxt$0&a-m2~`At z%8;I&_5W63`r{st<Y{^&G$vk|CMe=ToF{BKxnNTz^zk>#unwhATot&bq5#tEMMif8 z*82P3g-!M!|2RLFmt&;xr)sl&M-5D(6Ym~5Cbm<YVj)BXB$C8cl1XCgijfZ%3^FHi z*}~{1G(XZ#EY^#gtD<TKz%w;fUAxr)soZW5P^dh&{NhGz^vt7<F0p1pxnvm&uwO3N zaTOh1)~gK5ZK^j}N4U#1R{+TNvIz?A`21I+*pw;7$!ZwLsSqzC2|gK2pSV?`J}S&7 zGYxaZDUt!3S2AudD@Vz}lp2^ORSt9wWhd}C0+2)9;wU%QCdbSAp~K*x^86hJkEkpa z6tL7&h6LA>fZLtm(E+HAT6W#~K8jnZFF0H$El@QI7NIT$X~BtL3W+m^xGOo5zuCPL zn)^q5%@he2Drb<v0(1fHBI#8{UH6kQ`OYS*(k7jQ4xr#gQxMJqejtVqbM{09t!&11 ziQ_4unj$bRlup6js0`lak#ot84ws5+Ahifs4*@V0gg*k`Qg50}PdCGP^1(5PYu@9c zmzE;hw8G_Z11+a3DN{JSfdEBt1t>Z{hlTd2hN(sM968s9KQ|(QEr(;Xu4^Kek`<#` zu17*UxDL0!0~(nj#wa$!sD3CTSp5y$TvgqFkX2~RI`wN;m6>x(sfQqax&I*YFuc8& zq79t;0%QeG?~#Thxdi-vf#2Xy9nbyYj*Q9fl^i)d{iZd9t)hah2D4lxB_B@Q8a=QK zAIj@{b?Rx1=)&+Ry+Yj!A7ZUic8$1U!~p-M39u=@<YaV?P#!u^q7Y09Zhb0^HiWzQ zlY@^_OPMQ+)BSR|40>UyhV%i9wb)|NaR9Ud8BFdQE7iqGYO~Xk&Sp8PLF#Q#Nfpt* z(&ZuD<$1)G-@;u>K6)9(#3$hX2wHKdx$V`Bn6|pxPW^y|=xQmZq4)|zUlD3_dd25| z{Qh$;sZFF3p8Ipmue`b<5drGKG()q)hTZ)P@z`yn{vy75enC#t#m#^)$`lg)H<HkA z?|KKEIgDQXd3Q~o^3}{KHR;UowG)~ALJ>Ahe{JVMpLTvIw{?oJA5n8tvb`kB8gm3; zz@Edtq{dW4Qm0~e8{RV0RQrj;+Z%AGE=DRkbp!?g=V%MD4(t?;hx_n5><Q6AL{b(2 z!M##k7}^u{jB=i6E>wQ(Uq2ze&(rGjqvbHAhYN~S!(`sVJCST26(cy&6AB1%sM%eo zY15!CFfmV}N6$b<P%^2f(!#Zb;Yuv9mxhOD)Lj)Gr9|<6LJc6}YDRU#!C_Yg_19X0 zYoK2|prQtO`;4nXP<-$bk?;-W63UwzgGa9lN($q3Ae;g3n;-a&*Y)tonpFYV#3Lgd zL#M)<Dp*QZ#R+^qGiv}!I4~6{Q5W*2R5gkrJgFBQh$%T--VNM9{Y*dLJcC-Qf$mxy zfMEh2Wb69dOrD<Q5P?CuM`R5zrU7$3s>yx>{(uDEkajnu37ovisP<UbpwEDGQSMAT ztRC-do11xjZJ<<8B|yqqT*KqsZZlsY@<7gv58EV((eU5u{iQ7aDc6PXlNT)MP{Ogn zkyDbuKwJh16*Sa(VRJgy@j49350M7Uqi?Ph$$00=SaN<z{SQ)~<?uwK0ubT>{V%K1 z!&js)S+9m#FZv`lMF~6I!+H>Lf4ccce?lF>`JhvfTt~-<Rfi-@vXzW$BBlxh<ayAd z7es_&HbZw+da4bPi6hQ+!yQq2YfHniH3khNKL;#S*;eE!k&KF|PLZ?QodRDuW0cL( z%}Z!~rVJKP`<*B^ipXs+QgBvGM~f^ud6BFP3dzKghrbw?b=5LyDm)=qdx_<G5A2yr zuGMZIE6};0DxV5jEJA*uF7W1<+*XKrQlPI@t~ewocPRtTDReJ>b@e!uTKBh9GM!p< zQ&KHHg^w}zvkXjQ1#-_bj&GfmX?$Xeo1vr8Tp<3LeK|q-l;Ed8775_Qyqw$mu~F?k zKiBQmnzk;?r%MD*yx+6msNe=9S-L=lDJ6GHe?v7LwgO=Q)#OW^hCBSK`m8zDj_>c~ zEpE(D$|R<7GIJ!i0ilekQGh;@u_hc{N_{zhBeVaXY%B>wk*>#62pGz1aC@F7ejx!^ zeMud;POZY(AP4SkXQb$+c5w>cL>gwnofUM;9$z4j0(6Hk%gA~D$d^wc&!lAwtuHK1 zxnGBNJ!w8Z)wbC_Ffy~9m_~}ijEFb-Y6<4EC0wq%@#y!@oEoU-EqUfOT%avcUyZq2 zJq6c$ViC}Okl_L-VzA-R5SjNI5fNP#|NY4izva))<_d8WvsTDHsNk}vq$MbUy5jWb z_j*rB=G6H)hG;`IT@HZeW53s|bDGU?-^$u>g%lHWFvxj%tzw)G5iKmMS66=cC4Y_^ zh_e$WK0;AdiB9ejwUq`c0%Wr*bvwV<o8pg8-)yzX^(lOS5DoA{LXiL>!9@dQ0Fp!q z(T1)7nID&fC@t>b5mD4lRP)V}rh=6~NRCy?w7xd;3c>|*Qw*=1dKFAPoGrvm0;=G` z3Lz)U<+Dz*S%<@zhF&%@-)}{-Ow-J914aN(sXmIgo3e-_qOyK9Zd`D#@KleeFyu88 zz=FNT{h&t6hd~NN1&j~@&Ocp>(O#A}D8;~yB>BF!FBB&*TZ&RcWmwfE1U?A?J7SN{ zb)|xR!<PuTqOA2eZ!+h7=lAjfdlT<emDMF-0Z?8GX|0|@{SMo$NLGHV_NyPM{o3y( z4Qvk+Tq@)k#2K&|P&;}_(t8~OImxD$*66*V+T#ao%yBzN<tq~^cT?dlj$xN}+VS+e zx0^%Nz63q(!zKB?`sW2k3d4;DI>?BsK}^S?P}0EuvJ-~Zc9%5SzQ+GTz3wlfh+`$( zRqxFkYwF#gX|@4bcKABQC2y}vgUmr-R0esY)V=8k&OOewri&oC2JZQ#{E+R_Ro?Z| zn5+p2f480=NR2*q>vPKVRoO@idLD(;lgP+n;0)Fa;8&IBdM@YAA;8uw2_T%pWmmvF z3`wV?%kcYO`yA2;4;%K@d*`_iLN#zp)s2$o;|-~BBEdkLMKQZcs$;}LC9g02x{WtD z!6WvaMtC&)rUl|5Kh)+!|A8K#7*>X-gK!F=UtCaP#HlOKx%uR*J#Z96R63LVw<;&K z86RyPA>az3#Fq>GnR=STK!*>WT&TZL$DKy1oc=f)k7(Y1ZG5t|89sSHUy!v!^N?xZ ztI>Wm=qY|D%7&eVAdM;cTEqB2W)0b6jxT9Q!egr%dE~Kz{%I*{k8-4aPv-qoni8ft z!5>8Y8k{V7Qwj)W6n3jMpgX4KS6vl(@gYSu`9T4}jTm<(Wj;*WDv2bsz{Sh!Z&^M{ zGfo}zN&E<QC1LYhTcK0>+;feI)3&C$O*U56UJ{e!4YUZ}NrD_j3z<etMGE$oz1Xi> z-m%5>P)Dv~tV%Q0qf&^3>5;x1(==dsFxjSUi3LX9s?#)Qn0;@LEpu^yeRp|9cLcEm zr4)>{ZHax)8Q5Q*bf|09YkikYgY)X?46dSYDNzOR*DD+BMJ&HjB$L6=I-wdB<sx@x z*fm?7q3f`kN}rz{KhgPRUacE}><|zNbq0Gc*mglG$RNyjUyMfSv&;SNd|eIE5{z>E zT@tE5PeNS@J5fWyCbjQ;PlMYWSE5@L{hRCRiU{w|3XZBmz0wo6oBBb8NMIoeoah@% z-Zb+3sY63~Ls<!u-xc7`r<^@l?m$P(e18b(#3Ac8=7-&rH3zmBNS!e`sgem}i5?qu z${Uxl-rs93W7*@Y{^E|x%46$<(2kP1ON2>|BQ-h){KU=(xGrO}HpS<s=g9G9ITPz( zDQIUuo6M*IRzUs(4?Aqmgox`#0GF)2Q_8kfg7Nn%uOo)U0273QMg=E`#9+*|$xc`V z@foLzG}3j$jW@^^$>uZ+v?Xy0Tp49TJXmN5O~d3nTJt-Qt>dN~z?_$~34}x#p0Gga zRh2p}XKnN-^A*^)xSJk<mW9NdQ<4Y`+>W?U^p;ZX72pM+Qx`VM7K|wr*yKRjqr}5$ z$^;DV(9<wgW1d3eP%`d7Q>&6%P*k~xY?m60Vm!|@RSv;f(Y>fEtR5KnNK5=8cnWcA zQTt2n2lKjF?nVH8VThU;WoQtUfP2*er@0*`3tNfrPKQ`*rpy(2Q;^q#<g7AyA@#-_ zG(?>)L&Cr)rTA-A6a{W%z_NW?T*AP$QPbTVy?u4yVoE>ZoQ0^4`cagIRRed_-Vs|K zoJp4Ebu85m+@YUpeX9*>&>h8H%m5|>ehu*>%1LQ76<d4@vP0ji3n9mf;g~dsG>%HD zZ?4Q^=IDYC-QbR`g;<c2Ggn5Hi85lv#L$FDwM;1uhGE`a?Hgxx&`0^J)d8TfTI?;Y ztJ)WDR&K|d2o<hKvw$21GD$%CNFLcGeap=*-XizS9ysh}jp|FvJnd^kqbrIi$aiAJ z<Vi4+p~UBhw>+jT8aQu4@SVocjh-5e*&r!s`TMw5aCxgMqOaDV!ASS4No0sMtyL!| z9|#O@2vWimLOLPYeH7bU1ctNphLZWH4;r09YB&)Xg)|q!dw6{2vEhSH9SIMoLKtj} zAuj)*$&t~s;bZ%O^i+#^8n_E{BDDpqDCFCr)zA`I)*VIAgVxj&<J@7ItD7`}S+=4q ziuOu>bOfA<z1zW4EAKG&$wiehA<#$1Ipo11SqKPG3q;%ib(e1%>}wZ5Ix*TEKWv)e z*KDh{&U`5}wh`?<*EY3No)Pj^ip3JucsSs<z=kr7S8BZ(r$ab#)rEdw^<#%Y#gE3* zrDUf8d-foN<Oml};bYP6suvFjyk}`z_&JH4P!+HN5U;0hkj1=P(?M;X2Y~FFFv;>< z%D)nwN#($DLD&<-GUM{A<Hq46%fZ8tPC`XslK6*B)(dX7;oYhn9zG9%j(gC))G(_S zA-rUS(%%e`+#jeYtSXAVSOAGLjEgvNS$Z$#+CTgT=l&qsN<AiEss1>a6S7+|<B)Z> zWG4IAs{t&Qh}ad(xca^r%#N1o7|cibv!(|iB|+ItMOcF^YpI&Eb^yK;zoT_=nd;R8 zf0B$74emV7Q^%8>^*tg@{zcT1-^i2lH|2OUWf?O#O^LvjRLl<HYtTSxqd=ZQX`304 zBo5$qipY_N30Ww_82QKe@}{4lcn;JpI1=GRqiC<Tlb$Z4(Ff^WfQZI@>p{@Xj&d>@ zRmR0Un~K`X)?i(R<^<%#D)$R|IUIWQ#)0PCUO=kxVMm46ee*#>blx^lL*OI4W0io_ zk;QX<E&)xUyJ`hn({D3tww#}Tiziv(qMS{*W^-7Ug4f$1JV0LY10)^<hc$>)TtBN2 zp5IFM)Ksm8vjHf<73c$=Cd0Hb851(W3)mjmlmX3w&1*cErxR_-99R$*$OD?cB^QR| z*&KEi;WZGDh@Mq|aKE7?VLCH3MfEZh0j83er+}XV78FuU$yCok%So2*pfX{<e77!8 z5iygd<o%LA(3S+aVID?=2$(1QpRUiP@7CPA4D+*8mZ2O6Wm~})lH%@wTpT~sqFrzI zn9~IvKqM|GG$FpPe_GfQ%#2MS#R7nek|TgXcdpAzw7sGL4vCQm-C1IqjM)>UwIrn{ z@GHi6$po^-d&c;negylg+;%YZW;@hLzrp4(QY;9EQf$&fRy|ZPVTh(ry$6nX1*&@v zQD-NjV`;Kbt6_`%@cz1oZV8x32yiRnOeAgt2NTBe!5tglYh{3B(GVgb+?bP+W3zh{ zfMFSM6*Yu_;h?Xvlfpvic)N-HZOM%j;-I1yoNbVRNH0oid$O1ZIH=!}v|K%40*_qe zf<%QBZ%QWBsAc|^@KV2(uJtC%EWX#^s&LtcaSE>)pfy;kH{hy%JN;Y1U;TC(YUTer zPK!b_5kN(h^@hVl=weoITED4Io*K^ui4-A^94ZCj-chWw5{~$-s$54MsTPAIRSZ)f z{&X1iQk=F13HB`Z!`8#^%7E4)n6I&kz!3t^HDTR}qHT4FY<Myc!^u`lBOyb=iKJb@ zQZ8PRUS%};);pzd+0jB&L7q$003|->|LTD*3Nei=7ZALYiVVd!Y761$4dGfer7jS9 zNNe*WaUqvGspf8iVQk$PPiPzFlAjph2p!(it7|8+0A;uiw$U53k79-u?9*Y;z_0~5 zsT#dx6oycmq(Wkuk#JodT-1>_Wlbm?O_u@_!|Vr=ihMq5i3r4$#-$^em+iL-*o`cb zjo%>+1;>fhbODM+NeAqHfI;v3vE8Z)tM=*SxUO4$`+6n2GgCG;keW4~P<q5LL&2t^ zL-lHwBuDiA>TZ@>)kSMidlCw`kYqkI%}5GXbp(-1M2RoCF!WZQdgxaJ+f-1I7-|CX zsDxOMWUgbFAs%4bHkn=rc6KPJHA;K5cz<fj1&nw0NPyy%=~sxI<;VJ8Mm&+Hc`bE+ z+NWr(tta#h17nL|Y4_J3m58KEDp|5uOAqaa9=RT7KH{73QW%p(C22@TBYKX0xZjxR zhH-AhN|5Eh2ovUoNgV|uTl%E@qP|dPm%Y$k?U$huRPWRYH#~C=jZIfU5~{}l7l$9V z;CnzA<B(DnB$s5w#-ZmWBtBv~=S>-Kj3p^GQtDi)0q9Gw4t^llFis^>d-E3jr1q2w zdAjQ<9qI+Hh?T)VJ3EZ{hu$BGt%O=9CA`c+7p@Wi?!*~)OF!<X*{9n3YW&-(w-UUt z?>;*_{s2)+gmI^k4q%A9${Wg-wL$=@uJj!+3uj$~QYwC5z3<Z8I_F8k1%98J>%RP3 zZoIf9UxYFem9zpHP%2^+gsVuU6AONPlU3FhUrT~(NdhHRCCJ5VDW}{AI>s$vwN)^a z@TE2cNd(|Y>kp?ppJ%dyy&|lrtQP_aAk8d6mC(Bs3MW-R>H#B;&f|M7cG%#NB?{EJ z)26Fj!bN@X2oGZ^#H_%VQMbNQ|9T_;aAQfi#F8MNQu!pU#FC&90hU)_HZsoL)xHxQ zeS!P_7c;N#)k<ksqRSchf%}-B&pelly1Vaa@Srp)VH}BD0a@Yo>aK3UT)ZAAGzLW= zt>Mhx?QY)PQCU^w&}T#LF}*2$UxyU61kqz#)Wr>t1LS@~$wUdsDI|H1kv7D}?lZQI zgWK`t`RKaG=1Hm+OjAk-DFoIcz$O+(?v}?Mx9V;4v#gIz?U84v!NmdI1s4Kj3K=y| zNq(+4HKlb9rbG{=9hCF)Zcw(&&7&qq+bi;Yv#@4JDqG;^7ZgiiBnvMGc1G2qiV{6V zj5cjAnwE}x!ay!uIj)a%QX>Nlt=&t-u07PTsrszQ<J?7K$Mo!s`ULb6vP3<xUw;0z z7))!Me|~Z;9Vjjl7}>(Kfny8qPQsFk4s_I1ef&M$$P7o}glFJbNUs_lKBf}nvVhx3 zXC{4EZ8U8*3<wwn{dj8t?;R3SPn*&(+WYJ3j?#zB+BK@G%-9#*Y*}7mNo)APMZrv} zxug!eCT(P)rew>bg;0x`yq2co)V3F2{oYQ`1f=nYfz@VL_N@FpuubCXeN+9kI#yKr zjDiY`Jy=uXpD0VNfwtVnwT;jTK8hF_(JDRom8EdrHD+~SK#7FZ0Q1NNgE3xcXWW6A zOqx2HRM1QBu!9HE$STiu&V{q`+`J-Lc1q}UOK)&09i7`$QezRe=QtAHI7LRM^LkJq z2T&ko8BmMK5oT&vxNZAkck0$b`XU*yKJ{1v{NCCfrS|R<raCdj<oZMueM@0Tl<I5q zL$XAWHDs!HS{vw@?S#uH=PZL==<@EOkZf$iNa$%)28UgPDr<-edvQitV<&AnGVS@! z>#0}|+JhVo*itJJMtYfe7%*!o6e+jTBvfw{GAxhUc3OGSG+gs1-HFaPqd5xwCA^?f z6q8?qR(m9#^mVu8e1klEVlZigkqoCYY@lTNlC$-A?B;7cC|A4N`+f88zKik^d9$cB z8Lr1T&Jq}#;GTv6E=pu^osP)aH$dp#mGDp)DgJ({2g4Xj=#lEUXvl|UuGYo$pWWCz zBlj?Id	L0ls>eSlEikZ%m5UlRSYrjA@YKx7qp*yD=+BU0Wa6avJ-jpX)X}BhVWX zC^T`Odd5&)<Jx}k#tfckW5O#Y&LNy+6=gV7mEqHEh2YqYnNg6pCX0sDjL2gmPr5OK zlWk0r{Q)XtyHXyipn%UqHfHdQ8<Ut56kkCr7>1g<T53}n&+Hs8m!V#(K?MQf$y#y( z8%6GSI(+Ave-8KR5gcp{mOMqWDO1e}6N%dX)Bw)y?N{f(DuAZS3s~Dpb|g;(1Uxzy zvQwsL5HauB*C1}jHHZ70I!=TVSEtmXvj~<^v^vSCmP<~ea7UjIp}BofW_xGD;wuol zsPS6rHvtC7N;0Ai2vFPe3uxla4YTbc(X<CMimPA1jQq4<M!)u{JJpaMlR*6@62Q4G zFVPde40wZnry{G7L?);(flr?j@V2?PYH6Mj(Uw6=?umw1Vo=or2uBUEbS!<K<AIRy z<GQuF<9x9AlC=!xL5NP+K~D%-+un9ZZB$U$5$B}Fq~$PB;GLl6OHF)BFi@*pUynpV z9n*oQ1)Uw!603i%qsqLR;#!b@!>mZ9gpv*Yw5YNpdvR*mSO7(PhyhF>DIyyedrSuf zX%@T;k45Tl@0^vlgHvwp9I!|yxL+tW5=adWh@(=@GC^S(&-STKg4vdB0&e+|%LZ|l z?^B^L)h-63boIb3&J^1n+%D)_+*(u-6?62FuKgNH5==nxGw>>ETLh4Vlxfi7*D47G zh|{A-IQ7nxt#c$Zbg&Ua{1o|3Mbe;VhExH_{(th`gvXBKO4F{NA`FCv-B1^DUup;f z5-s%zmMx7)%L6n97rB!6Q&rt^-6~S_VE+3&Cn7R4a?e`}Y5VJjC5o9hGS(AkeP4m= z<@fXXQw(3C`nJQLjt%pt+NiG!U1AEneFX<_7--|}2{;;BUQS}G(B0)efM?8~pvg>! zm0v4mpecq^(=!d*Qcy)7ISLg39zlWP?_;41w3c2{%hna@Zj9+Z_#6|ls}fQ~U9`qw zANWo$?MM%<O}3b)Ct&gB;H>^SqC73@&<7Ycgy50dIw5;Ljfz!&?Byu+XX`9&$?e(N z){`dh00cx-zYI|W<0QkAw;_3Fb4Ts{HIbe3$b&fyMd4UYK)#D%iUvJ5!l%G8%lUsi zb?(Hc;P6iJIE*VITev_uTPvvvdSmxa?XtJm4i{6d31ltgj1Y#yY<{w1O4z_l&`W}# z%6wnI0hyRj=$N8{ACcz8RC@u^Bg9;M|Ir`;a7Ytqh2A?Z@;s{as5bcGjUyHk%F?UK zBm?6F{0S=$^r1dep%n3fBd44xtgw#NFgJ8)GrtX;rAic54%Z`RC)Ky~<7DL2-X??% zMKkmyE{2q;MSkRI4VyG%hn(ODi0v>1QY;#fHYm|DB0jEQwE!%uEWui%Fq`C=9`W(- zey>f*$Di}Ili+`Y1MUDhDtJ$V_As5p+&|Qfex>f8Ub-Qf#&ty!VB&&s5L9TqT3YlN zI*eS^ZMHYyCr#HAhLy;NhBhe3MGrZr8`AYmzh|@E%;l-wu`)-|-8+H12~n6cus#`T zcKOGuBVPy_HXyueaB6Ww;U_L7&+ccHpKX-vgCg+0xaeDa77K}5hnK`^_~ylh{^-Sp z`s&5S*U*3+kKYPENT<UrrFC{GucS}|Ge*&1p25Q{Tex>?ZtmCiZs{i7P!Cn&yowpd z&PfL=95g?;6r2jV=Hk<7bJ9&E+-PPRHl^`{Hh`n1rrFmzM?(jp+b}AFur+2Iu1bBE zluO}-X(??qQ$2Y$?O}uOIOJ*zS!0k@1b1H_HobguQ#2jmTl+(bw_$gaUGEXJyD#tK zoQxg*VY<wp!Nrn)pbt2HnFDzNf@@63)z{bNXa|CZaJ+Lpdj}dHG(kg3F=`hOHJrOs zc*U;w!;i1N{$cm}%^!aJ%bR$&!}Y6p66zo*(dEfAD?!~z^yM=8^u*>@*S<LbfY9Ps zCPNdWgMEe=5`#(}PTHAT-`cwUx-hKM#?mFjX8l05n_}xhCLs!r4N7eBGZXgI9;4k2 zT;q2$%PWsom$#-C9*Zoe?33HjPzkE*cFyHuAD9wE;tXy|2acBjgjsc2Pwcc!U4bYz zg|-3jFwTHzz3!=YpgxQ-Qo%%sVMA;`zBZ-y_Q=B&fNTtR(9GgeK#HGrd+6dAfy<C0 z8I|0rB$(8-BjXRGerj>r?vK`yov5`2bCN>|>oPSn=r1txlIet?Y95aK1Fu!){mb@+ z(PnAe-LO{(>Q)YDE)+odlJIYbv)gef3Da;McK5=xZCg<029sA!mKl_WKKDT1zMgBf zcZ+SF)hD{f+~EHD!)<o6JKXN7%cFpqd*A^T)I?Pr2Y}Xb7WH2-!e)C<)xhWP+b;iO zVW+IFXk7bMk-5-qLiJdPuEI^Rc>09{jPyV;6oFFCiEbg7YOjpZDD|VJXnb@d_B#5s z_h3&^3?YBuD3gzm9~j6^TT$%p!{-C-ftwD1cJ3{J&hVo#F&1c#zF(ef8?<wJip&#$ zSJICH(gvu05e&zne$dJU);X*p?erA=Fmx}HX1ye95Mphg#-eL=LqaP{%5MQoppz$= zz!0p6nC5$G(@u++lnTQtq)AMmGRrr*&(tXNQP8V3S<yHp34nBA5F{v(`38dW!tAb2 zhmVn3b15dID*zsiT6Yh$zqMRmqChV-;<3_dcJ#KoeV>UM!s@XLYta8lW+ADk3Q^yd zelT@=XjJ}I-Z*Mvo|!hY1bMH-hzcZ?1iD0f4p)Z^_9-Bk*vNQGsLjCSSs!wJytp8h zy&4QNu<E>O$|~fQ&93f1l5zmkZ~|^ideMm19<vu1uQwle*N1C3)o(Aeo16XhTb3<N z0|6Nm2M8Gj0&Y6--V5b`)sT8k<8lNVI9q4{$)nFHXixA_iXf7SnERFIA3t!V^}Dho z`b&4DXrE(5Y80hto+rxZ^t+RdQ&Sbl`!obn3gCn>bij!ZjS1JiJed1cd|N?RSx67i z^~k0}kB6!q#%%6a^K9_jM)_3tiwU}Iv9s*7ca_y@!2`F^1^N&sRpe!!0}5!tG+2W3 zDZgm$GmJlm4ufoxkS;=cmjgZvJ4rh}c-ro%O&Gqe*QDT@E4->xA9}1fj7Wu2FqifV zJuY9Ltaoo<w%)sus*Xqc<g!NOIVN?G*D4zCi9c68X(kCgguC$F9h3yTOQLo_PN`qQ zHwR4{8$ms>-wh~rxOKhPgqNzjule&Yk%3eodA1_?GYSd+gHXhW%sR*?#y<<p&qxu6 z8Lh%W69kfWv+}bj5-WKx+ZK)2%>`u`VpxJ>oFx5d{9UK(Zg6wB6-CJfpbKDiZ08Ee zR7~~O`jzP`nGKHbMwCbrbfRQ%rLRHPS04|41<nl!&`|S84o4#!!tC}o``Fa;w5LK; zlJoQ8>gN3Xr|ec}1Hb*7xJT46_~y%dU%UfUgWxDIc-iVd+k%n%FsF`W;x(`O8^b3o zUxNBklk@`#sDTQIBbA1al6!v6nw_7^S_8<?uJuUDT5r8MbnhKy2f85}?Wle$WO%o- z!B}OkU(Cah6dwv7)Mm8bk!gu7`EGrnYyOw$(H&vSP?O@rZ6MSS6%GhKoa&?W<qto7 z+0DV875M(<eI$GR%U62R<&6FOlm4@*ljwe+CvDSo<S|-0fL=@o!5x7$+cf;((Zh$D zAoslhn;zV^K(cgJh95k~@P$+&@f=jkJb{l#$MRF{?KUnp3S!UCf2o!j5hXRft6(h- zmzNaLq7~d8uD<7yLO^Z&in1?LrTELQ*pTP~5d0Bkk<35B0>&(mr&{e|172Lnl43iz z=b%>=+LYZvmdmBdKIo@<s0Jw1`St$he;kf?U4Ff@IgJ-$7BwjP8^xqoxqbw8PYK=$ z2gp1#rmS>a`m0M$Pw!IWIc452E|~X)NzmQ@6tOmgU0ZXrWQ4O|7b)B-M*UJ1h-${C zmuYn|8h7x?`m?<~UsJmN?QeG!O>6)4D^p85+-nl2hXWBLKY*9O2m1C*d%c(DSkC35 z>F?`eRR@s2nDi9LBnaLH9BBT2p<#_sJ3VU?<)#aU97XJC3Si+z)O*Fkcii_CY1{g- z`%?JNj)%+lm3^bg<cMn7DHu@Mjow<d=U^y`s05)DFZ6Sg&%3+XA6If38*6Y+k19ET zye?Fg_l8o=R8?yp_yOnJbMgIDC|@Kk;C{n0Y@fdP-TY4P6>~BxI!!aa%{~bA0!DK7 zp%tR9bbYDosy$3KI@z~;84V3q-T=G=qL|ca;yJpMh?07~w3F0p$Q*h5;^IFq4|#T} z%+Wz7Lc0^9ANW0#SGs^v0RTNqQ5HZlglwhW8w;IydA1^}WUJ`@_%b10I~$W7K@|-^ z`y$z*CK7L=`u&||DTj%Q+i0~C(-^X=%o8SFAmotG&BOL2i!s<5FNH6Gz=Aq1a<DKZ zj2W>wREBbbrLWfI{G3sv$<0eDQn7gmxsS*()&l=8uxKI0ie$9Ip~OJC=L_9?%Byj9 z!H8H&H+Llt`?uLG_@?+&NWuz1qbYM3rfczo4`2F3y>4aY1Hk$rMfM;H$naK?86fJ& zp|06M3tjJAVzRL|f3snxK{)soD-10KPzP9F=sIg(i?o8S>xIP#c~Gse8xvB57E_gw zSD-E^2R64Oe26*ld|22jp<wjZTKCifY_q*5yMR?m-fNaulG_9PgDQLJcXXi(y1;Bo z08UEbB)dX#KpS4}NR;0RfjFBPvlLGo_F_u50!6Vb%jmVGK5UiAlU<Tr0i2a`FQ83c zOD4lRL9@=vAR+k{o)F0l7{2se-ND_YdP66I+=pF(%h64<JSaHg=Gh~@J-!aC4}!BC zrzG5E5!tsa$d(Uw=TVEV=!fhhc!tKz$H!8UOqIDXKROV>NDh*604xllYjG)yBSzsf z@L3s#Ei*--XGYnixESTi(8j%e9oUzkZBlCAgQ#p1cGdUScZctJ)G$k=?2^MyUS@?{ zpfG@)@d+5?krckY_UYOH=Y)MM7wBarDvA>UX;$GtAhr!hCq}z@w%GPfcFP8`b;U^k zRfJ=OC&sr^6F2jH6j&nNDWFkm(waNp{K61t4U|8q1hu*O`tDXuW8;KDUo(yr<3!L_ zG%81;Y*2p4sB)6UyZ~ok?%+-o|7G*AQyF-3=;!0Fl%G$Hg=Qi$IjShb!<4|aAORKi z#G0D@&BX<t4Alv>r=ERutEzWYVaGW&L@A)vv9@x+pbI0Ma=EJx_57k45|HM_)ej|g zM2RNG5w<h75?f~!!cxYNJx7DE!(g_|?r}raV@|`>UR3puEJY?MKh)$$32>*tA(&Bh z@60U9wh#KfDdKZDiG32l{ffjx@+k2l_1@U<v5_5WPlF|XbOz2STPuQ)Tc3XlTLI&Q zpb2WLibNsyvU;?k4~VFl8SW2wd8wD5GFjAb2<ah6xhc6d6>Bs5;YdIS4?;l>NSjwt z!$e|gUa0yH{ir>lb7?s-?;Q`C>zBX^6ig)2!g=jU%9VLGGdJtgE{ziyQu+dMV*usK z2o)~RMPD$_mKq;S_hW^d_K*&QTNDr;Ny%hRGe|@oEmgIKyg{ZxbBn8;I2qPh1vJR4 zOjF-}4w*I{)anlNs7*r95GMy~r5*${`d81XQj8Pjkb<33%ar?}#Bvs;nCkpCp)w)G zYOf$8A?D8YikN!b4N~lc5B3kW989WL@I*VL8N^h^b3Rt2*yv+(QcS(Lew;cfMkJJS z@uDClJ%Bm`Wp_@BjruSvOio(r)jcK-BG@g$v@R<QIGv9lYDhSMoQ5VD<lO|aaf-jW z{V4jI_$mJ)+JpR0CEkge#v;h30%aory258AIIfa-Cl6oz4m7IUuf8Dk@q6t&wCfoM zPHr{X&zH-CenSn6q}B$|=qk=ioc*Hw9&VdNC;S~~J9J!hRZ9vEUHLCpxVpr**l2$` zGI6^0C*SOa(FQ`2>)R<IsU}&IfTjVX-z+3Sp$<s`@EwN&3NnJmLUJ_b`8&_W#6SVF zLUQa1=&A^IVgiu>R1+>WN7H&~qQUrCW^46ixFjZfC`82dNKui(uctYZOaqy)_(y?% z2M@Z8GE!TorSEXMA1s04|0dKdNf`hw17ooyfgkqKkrb{ovIRoYd}=BbDhZ3vN#Ugr zjwJE$<zIqzd2AvZ005J{fHM_5XriQSzU9cqFTql513<2MFZwUR@4xtum%6B8GBmQ@ z>9|Wi#mEn-mLjJQ%Q8sBm!}g`7o^d)tui{JtEVD&K-2&l9~^Tij#Ct=^(BhdM{AZS zEHe*g4hQrE%9C^4Br8i4J$#9xM=w!#&jW@R2(MmD8iY$>(8N7I+_>8osDG@MS7-St zVh2zP$h!#Y6_R|{5NJOBt|!mbPw_57Gnu7<=n(B)udaG^PS!5@?Y>r3ddP4>>H>sn z+NW+A97Z;aC7`|iP0}P=5LS761z@}6jU)~$1cVhb3BDQ$dp8f~e(eTWK=;=Yv;bCI zMF?t1i6+2R_-t1+JY^(VuSiq+)}2qQ0`gu|jlA0BAMYyZTIEZ$0qwOSBR7+-_1=(1 zjlW!_?vRrs`8p#N%|_V7FV!Xd=m;VjLs<RoUio69An=HVr%{0E2g);%4teqd)vP<R z+W(yllEc=rik4D|%rl)o<dbuVlP?DND63FAqz}@8ulk+%EV)hKH3R)l5}lI>kVRhw zFgr{+!6x=dR)cOFQz1!Vl^@G*zrXn!^=)>WxoopbaKQ~6I!i+ZD_qNg10JtLQLX0_ zjp%+18UbRWs=!OZnx{g`@Yy!jx_v}kkJhiKS;6&0r5EQU0S_Uec!nx&lB>0op?zWE z`^tcEp)@pY?2e?gDvts-CfY|0WiNPGf;u>OXRfi7F1=MjVEPkDrY-6iM>nXFoI9|6 zI`Mlw8N)G^xX_S)PFa^RXP+sZ5g4vGY|29c67V%B?K;&O{5=Y&$^Hk_L?<l|Uz%u6 zbtF0zca@SplJOT81<*?*{;G0K{b=r&lN}+PT#1{Lyesk0>cXgbapQYpn*oy|DZP!X zNlQNghb=5~xUj%vQ&X|lhNR)COi=7uShV09$V0cF0D5X7^%6MD5%mP*tIJlP77avJ z;J9ks)Q&hby2mmFk-m#&yxk*7H^^yZlv<=fTOu%RIA=@HtUUy2E06h!A*UWd-OkE0 z@Up*A2CjU*@yAO#u@a{y2a-f0AnK`9!&yuIoswalc4+%REq%rQYb9<62eaG6`RyUY ztWyUQHi86Tg(`%?zQl-9bJ)HxyOBgNm>8GDxDiV^c|L&gg=xT1SFJS9XB!dPmb@a) zdX?S&sx#RsT)@2{MP4{-OF?8Ayd#aJ7Ck!ZFvYNTD&%-w8z;ke+>mXms$^_8xvDOC zo6QZwvIlZeGAcLXT!6=l2a|tWE?Fs6QMEz6N}>$;R)$#ss80cX9m}ROuchRCBKLkN zW)|skF!~TgaGumG5mj%bXfYxB(K6#qsG*5Z+W9};ma;K@_Ov=%P@RCagvj;*9z+F| z12r@8YHN*E2m3&o)?Jt2kLVCP^BI;q^vjT>7CvO~L$u&%&z32x7`Qi7<I<{qknXi~ zGGi$7q5_r#{DRuc5f;|Lol>OqZ)2k+F$YAeNV7?NE=(ajXYSjBKmYr&B8Jxv!ARAs zOH`Hcs%mC%IL&p(W`~RSZ}$~fH$fZvK!$uC%l4z*kt#KW&)}W8(`BNEWKxR*6Li(m z3sV6ely%hF*JyjFUX0g~4GhP}o^1c@quL_E=oBhw{=ZkZ<WgVmRgM@qfK;ClMkZes zeiP<v@Q!@@)55)16>1YT10|PB1+Xd82W!l4txDRYw`+MlLU?Z^##18DvlQHwT#|T7 zJvM%~tDX_#oeIa8bV#47HkctwKHAPhTZ&FmlR~$r-Z;B{Tglj8sDWGgz>>;C5z_S$ zK!CejUth58$^7!0pT1NN)gDrS36ahdVkd_Q;YSLL(Ecb)PqD8|3Q<opKluYDU&wJu zzAaM94^!M45^KalZkPF!Y&usk47zk2hMd(T4H5MMw;k%U0HwY6M%z6l@HQm|C7k~1 z>gG<OxlCmef^45=gkNy8D$$@GwhbrR*Qs~+LwJ`YeL@l{C^ayD5&_UsuY@R#)Scm` zAo)h>&Q#)av!HYO*Nm94uM28QTK!AP0bnc@RoAb<9_S8?$oXf`zpyTZuLQ6IAJ3kP zaexgu(!bOw#`>4~Yo&k9-Ig1MKXY3`Iwq7ZL5YnGP`uGZ^&!N5A4XSf)7`X4#{LyI zuxQU>Mg<9^3qYcxTyP%Evv&7b+tMIMwI|)uZ-;lV@+J`LF$$Hri)#P^oxrapk5K#( zeC_I{|D|p<LroX9>1&PZY`znLtd^97`yqTt6+(r4=fBvJ|J(9GDDywkO46pUNYxT! zY81w<xXFB0gqu?V5X@n8;#`~dkI-Y#NIPAOKuSPaMZwYw*qXMkrWA<IG6ZJJ#{rU% zrU$%`6hQV=7tKN2j{M&B68YZ1sv~nXE-Nf62<W6DXj>ze0_9STjQ)j*91}t{g}HiG zM1h*?#mJRKRU2U*r({8?_m&i*Eu(4e%Lw*ibO3OT;A)1ne%sGoSJ|hnjqAFB1I&L! zWpqNS1(uTaTskzhB1Q}Ia8-~R25MadhoKQ+&HIDU`$WXst17g(xW-5WDqp~?tk3m- zPN4x|vf^DP8C=9BN{n*Y3D^l<#saoa^`FZ9+kFcNV?`9393n@(uijd92aDeihC~vX zJYZ18`#0OksoW$GrwZ`lLTq{NaEG6(Z(F%Z_sKRVx7BI6C1arGuyIB2r~+Y@neUd4 zU$8av3g~b6vG_fzGd3V#MmZNa`HQAs)=Rph`Y#q5chz|GYpat<=_sVpB{Bt*TCvs5 z_j+o>M3mYHM=4e9B(fonMw97#+h)`5woE6MEwT<zc^py{q0iFHPS$&IPiCL0vutKG zaI1j$6V44v9kKpQ=lbvI4!3`|Ft4h9ox)r5mDQ=GEZuh~sBr~)g=~VQ4PkF3v0RVU zP8|j&0(>j5rhue}Y7ICV&ZPBxp}SU-%UxZ5N)MPj3UP3_XHZ>|X4l5f<n(u!-CPP- z519$vJ)qnnQ-PKe&?vNLsu=FxRo5@1v9Cr)PYLn4mQD062Zk$!R-Mpo>IW49Q=)H} z=!53e)_l8vUtKG?wJ>*jr+2TeP7yp9Xr|=tOK~q;iA!reb&OmJvB9@@3m|>749#<R zjMVJ(i}hv>!?5oxpv*b(9&kE=lB$BGl)ov7DOVwt;-sH}@7RUJISEmB-gJ-O-X896 zjteu}9#!k7u0Hzux2sc4&SFdk7-E4S7J_GKsvrL~D9(uh_>lmfgrJHoeQj!C#myKe z#D<fc&f=*UE-VUTD<9qU!(_HR96%sW#tBhd>Ze6fX}7%9o-XQK+$Y_&$37u62#yA6 zMFna=o%9_@{p;VIoLZqSCZ)8>YY=%LLX%jn8gRQ;7Pdw!U-i~l-3TQ~8qik-unV~$ z0ct(qGcf5D9Dc+OC6p;LNNo_ypoz6BvsHmD2axiNVDO5gNZiF80d4EAH|BsbaYFSA zStvZ2z|e9d5Dy0BYJ-=hPo6ikC#DwF3);ooDVOCtQT*<*y(lf@1?NRgyaL2G55<v= zv{Iq}vMjvT$WJNK>byD>*~W0w#j>efA{N~|Kcwo*#Y&)p95yimjR5+n);^8%X0qZ6 z%n*FXAVNAGu3!mx_8d4;8rIsdpQM`<wXiEqNt$5W!qW{OIpi{gi_CWG^~&DzllHFi zdD>eZQ2I@~zSoru^VAQsutF6{;y~i5O-E&d=6sB{e{p8-Pe^ZZr57YiIKrSn&hc1! zTe(zrSPYB<(Pnh6=%!m+Yiq~qZ#$o31+tD?VEv^z<?^n0QI!-`kH-!o6&3kP>rb}y z@9vfMPo9*K_tP79?}G)QtR;e#=*a7<k{M*PxFSQ)aU@GOLm_Jqzg<rreRnNY;=S^3 zcnzdFA;KGmF(lBPUHNxAkzf6;!}wQeYDyyp_TeX0&je_6H(d*3v*vttNQqy$MA1vo zT2rDU2#o2}$KEd3x+L=^*Mp`%7uX~pqk);lcG4H4mc47!Ux5|LvXLlPamWO)cRc;> z`t(2XfFPNRxLydb5xT?Abi#fDVwzklfPR43$A`>Zj0fax8jza6HA^HFq|JyV6iiRQ zTvW6lw6s!P7?Ql;P%Oq8BmOo>peEIE!>gMW&^REO3>Zt-f$O$*Fm6Qw-S7p=kv&W; zByqJl;=bz0c1c~}H(|?0X~qS?rr#o|wO{>_lG?*jE-+{$hZmS7jn`&IQtMA{6$@iY z9W6++iTy;C)e?;M@>8xMVdVxRI}C+1HJW93pOWKc8M%U&oZ@2xmtfHwc8VO1NzbNC zl)`XvvkGv$Er-?2&IC}@vu1yRi`|g?wtwPooR?cu+JOh>2B3j?B4wu$Hosc1&Z2tp zJM~Q~o!Z<E*3KK^mdtE<Yl>KxvdTljZS(3f1W2*5D)pv&zBxF3hlwf!pJ7ezH9~@@ z#VoeW)E+{Mz{!h9#jQdRYSH$#CTMkA6C5V1kTT&sO<f$9{XMj_eQaa><Slgi^sSC0 zLr*M8O~YEpspe?6)3%#Fz;1*GS@?NVK;TZjsvav^$~Yr`3m$lqe?n@QPPo!t@>Gh5 zEEAUy3B@Sffg8?QdkJoMcl{Q$%33Qj_COu?2q#GH7Ag~=b18Y<bo{q{$`rZA8O8r# zT;<$wD9R|Id`g~e|J00pIel-+(UxQY5Ab3T9qS;}M)bDbM~Ea7GP$TqC{mL2yLr+3 zpuWLh4}vIBXINA@?x*w(#y^q(GG83Jg4F%weJg_4K{aRZBHw^{no{DdD?*!*?f#vS zPnI6DzNd^AF(uiXnmKsj31hqUtP(fs%#sq<xihsAw?%LEh?(UvDs7FI!HxPE&I8Az zr*7H(jdDG+3%!WzA);tA0+5ze6>|-n7pC^rWC|^{o!c-hBpF^}*e!y^s+5ih-N4%J zlO%{U*-G!62!x(eIK$v6j48bs#0~&!NqS)LwmLN2D$?~<-8t1coCL%O(+UbUgl||j z(KJildHCo0qh?%Dj7E*a3DsJ%9GZYggLX0UflQ2S%f5rb#bfgWas%CfqDSc0ZS}1A z$>H_N>Fn1BRa*Lybn|6%lBe2RKe|?Z9aKPm3g`j4AkKD4sUFwYb>H2#@V(Quy0g(f zfikDipIf}j#9e?G-!kzbyR}Gt3amkS2I@(hkHZ<!n6s9!u|_jB@k&lDO#E8sy27{+ z*E+fh#Cl$a&l$-$Qvg4)@n){r{vKbR+U2L55Aytg>Y+%L(}9mtt51Uu$CGZ@4RS7H zm)h0ZzXYerJMbzf_oObr<m7tG2^y!&ii{g{6|pEINxi}{n3H!h1RJl`axI)H_W%TU zBPze)0U``9r)+5Eb=&r#pY6|r$UpolKyqe@=Slu9`%iszLjJ9Oa`8BJJ3b<#3_6N5 zV~j5O>=QeF^;3fl*d+J#N4LDUm!C2-RBTB04p6TiIlhwnJ=PqbZs)7)xa~JRbfIog zN)-T@*6?~xb?zav!nkv4j7xIM2^3MaD@{+|^rJ=U^s!TSzLynY3EBapBCXitlPB!_ zji2rB4aO-kFzhKw-6o?fXkso~cK+~_8+Se!=wvs*k_+xEh$6U@Mza2)liDBM^4?y4 zDmy<TG>A_h1{%s=1sS*5`P3*w{j~p0>603y+vEfK8Aa(xO42jYZ!&)Krnq^1$2wj$ zzqX0UrGd14!wt!?zXnSjII^n>2tPVO*@XaLR4xV<n-RNe@QyV5l)xvhV6R9C7zLU# z2_Ug19<Y8u#pRH^N&K&UuGK<j<KjZ5<KjXEhxCMKEn-Ay_SD^VRMcAmvCvx>grVhi zVhXBacm@cMcaPi7?nsBe5^_G(+jjOBI;`aE#G<>QzyabA$f@cvg>K;Zh_5h#Y^4Tk zo-PdDY4(9X+2CMx8IvDyOiExmV(5#2%2C^p0V?JMDKO+Z+{&K7C(Y<34Faedw%e_$ zoP&X&U*vJQ&%y7NWj#N?++W}Sw!7T_3PFT~Cgpg3*)S7OT_wx}SZF%aSnZF!G)(6` zVyX!!E;%W-)X$-Jc8_Hul*q91!zYtB2K57WUD#gNcA4@@=p{)0lhhE8a%f9QYo<Do zgGE*co%62`ALt-;v9(Li5zwzVm!%AEc*w2a#NSgNlU?66zx9Dt2d)a8+@(sQ^Ovfh z3|<CE%OQmw>H+EwE2%xOho2Hj)fM=jf>$F$n^whJ;0ePY20BhBrS}X^)E|k*Pj6j$ z(%CoNB%e}t7b#WL<ib;DUZMt4a|O3;*b6ha^%~(M2#>vj!?J>V{f%J(AxI6>foFWH zgl?$N`6rRiEY~?bvX+#u-BZUx<@LBqV)#*ZsP|S1BwRvhNh~!>sC}t$f!a%v(7_6( z%D1VcNh&fe`3?I7(BcRWl|#}ug1vqEq6uy2`+m5kPoEIIr-u_l_@yc(z(YWsY#QxA zeu4>Ey$9hC5WZ!?pEVoaY;!$IlAebsq0MrJ!emun9zHOWf*8OYg7*yf4poE@H>Zk9 zqMi4JhTIOWSsDoit~mfkg#(^=rFLDd_9i%HcWR@wor$@hq4y<O8OL}f{A~SKx;?Sb zH@jJcqS{-eF2dQBWnlr58y33NEU%pXtSLX$S?<K~=rYnltl?qrj`LEHvGF!CwgSrW zoX`OY-NLxjI$IV#JSk)>m%v>CsB3p=Hg19W76<-;{_nd1NmiNb_m~`*PHG!DtiY}n z_>D+p9&$Z2(>S4ksHWxS9x7a}L#~%xV}OhDi3C^}lzcFFp(v)hNTq_A$1k{F+IA){ zZ09cfwbDRvw3Szoy_5Ms9uxUQ5kjkbEF0<>6}5~Ck|a$^$E}G`MF=%pQ4@)IalwFX zR^rK}o`t8g@tYR*rT)eUv2}tWk<tx#5kuIvadfH-!vR<7WdEkzYR&a->Ek0^dR5Hf zaj3H*D^m(WpqbXTq!KJkXRRyfr%*B`x{1<HF%x<FZ9zYKX!?S-Hb2~Wk(693*dWM4 zOI+&(*m_jy$Lu2g=!NKH%}(!hGT48NPPRKz(V4xi+ATZW`iZ=Gohf+OAai`MQZf7T z8vha6QuA<dp-r8k&S*(*Dr#y(BV_+)5tb5)YFfa%RY?g(`&737)|OV+icA2m5J?V$ z$%^zfb%Q_U;p&?exLYC3pbUzHbSw;(c4$^8Q$i-ec7iRe`kY0P9N*o;)cirf$7}I6 zdl@O$F)ni{!fhU|&!yc?S+crLPQ(d@humZYEH8ztc;t)=tT9EQLdpt4D=8cWfPSOy zie+QJwB9dQfvaoyjLyiV@{jx`5dsMy>k^KVmV0k)Xj;3{yH>#}03697p%m@K751jp zEeJ!*EtS!h{Y`2a`T4FJP!Hq)Gu<{ac^i<mQoPsvtMz5}R-ttfDgsX}A|%DM<;t_z zd#CBuRD%J>=U27@7!mN2bB*JIt7D&D$b;sW!&BZJ&gS=m1}H>Bf(et5A=-{&_*4Gd zz8fQe1@LBwOau~HTs7U}^}ErPRlGiw74Q-af+EM*0dlkgEh~sq@(8Tw>tlg0rq^5* zvtLqjw`&wH5-Zv<O-*Fnb;HNe8%y151tltobnWkkbJ0zs^=o+JJQ(MxPyro}>Rt8g z=aW1bm$-->iME2cF7;cM<jD_*%Lm99RrkSqcmy;ODV510G*y#Muq+pvpTa0xM^t?K zgj#*qia5;AVM{>d6jclZAbtVds$810^KV~Pehm#9CSe73zd+B={>XLFO@G)QVe7#G z;mVc9t})jWjNGsuz+LNy;FuWtzo`+=x3YRQ0TY8FCZHUdM^ZWG-AJ9OZJCz$H(;!2 z)GJU1)0jMN0Ytz-&~519r1pB(Yl7GrDg!zQ87oC>Ly#=#FvecUvKqr4HX~@49S&&U zUTE}=8n(gj;6MIDbu6YgpZ;5PvgRkYSJ1K-n#XpFov|?e`<JWsQ?vG8J%I%!f(55* zLADpJV5!eqw4mBgPb;qKZ`E8hHc<NmYgR_y$>ybQY9`y5)%kk61-R6rQf5y92fA>E zkxC?Kr;JTMlI{9@@~n0#%ne;3kM=U|vz|QD+065nq*>BQUCTg(PZ}mqIh=ue+>QJo zr;MB|alZm|w{LZIE521VeAE;)XX8<gJjJ<56DO2B$2vvtB56&Zo5yu)`b_CIdj~>C zTbB3Al*ew;{{Zk%nWFeWF#`Lk=)64-h2cQe(GuX5EZ@%LE}fg)ZHHIs&Ubg>1&dLm z0tyo->6Z8;r&p9Co;A14;+^5^M#LR0AwQT0LLoqWW?cqfZUXurUN=x&aJBT#zEqD- zF7dXh(aPcB`tsxMJw=P}#PudPgJ`>8P6QZ;GC$_|ra6kc#wg%|>XezPQK2&fH@B`f z^j$+FwKyd1P}*IQ)@7yKEw0p5gb6$i2#g>~#BJ%}@9Cv8Hdo7rQ_vR|C!e7wxL?74 z;&vrvB}YhrW@F2VllwEdd-R@~YO5~-WHl!hG-c3<&dsJuLlE}}&f_YC5?RuL+oxxL zDQ{jYU2|@8rR^K!*J1#gHba;=0gg#yAlseNN5I^dH%%LpJrc{W`8CB5kq38ZRe-Sq zo1(T0)zhYp;r6onVYlQ0I05)CrU1YSARV=8>-_IsU(QquDJoJ45MgdX=plf8$7Io` zu6<)em)dvb3{&bu;Mog2{9tvaJ^fS1t{al4Y{U*XSa6alprkRfDN|35aRBP2<1#+! z{OHZ~F1iq2Hqgag^T1JnMi~0&&IRuF1z$tE4LmWmtsWqgbyvxM0-%$mWdQFo5>AI* z)h}-7Y1H+!Z5*fovOEKv2_Aq&UT2=nuk-Yzij>U+^sDyquhbr?z(&e;U)A%|7E#TA zVmztRJVA8d!7vrnFDMM>jlOOJxbgpY*k4<-sumyqKGN6<D50FV2nue?(OYxVNuO<p zNQKrK!~&BIt5+;&+uh??_bjQ=SGU#QW^b~k?#nztLjm>@Amb_583CPf_h+Yg(0!K* zd=O!vX!L5arDwaZPzAPjI=QSe$UD1rSCd|mB^v?fQKi)T2Lj?eer;~ntr;0NuBIf( z1zZ*wMkt&WGs>v(**WPN50098IC6Y90id7&lGQInu*-w>&fyLz-m^f|(_}~$&Vj)8 zq?`kJAir1fgFs4P;;ZWJ-Jv`V!O`TIO82C+Bs&)Sy)1YIZeJuGZty|iAH}LL52Z~5 z*~g7_etwhPy*oeu>9(r(zfDBIFR4{IKYu0vl5d1udMdpD?=1laGTZ>Q0Deu2Rzn)l z0A@(2==@wqeI!Lhp?;q54QPc~byB7aFRD?U$Xt@I>nsN8H|681-|AdMI-kWF)GGiD zc^^846FwSCg{+AB3NZc1IHuGh=&@^1NyA$;zz9*@Yi7$%G7&#pZ~B~+Ol9PAo|2tU zvWdDZbqu;qgoq}q9_*Y1pfH(M$>3Q94hIlah*fKNEAbE|#A+JgN<ES7Txor0@Rw?W zLrtM<P4MilxdL^&%}0@eoAjC*cU?(53L0681$0$-sE2uCvj((snBssUNV$0qj6nb| znDN+$I_G2S7fjP8WhDT(0xke5YCXz9B!*(Vae>TH+Rj^=9d`%H$P_;+xmI3@8;!_P z;XsdtYovMFo@pPb<Rrh}Uy>_wO#e{j_ix2f6SH4$_ll+iTtE;w83%bkHSu@WOh2<v zK-+=Ig*(oy+-t}Ns)<u!E!@luV|Q_1gXl^W3yqtDZx)*OyRorLU8j5CT}swW;v$s< zW)U7?@TR$qFMEesb;=%w`ip+`MgQ2hgKq(>)T+2n_aJ%4)ZZQs5~z1@S&@hyg8k!$ z$i{EanuonbwSVrC>s4Idm({MgzXjn<Vw4UPdju(Q1S4dr>=l<y@16P9q8lZ!h<ROQ z`)dtsUkeiv2Lkn*;u)!27{1ib>l~OtBx3}RR?3UOwFbW`#JY>Cl)mXl_Li}PrYOUs zDRUju0Zn1-p^~#;B)O1LPYkE+ACH^L7}$64>h>3>xxD5&-ITNuTO-*{@(wbJmAK`_ zMLKR!lazmjqjUUBc{Vj5b#Lw?Jyc&01RC9h54n=tM@6R2?$bhd4P_&tjDR9`Tpg%v zOoR<evC<=;Dn^q7-ia+mdK*so6ONT8&|pCc*%agh<Pm(963gw&AN!Xna^nix=~}kB zlv|J(0n!+Lo={K@+NZ0#$t;XS$f@$<4s;yH7f<WV!l)?H{4B`hh4F@FvytqTlZU6w z<bo>au&Sx)fx<&^sOn?WyfZs{o_C|57>^vSOU`Vg0Wc%L!~(qL!j4%X(xob7`qlZi z9sL6VvhKB<llMt@7t(uZba2l!E%#q+j!HWnYUj-zj<n5Wq3fJz(hUiCLLw0pK5r63 zc5p}bn^TNc(cNvfzdI%kLU+;tbSv7-`fw>}W=Jk_e4HY{hJ!1fPO~GQ2^2iJIUM(f z+=hhx(htZdKnMrilJoo7o1E{}@EMFH)as^O{#lkomG(&nw%RL{5!`JNQ87T*KxO>L z=oMiH0yj}eECuA#LfglS`_jk;CoD+n6zXgaDQrh-I5xG2Tm@95t*aR}oI9`+!Xia3 zM@{NV)S2rOSCkTGxBIv6MB0V8IVgD{W=et$$&*IfsmHCjv(JX>m52Kr34xVH##H(T z^<Ur0e>8^$ar$w0YfcMEC3y;`Bc=0ET=@u(_NnpUD@1kZTZOvyK6z<wD=dQJ{cZIh zKu@Urxq+WwU0GC%ANPN+G?l_Loxt?gI)cJ056xpt(iVid6?Rqol&%lb<6KAERobX~ z2vLAN(_~wZXIcz|R0&JNNJdB^Cba-`LKvtr!Ha00%G?^k-50Mr`R%;y4yR<d`px>$ zrBodQG$A!F0bq;riFUf4QD$~4w%WlI=O%FdJ_|}ViaCs}W*5kojL`z+NOD$)Lqyos zoEQKX$ii0|qCD$OUhort)9@dn^--LFTh`-ZE(EKo(e2iam<YfLC`RDP!ltHFu`^<{ zT2$A2(n^)#baC<Hk*I@h0Z8AK?yyZwgQg0ARe11FdobKE);jF4CPFSly|`!%1f@F8 zc11@Ahd=3hG<SU)F$v)SiCYd999hVYr2Vzw|3RBy&354-{Z<_`IHo9{jh9Deb8PhO z`P=hztusKF#eabiFhlEsUmi+2vbm_2jLD+6cEZr)dn<w&XEAtgkg|jRBo1Cuqwj1} zWX|N9(~c8pgZ4)hB550MMv-{1Ly?C?a!=QnxmD>>ZOJ0T4shuk7!(Tk-*9J*RQ2_> zw$ZX7G4u!-61~O^7)k9`i<aH90@#CQ#q~b;N&aG}Li2ZOcTT2W51X@@c-E{L;+f<a zAz?wKf*Xf3**hk~rcda^z}S%ybQ9=H9mIeaNL_t$0l2+#kK;Wc?7)~q5COL{8POqR zvdpGk62d#399nF;EdbHYl4=2FCC)c^Ri$v1;lHcM@`6L$YH}0lPH?HY@&H;T#4kx4 zD7EUK%L8>;HKKBEQ#KkE)tMCOAu8~U;HWUx7Wc6-uUbWd>Abl=_JwsU+vl76I#iEV z?~6Rce?!7HvE-y~3ZuIFLK?HZCNOtVj0%rsl$G$oXob4}x+_L&mLCt7_lkazJouc5 zWR5u`U=fH3>v?m}P&KiSwB%2e;KybQWNfTFq!<K9E9#^$QK}UEQXYs`Kwk&)`K8}O z#sN&2gN;KD9o53!?>jdI!&G~-Ka`YG;%a9y+%w80L9F6xMbY&I)pcz(ZDD|sgKnHu zLc-3iggV;_153=bH_`kRU@yMTfmaH#x}&@PuC6;<9?oPKq0q8Xt#ln|JNjl5`8Nk) z`NMjWKs7Ze0BW#bn88CER#u;He$cELVD(fS0`(=#Y6RrfWQEx!m975!3LWZ~s%XOi z>G2&Ea=-5G4zk(-+C@cHGA#9ZB!v&{)8+_CH|^-3>*<}NIaqu)f3L;Bb*c9uGcBp` z2#Y1rwz#zYdTo?aVMbO<?PP%b3+SAEE2+tMeN`eOGJKcci~lVG?lU3Ny2waubrUvj z?~Ps)%><gtZ?s;p+_}#9F5yAF*`i2Q=`#BBbI!~8xgIuQ6;YM!%Un(L`FVc0y*+$5 zKYw%h@xyhccpDKX5;xgNPo#^Sc?uC+smccPlrDCUrGKU(P<>KHMnI!+qf7--ESIru z%i$xYOpmm0G9XFFXHD($A8FT8!nB)ui{Z&utbolUs7uN}L{9S>)p2~m+UE#KLR3}z zo_ecd7FIm@?F*|%E2TJsq$DbB{S@YNy;l~;W8u-Ee~^eyk-iTRJ$y?_S}HucDKTNq zm2J_Ey*)q~NNAB#B7{%~?Ngdy9B>r)ds_$VR#%C`Uaq6o4MBFgK`lI<pZ{FFZ;!CO z`LuPY_E8i6vZI9#<h_iH3W&&|9~gA%)rDTPV##%+54)`9pCT&Uv;<-j<-U%DWrn$G z9~(<t{^H`I>9ge2%?;NW<=cOtCMeY^j2^Q5_WZp0SUW)-F+irzjQ#dDRXd<j5{00I zEW#K*Xv3g4vnA#S*_=DAMV>g;ty{RJ@V$UP5{?*>`NfeWUTlF>JpHpqPG~K3Y#ypL zSnQY4sEDONstR@hNgz}PVS9A`>v6MR{Z98(S07@Es!B%_hZw*962SPWipbes|Grc2 z$E_(1`?)*NO<br*?$QCtnvCcCd?LOqlooIZjv4Nh1n4neeAANq>4-0DKo)NdZ8JXE zu*Va}hn|6;F(N$$wIw1A!^1y`pOrZGf88hl`z!wO-@ouQ)n6xFVyJ8PcRQu@Wp_}q zt2iOWJ;Xe6>U;_}brCY7x8%xDo6uh~wgBFv{+Q4cdT6Gq?k9|`&$J~Pb8X`D-EOgO znN$6yIlwn11(sCA;-oTo)Stq~S%CuwQYU=287M(g@5X|mI4EsO@AQTPQ#OFU)Lwo0 zlbE98i%m=UMsA<((1c4k^4OSEqL(3j&3%XFz~h=~3g%uXe|~*(FQw1(j+}^;0_<ux zhI_N3s?XdmBloW%RPS}>KczBiU#KqqS!V7DZacV(Qi@5yyP+;D7u+3j@4omqb#&$H z)F=y=G}pQMt~jc{==3>#G27T4W_9)3s+Vs7oY}O#D>DZT4avsPS7ucN!B*capgeUb zP}Y@4pNKsG$yDl5K5jB9KhIuW?JGdLfImjS8arUjn~eWwKhUe)Lib3i7RPTwP(uNq zaoj(Dw<xUu_dWplN~mWgH@mquR=h#v4<$t2^MbT&h%a@x&^UB^XK{;Mum#=sNClB` zzzB*X6^$BR9`dyliA)BR{vn(6BROH+0h5l$6Vh{&U|Q|~mm-PEl8+;W;ijB6wxdp3 zC)<)rIAe^$To@x-1cef;f|7MWD^RkfyXNLr#5<^*A8zjw@ELNSDFKySL}Kr=%AVlS zRalT!i`h1G*vPZ>T@4iqK^@sc@MH*N&~xjEjj{0D-&vn_+mYr6H9i#|r(Ol$qF~Rq zj<o0Q=vJrPvOz+3#S#ZL3QIVoh#(`8gFVFG&u*gGFRQt0HCXKg<gTo)kL25~?kO;! z1pS_z+At+jZbfkB4uHK96eb5QIeeb)laVL~3Axbkiy}w1JYp1`BbdX$BN8a#`TkED zA6Vl=#EvYZJaPb|0U*qPcC{a9-qwX9wx<^QX1*iI(>R9$DGig_i1v-yS?*6}zx{Sn zSvw@SP-^1Y15pgfP~Cp}#(Mi+eN0H;#;CtT>v~6(OhkdBLu8|ZdPqA<Wt_YRcE-mm z&{=-nSwEn*MxYOh!1GDf5NNvLOQsLnwf2+k-Ig{<O#)_+O7Tl_4d?*D+>#nvpFAr( zypptJzp&VrhWD2a(hhYS;*5&{HHXSuYR(m&hdf<uBvG&FgvtQFR0f)i0EpM6#QU3v z6HVA9l2(a#O|kgT)Y<)E4~v^}l1x_e>T{~oFx*tP)hPep%Ef4$2N8*aP*#)c5rAec z=}~RucIKm#-_)^eyKhZ6ce)kj2v99qzv+afKUrcbfmqxeo}WNI2L{0Q5>xrepUkG5 zo3*vCqqSCL0-3vLUZh@a`nrl~%`8(}p}+J}r${ZVWiN@&&2i1bAVWqqV99cWw<&fi ziB2!o<fdumj}o@xxfQ{(Dr$ogesv;)fzJ`AG{n;W7CLP<An+38Xk<>{A|+6@tqs^) zwdrj)iWv^2bi^Pye5+%~0>~ZUIR=o_b&2nsGzJoeshETNi8M~sV7!8z7D>N>0=3XY z?RXBEV`A)$4RLbjNg>)}V`U%JY2_~vLLgytu>#dYOjFVd+dIaJ5r!&a5|{eNN(2+( zqRs;*T5`^$2E#m4drRYpN^QlP&E1e3I#JgPl1w9lpQzGTcTIlS9ZqSo!Hyp<F8*>? zCqKv^)!B-*y+4TGygGakxzrVQ^c=}JozBlG9H?rhL;fX`0ray@0;fU?kdxB!V}~LZ zNpx0Ew7Y%m>(RZ?*z?o9n5*15T$7Q@ihO<inJ%;?K4M?A8R?NjJ`RNBLM=w-2oW1Q zBYmbf{S#*bWRTtipD(2&3NV$HuB#6(RF5w%blgi~N*`v&`SOeqr1i9rAP+wwl1A+L z<ym(7_Pu)L-vQA*-hHtr*X(QgyZ0m&pAjdyLSg&%`aOt@A9mOGmlDO0^uFWSch_*E zzW5!<4(6wAuYRkDIDd2a?M3^_%d?-}0Rels`U9#!*ZqkXU!MKtdjGfkYUQP$vkx+^ zrB8nKg?VcJ^`DoAJR>W6?RPKFzQ2Blv*+&Y&-a&?XMX~!@TdJvb@pA^SPDx1SeMz& z?V+fS+$-h}EgH$|yK;Yc+00_2H?{@Jv3cJO`ag`#v{M)Jo&rHR?LgE}gBk<@{=JYK zHc2T{&zeT<Kylly)P$Jzqmrx2#HtH3Qbr>HbxFKP30o_<p+nXLkPnxaKxv~?AHy5~ z?n)%H=YI2sKmIAZk?sCRTuQ$vImAw+Jp>&E0wD<pKq64m@Zk2^9>UB3a7+MQh#(3| zww~&{wTZRdG`VwZ<Cai&jMO+jY_jcNo*hZky+3YVQH6edaq;bM`#Z_sx+fy}lV0`N zCfG9<7hj`*%I<l2ruKsT@o3mEmo||3ocV-NQ<i>E7<BILE5Gj}6)gSuDZVzRN~w!Q z+&3Grlt{YpOH$K_c7|*{7G4z476GM!J~D@;J8n<Xe|4ybs*uUcY|i(qca*M4Q0vq5 zsnd+xA*&uBQKTcy0;`_)-+0t&*v7Amg~^hDq)u6kTVu(#ZiuPRZkfa%@9%Ez?*@K0 zx%?Wj)rh|cFn``$*Vk$+u}T8{9?FeDms>S@>`?+Qg13oWG*qLiicuaOJ<3i}3`VLW zXh4?+0*ZqGrO=2fdza)CT&Gk^Xk)^tP=nCy#GJq8j=9#EkoF{oYKsIPsEXkm0Z<u1 z0F<Dlq=NR}DvP5z*K%=n&H?sLAhSicA)`9UEbS9Pqi7zQmR;X$O>%LFp~OGw!_@RF z56HDk;J||<6fY4bit(<DZ^?y*R{IN>B#=`i{*z+|A(2j;mHBEv6Bh5m<&?PsOAf+6 zbYvKURQ9$unf3j%L5^BWKV$BlA`}5kB=MLNNDQqY)y6W4PV0->J1YXt>iUGy-pZKX zirTm0gv9EaT(hb{b*Y1(u04_n^THDqo)f~h*<tz=P1$Tu7ON(E%Q&;`K&Wo7?)Z2Q zp4(AyM&UJt`@N#fB@BIE6m|1Vt&kuGtG(<x9dK~^*YCgk_J4i<=G#B;`#Pe&7gp1{ zB-;nP*>BI<r(5^2-Lt5olPb}hBZ1co0ug+dV7IgC`q4vLMdCnng`i22q82JXz!3m~ z(2mT+Dn(~MHRKg$g~_7V^Q{l>`FS^sn=M2T&0x_aDbaUwA0!TS!nJtT(rpBLZRLrP zUqdPZ={4jvQjLUgY?5r$c0TC@Y~C!bjQVwdDY#*NK{a{`u@NcR%pV(59<+y;bS<e- z#}{230dYRud=z#QN!z~6Zf;OFX(Fc_09SY*B}hmhNkAOG_Yj${uM>P^4az70B_U1= zik35<q!6+I#Ig9Orak}oA-fq23S2PRR1v|UF!FGNg1L&;&Iy`+_u)N|yHXmJuaO}} z(p3oAGMoq{$3h-Fs_FQ)QsRZy3%pivEcu{&@EsTZ(>#0B2LeH}r*+Q<b0rtxd}@~P zkWo*^g9kS~7rJOZS0+@NBHCPBm9YQf#ZsSB$EFqJN=bOFG>EN|r8yj`u-2#-)K$R* zmqmmkq!6D=TuKGyp|sk|uGC&YNg5Qcq@EjkEK!upho(sFy;Z(1lI}YqCFT@^Atr;s zaipTflVo-4`NGtmCN~z`q)$1vK74usrZ;%Wkzayh>_%*L3&dDwhb$_Gour;6Ctz)q z_}C)AV$K9v?s#Y+a?LZ${6`8flzY2=$C6-Z!Eg%T*iQ)(k#BOk1RJ-#B*I8kf_)jB z1aRs!XY3P*ut66r8Afmg(F}rJSb$bk;>tNyhK<{{gcvzzKs%96UpZB#h{qow#KvD} z#EJq-j&w>Fu>RcUr%JJY+iPMB#h2?}V6UNkOoR(-L5xY$Ctb^B09FLJl9&fM2w9K6 zmf=*J+0}p%1%m7VyccNNf<|=ey*zGvX;+hh=(^ZeWV)0NshCf4F%P<6?P_d5m`7_O z*u>-_rAeQ7GmqQ0c6AyNA(z++g&a_iu?-%utH)nxb~S-?DrUGtI5RE*@6&g6zwNbM z4Jj5b(*SKiaOD!r(S=<tO*gl*w?B9~j0~S3h5VW}flIZzeXkh3xD-pDni@a_sK|sb zUA!48v^?_zZPt!70*=zaaUo_FpLboWHNKXj(0C<vm4ss}ilKU6n{V76QSdVw>abnF z+yQ@;jKhl54e>k;9RtA)-qfV=ur~THTtX%GJHLp1pdL`O_+1ZhOItM5Y={#L<%gl# zst3cQB={gIN~UUwnwGgB!Ym;)Nu_JpApe?KSzQ!1FPx#&WeLCx*nYif8m;2Yys;Cu zElMPwEVu)~0zv9X%A&Ps^Np`AN(@O-Mx8l8Bbal7cE2{cba~U{LXHqn;*yCSE`>oe z%N@!%JhmN3oCH5f;iDv)BqJpdcrw}~7+cAA26=xH7np2q0vH%&gn9|ws_$x}3hCC- z3y~L}qu+vRk44VRw)8^(W%CQ&5I?EQUe5j4!9;wSahB9^i+V1yY;tGop{{zi;MfV% zn2>pnCk|i1Vr$J-Ce0Efs><N~1ewfG0hz5FvSf$b@LTz(>)jIeBiy3?j%oK&$0r*N zWN#2gsYX&?drBpEpy1arHNr^CEJ2njE!bA@Rmh+7dT}xIYpI?5jQyg#hTKR$0@4(6 zc*)(i`=z?niquXM|15?CNmMliHY5pv$^fTL&yeW%^hfQQpP$jz+b|}b3n_Pvp>Oqp zNd+GV(a`taX_G~pe|^yRsfn6#oT_D2omdJdS(pb9;JFmD!kof7r7V-dJkTgK^8@Yq z6sfz7V86TBD+mTZ!UzI*hja&F#8k|8JW`TSg_?uo$7@P|zrO8Ce@!$$$twU@$-MwG zfh+}<LZbPq7xJ5ni>sR>|7?hHfz}b1xf*n&lQYx@B#Go2o>}_~wvg4?(yH8WsxlFl zMWByzP%&YtFCs*ldUabr)a0uXMpRl{?F+n=>fZ_;EV~6>=r_<=uN7x#><c&vOOOL= z3oayamFahzlIKzDuJg6}#Ww(|kxxWX?%)%o;K35*K;42kN<Dlw2-A(tNRY=kmVksO zqES#bLlmjba3s)-K_fk3&X;pkfYT-l0mzS^1G6e13|5ZH;s$uVe|w!>zB&8~{9rS_ znZ!6Cw>awPm0WzN{=;Lqu-X2KzeauH<yrg3?rUxB+6hd!`yLZ+Mp8FvVZP7(sbzUH zl<*ElA96BPrP2^!R`S~gn9~NA{SxNoufKey%a*=rsFV$SDRuQV0DiceDJZ~o%>KT* zc|l*k;(z)u>8yU{LgiyMPH)YP`v!*G<4sjeoT#QNk~2x0+=o=}0I3pWaDK&6ZVK3A z3w+h`sc&ljCrxQQgG7q&6EH3i3No0wktF*1wLoe|pHo3M;jJdHciq!-jg+v;2WCD> zAuf>R1!#Pv&tin@vtdCG>w%r}2~8=SWf3+i#0<E4g3999Yjvgx8fiT29dZd_2{kTO zqJWYSell`F74Q&KGx45mXA$i^u4y+Y4IT0h3`J_~X^i@Dau6utBV!q8n^T9Z<UmFa zkpRNo=PF$WpcPssjE+waoPXd?i(K$sv?tU!D`hG#E*g5~rr@^!x7#j3?;xql0qhF| zU<CClu86Nv!}06%r}X_i{L+uQBzXE^bA0ElUBX$MBZ)u5xKiX42EiLlNxl?z>qnDa z>BcuL;=)AA<vfI25PGyW6mhz<Q_j(88EXmGf$s*^g1a4_NnfWcwvtIm-+81Ygvt|? zh!x3k5-ftj(*?;Brwht;DeMyF+4z3d-T5=oxtC|}c=_y333xN-3zFLI@!7xA6Rj@U z!|U2U`=9sKebox`EzaH|2dN(u0g|R%;LcBV_Szlklo`9%{WWgPlFG-vqFPi4_V6*X zO~l+=^y5!yP4gdGa+r}RO_(tj;3Yi4Ih9AJyMa#{xaB=Va}mH(_@-ej#6`I36F&7r zmMcy2tE++p<pK>f(zyFN!2U!BN5&=YEDi&C9a#0ggBu_AS-FZ=yv3)CYfkJmA15an z{})EF;4;B`Zadl5ztbL=xzBV~26&MefuyWQa6{osZmo>1N4U9_q*o!wx%$lw{v`iu z^NWoEfsX2MMzB4h8}u|vWY2)efjQU<7RWdH50b2ibO9=CclS;X)A7taX|KZhj|P{J z^RSBWwUIg$!JGsN9=OcvHdNQB_1jc+_&@J6RJA56x=CV2bH{5Y1+?S>2po&K^X&PN z;Zm6)|5A<E;&OUaU0P(DaC>vu9}m}XB&dHY7lz%An%dJoV%-SaOwL^LxI8MHGLi*I zh@IRF4;ZYOtK+keb-1w3TUpbc*$bF2HLf>uU4qmvB$1(eY)|#{lJz!SOvZUhnmPG? z>fcRD7&VWW))eX`f^#UxNg~N7Hg1lQr+cUOg$N{i4=QJfIZD(oL?GEOZ2N|?E|-D* zybrfJ^+QNh`K(73ZVg<o2cBxKN=ob(7H7qEt`B$n`r{5Wl$In?DLD{QZ{bE_Qg@G= zc3Sm$IKzXs9G~ofI`D~o(m~m(MiBLq$p@=6XahGU{?LpC1Gm-}_oI<7VnXU;-n6Q` z2Jk2=3FXG4_fixklGL$@87C-sF!WKjl%q7ljiuBm{Z!ghYp^bvVKm7SkUO&oTNs** z_AvIVyj5#k6eBu9rU4NN>M<g~3r|ptx-a&1pCy%qHNo+T*e$}s%X1d!B$Z_Hla|&| zMwB2%1p!vb3@eF#&PSr>+OidkoTMC-7ozDoou;>oF}k@Ho9jEyYv2?Um*ordIAaIQ z>kd<G&Fzk+eNt^n8xA9U1&~vT&ZXPe^)3J5sAcN;0RxI<jy_gEECmVI_u>FZ(~5Ww zrP|=Hdq6_9XQ(}d>R0wJaA{LHS_r{8JS$x)YX8*fFRZ%%3;b#zAVWb%(908dq&dUw z_uT*!x%hS0;D`<efMG~pDZzD$l}LSNnw#S_ZG92vqpS_}BTC5E6gb?zpSQWEnr!|4 z$1g7a2VS>J<J6SdwMR|4-5vfzz=`^k3@0?Kb_GY7QgYZ)RUZ@W_AuVL_Z1G&?@10) zXb+77GWOvJ(8*ThUtv4RQqr~xAOE>%uL__=eNn2ftn#HF@f%1jlvWpXIgS2j!h3KF zR-z7<3C3ZFd#XZcQr!RTS@W=|WMUW>7jqR#-A7(xKflZFK~$g$K%A}L3meOE|Gs*m zfz`W3#1#?V$}3*je^a!y@5|rBH<2KDtE-zkA)H5VN#LLW=p-P<DFuDa!(r13BuTf8 z7iY?Mw>sIjPfx55upXt#PxY4oY;R=J->;>&^1nb<g5FYUO6np0H-UAB?4;YhTf{j= zE;XKY1_N2;z{N5x&Xs{}7Jc*j*oUYwZxt362?n8Hs)N*I%-ct|zjTF!Vb1(Oz{wr& zkzYN3g*>hs*0ln^Dg~IJppmfaQk`wCl}ER4T{XlYoiv3b26u9n<ebdrs(IX3@bzr= z`9z1h25>=+3=n4(Xx}A@2IVqn8TwIks23!K)+JB*tZy_*F9D&|FI<?63&0}?t(4`4 z4<;I1)s~uwo7Q4m6PTtzuoJZebQHKws^Xt=;F%E8TY*|Y;uSzHQ@d)Sqw;h^7dLBT zQoo2Y&DT<5S^|tZm6NzGuG>Xu4r&FdEEz#$hoK)iZLZdOORen`9Jml#gNC>(^bQfR z(S+JdtDt=PibbEG?#c@tL2~mWuH?xpR$O25nTre2wR@xiY^ZUB7C}IDG@ztO;lhQ? zs%&ajxexm~D@pG7-IZr_5VH}_sCqc*8^s;Ut`LRJgIz=*t|xq>(?i-K&ONycxT;Z^ z(VG?I>PboV+Cy@2@kV({EX!Y(so5K41)UA7WdiF8RUOi8#Yef=>XPWriPoq5e@Xll z-?@>a6KVJh4$}FLTLK$z1?5iM_zu<<=V{3fQ0m=ctCpB1I|7E^2(~k9RrsGfF+J~U zoNYTODlB0C75{9-mGv!fuert}=u?3FjzSF|rcU;pA<#MSAYt<(Y>fou#u`<xH4~>s z3n;ianb5pMA5#vtM(6H@m0&G5fvQn>DVItvCk2roB@jRw1lQ!Ntrj;ogdW-laitnk zdO#syW`)|i8HG@0>G__C?lfW1#o4m!C1EJQC+OkxbYplYImd0iqzSW5q^Y$AiJGP4 zjR~`QPBV5cuw64%Tq4xEXB1{q00e1QDdKAC#b)aJt;1j_wT31nIr|AH(P|<1<9vAl zc5B;5$#9ve=I4~fo7K@*FFHpJD<=C|tR|BLr|%G<WEjMXm=IA|`&<vYp<1FV#Oonw z<eZq#uQoL34QWx_F1ZH*OpsNfF0bmFtumOE`Chd%VKMda$&vb15~UHAayv|=H<p?1 z?yi{Iwq0NlvOe;nVLVDRuEzrP)C30g$y3o#yIEuO@f0JDrwfs7I|lo8shrZ<#L&NM zVyultVe~2&-CSr=pzS2d-GDuAJ{a5!;6g!_o<W|4muPH_&uxC9!}jJcAc7D)1+d>R z#H0qI*@O0rr)_@wmz=K(l3}us0fHduk}tJ=?Mbn2^Ye3lMO>VS3S7QaPWq%`cLta8 zh;G^Zx*>88J$#v*B49130^Zh8yZLn^F3IKuSqqQU5)bE7JBGeEnArUGWUOv}63^oh z7If-|<xa-jz`T3lR(wr50G90HR@8$d*&-_=0KJ7_8*)?iRg=@G4#3ID9vVtWXm@4T z3y~Eo8UnjY$~g23APV6VpP54~QeEfuN5OG?!`bt%4*~!J2LSX01icYr#HTtha(@lR zzfWWh<S^1mfQ~~2K8%6TtQS7ps(IMmfjW0^62UA6C_-{nWjJ91QVQr%RT-4A(AJx0 zlXsv&4v}71X&098>4vMKNdo>bb(eO9&$_9>&stxiI$INyNDVPmoumVcFA+K0F2d*s z?l@aTSOB>~@)W9jwCn9FFnciy0$l0DzSPT;569NCr9Jzu@$Tu-s@wMBq8s%370>|I zlSdn-!fQiN+7&0SKz^wCU;m0uryWkXEYZdW=2xv<u(eIxO`&X9OMOA{<pzOA7T!Uy zFHv8NV|Kivtx(fy0oET*<rLCsZlOdVQ0>Vd4tIU3yW7?$wUJ#$+7Y$(z%EbSwu419 z$lOe5bK!O`jGYA!yK~b5C5Ed2Hrbr}6Z>O*s<eo#VZRGV+5|foHbBEc^6)Od-YlCb zbw<+$DX}i77Z#M`Zd#O}=)~4RrBIEE+&i=|sDn`6U_K|dF0?yn(~8>K2rMys0PNzQ z({`Q~M_8yA7nGf=G^C4*KOe3Iy{eIU+40wlix1>v2w2!PA$DpnwS6m^Vx(=ZkPvTn z3BA|fKYH#D{PU01N0orwnp-|u(1=*v!{m*GWX1(CAw>Kc{QYO@Z7pPE9z7j)vczPr z2>;d8Kmy&02>S$`6xpMMie8jYuypnP-96w+Z+>{ad-cEK-Ht&j#FqjUjr?@7qT__z zX#9i!_RM`Ewf=}I@I`+L^zQGtMV`46FVB9EP0W7yJp0j&oA0;#Q5VXS3d+ghn#W)5 z6_jF7M-)m?z7)#y@VUF&8RTCHWS<eRy^}xD_dvQvzv0iquk9uT8Hqy+;3*9#t7wy7 z&Z#Ngaq&)+2~a=C_bETE-Wh}a^4!~{yFJCnx8#k3&DF!^hYA3Y2&CS8Amwup#PaM# zb%4Va&jtn-Nbaat3lV<eZx<KOC$g-mriYg2E=o$!0|OU}knEg_?a>5tKHp59bS=sm zfa|@1nFdV=e^r4Gnmh<1G_5+*J8i(~4{t6v5NXhB3m!-!<bv;-0{|s1qW&w-E;jno z{P}jrNdg5cynuZa<v7jByTJc=qCk0ow$yge4hBFhEul`lhmaQJ0`xu~4A7hTv0q*i zQIIz|WFO}E!Ku^;7h=5&2kTKCv_ww`;*$XKQQJ|F?t(?TCVC$GWlN+W?<mv7Z5*d~ zHYAB*gGhPo_nX8b5{e=gg3?+-enb_T#3ChMC-1k%e0k2t+VsYC!0HoHSC`NTm5{yO zoc>`s2BsEK*@RmEq{^kb`|<h@;I+*dg%WB6w^?40^bPsXRkxc92`_{V_%<8>8gp$z zE3IQC7KE0OIf;{2SwWCO()1d2W$K5%j^c|e(#t^fhqWxmjlza)t(vD?wb9iwp?BFj zBR8WHQ^*Dc9w3e_xYDQ98J}KYY?+2e{S=lSFl|8VBdmq!S4*?I!>T14TA8!5z^X;P zAEA?g3d4S3b+b{CnZbJu^n4kHz=^iEcIyGs`CP^U+tvcf%)o{zl)vZa8e{rv`44pt z8lpgTRLnctQ6Q(lpe~b@EY#^K&{-Y<K?u{j{VJEu=8P1p3JFgxS_r@yu1}${j}NJd zwBG~pZ6<3lGSa9nsWXKW{7Q8dz27G;5R-n19CNEsI@W(>rllvGBY;Jk&Nu-sVyE)p zCxm7|Vnt>gvnhmu=u%>K3A_({n285c9nK>4OFjEznr2h9;OAjXrUdahc#Re7Y7cpR zCHHUKY{T|KlBUZb5NwDv%F_)^w;JSzq{3JL8OTDz4Xz;2wVC-!XU4(Ddv&<IgYBf; z(Ob$H74He5C>-K75EdXwViK^5qt}-6a=tR%GyiI!)R}*CC>DDqg%jY@C^qKmmO^Hh zgh-`BjWT<akh@!B2@hX-#vY+5s1DH&k5I0Qo=%};4Jc;UkH>v}y#CfVV`0TiB@?KM zfX`9cYpOrX-|P%1J?YU8*+;NzG_xr~iDPKR6x*UG9+e!{+uQ8p)<&1gTdepBUe*Yx z7Lpf${GpIy@hrIxu1u<KBvnYxVF8ph)iI>wQwAZP?e6i`Zi++<KTujLVIu%iYZrQK z5_Cy8^x4_!$%eM%vasbwnv)|9+oe!#Ly=83+fIkafE6I$Sr8jZh)rC5FX({qLO@Da z-!e$@0?UG66r8F;1xxiU9|pQyk%0?i5j5@#upnKxx<7f2>gNuB8}(xEZlO5hz{_3+ zSODle0=lse@x3UXGN8eWFPda|S8b?BlVG&N7syvee}4Xx{Oh}`m74J$|9MJ@zlVzp z2%oYjEwyV-Nwt$oGPmUa$ipQ!j5|j*2lxzk@2cw;ZRcRb{CJfggwILBP4dS-XIGW* zhD{+OtuOGhTJV^svfX18%EBXm3*4kwOdt`M8hb!kR_OFtTjnoWg6xijzH1gi|3S0` z*H<Z)M`#?#1(4&EMrrB^_EtfZ7$6LjX4$-PW_~PRRU4K)e;b>oh4xE6;f5#%qC{nT zx%v0kv<u>79SN;cO-Kf}mr@?=cZ8x!!;-Y^4%1#_Y;-y?KNGNJav7YgBE<@$4Dt!o z`Q~BQUSe|~_NU_Y-R)~L_O)4S-;-%`Bvl-h=B`j4SU{pGaQNI9u^$M>K!GgT-5ieX zA9k|c&TgOpIh1Gl$2;zdyE81?!|g}&Fa5^Uw7S8Y4~M^IADbRDdFo*DVh`q&iWC$$ zXLu}BDS=k28K;s6vK~|?N>6{hzSK-PPd_0|mprNAlhhkv2#7Kwoa_P3tY-+e%dJ|> z8pyT;4JoL}obiyn>PfGS2=TMOJ2teg1C_a9$Q0J2@2^W;>}s}6PkGiF_NXx6yW7K+ zXg{jpLH3$bsrS+no2?*A$*FS>EMJ`Ml7w!L&h#wO$<Tw2sV}K^B)iCTtmFIbbb7VJ z$!pMGBwIJaT?Zc$04Khr->E0YLr0?*7pkrS@FS^fknWp`itb{U6FM{VuFzM>9PjeO z{dJk$O0fo*DOru)B8=TojdP@iFHH^mQ!a=J8B%mkmI)dIDRTjN4*lhDLv=<4r<{|B zm}6*!l6-DnNDI>3uLN*y@Q#^SwT(bZ;_wKHkebUrYpV#<SF&x#VnfoVw^jo|w@A4p z_y8aTP?|Q_QLfuktL=znqv}9wNRqXahZGEY9C+(_Z&BRj9&W51#KKAr??mFz0Et)l zkI9RWdXZ9qLdLI2JCQDf(x*V`X?mntlZOn#`dlc!!cv_XIX7mRsM1aW!UTN5kxT(= znL^c)r_tiu12br;U2Hr}Vc|rf2cm(bc1h?JZrx#R61%;*kA{MipoNya&E+IQ2O=zS z?4e>HaS9>%8ot!dY_B+J@|gG6ex2ZaL#>jCqqamTRr^)$66tvc3JdiiWEUbJq=Kz| zYL!)`I-6b#Jl#JsM{d}p6h-}9y_fboLDXC5{%GXCq%s2mX8t6L+(>>usaWVB;doIt z5uj;FXXXS|Pe^HHab~mG*&mWhA^S?_X#gJ}l&F<>$;nPOca7dmGmYs1nM$zNca`!R zLfw!z!1FFx`W`6RRDnQO$#FE#+AT1rbh>alNclB+(YxyMD2L5YQmV%Y>^W5>wvByS z<rSr%bRkqFWIBaBZIx1i0X-frF?H)(^wNRm&4<Xe$14rfHE8)!T=1dhT3Rx{L`PF_ zK4Gb#vm!h@I73_xfO<mZp-E)JW`U1Gpc`MFU2@I9_6DF7Y8~4E!&|;4mXCLP=cW_S zAF1$CLkEm!ina?K2JA3ubn-n#1?{?8RJGDW?{kzu&8XL0=vp-<-w0I|{3I0Bce0gw zI)QRToS$n3JjA<Z4&+OtU&+1~<a8!KCXfbS4O&kurAgTOOh>3SPQ>9*cD5b+p0ZLo zdVf*fkOoB)r$OR!WmqHQDEunO;+8A_?l2;7ZM-KVzCIZsU={pR-&=_V9M%mU3vr=y zUpG92GlTE)jC}HlLvlj$ihMNSr}XeUb7W}>+OM>8(6x&m4Pt{wHk22!>YPNI?XVkT zYw31>r4Ev15k0gEfEW}$AeSXviO>m&hfAkWX}a?6gL8doH>sjKbv<sT{SAJAs@{t> znNiqRC1FlB4NhnmkB$Api+`K=j2haYSzpK(?RKe=#0?U8kf!E-Bq#^wfRYfok2KAl zCh?4bZ|29c>FR<yZ*&mKxJd2MQIY<Kx|gdED1BlFiSK530FAdsOL1$%H1wjQGk`pq zA|C~fAR<{UN2de(#(>T~Bit%ZI^T%^wFj=&1=w02w4HXqXphP|Lu|Vu!b>ffz;8a@ z;O#+z8d_;4mkf_EAbp=SgqXw$eNoBe3ZFE{*H={0D<)jtEm$+M%*Z#!ON`1SF3k4% zNC>E}KjRbuhekoZ3riH0EEM0)OwrE(YzSX8Lz+X)wZIW;rFW=bj788XDhHkr*!=`U z5bG#5H^Vc|28am26j0R$>le|(#x*kBFwHJln2wpn7t;i*nGAC$6$s|##YgO@_1Eqa zafbR50p(uS+*a(SC@b^4@I2C3lNk8e$?8nm<gDJe@C|AAz(Rvuay2S=1*%zrR)d`A zeX=_>W=q(|!*$G7hA)}ErJ$a>lsl48=~TpI+rjd9dZWv%+1@vz(4x*O(pe8UFiH@_ zzp9KK{kMFEvMOXC@i#znBzi@UCteg0Njagy8<^IV>r3%%;XV6K{{a?MZUC)3zcRP@ zNYb6Mn~}YK4iH9xolo*I;>c2<rJ;+9MsF8?PD4<{K*_%qOB7(o7G}g~ZerS_x*dz` zruu^nTdjxdYTVxq1LZs25MO=yU8^%a*iOj9I+s**po?naqG+4eFs;Ez=g1rz4q%`! zKV(ZNZ@%1nyGl)rc)3N+IdV|2B?w9)qDODZ7Evc7kWR%{)!n;8dGxe))v2F6lSy(T z-S|%LHVrJ1bFBda7^BX@oGAXS;Y%le#It|TFr?<M0=FV@Jt~(ZOU!<u(F0CBL!+r! z*63wAsn0K=T&1S3Eb2;^P-(G(J(tw?*NP7~lxaH}Z)7)xD)_DJzUD<v-L(|P%3jpA zux&VtZcjW&T_$RWrey10V$vztRZ3=2QW05DeAE<9;8bj$zWALiC1y^0Zrb^uv-3=e zNl_zDrNRV;A0Hk}U1B1w&7Hij{*5kLCse+aYMp8N99l>33634x4fBa`b&atYO7fC* z>?Tf`I(_zW?55}yqXb&?H+b*g3aU=|+v==|UeEB^8Myv^m{miJW0Y%=a{5t|b4c4` zfwleEd7^o}#SVX0VJUO!pfgcnEC9bK;s@IScqHI3<?fz%aq5J$<c}8dwHsVzAM<J_ z{N-W?C<%h8k3xcv3KoP2v#tM%G;LhNN=HT)2bcymQ9Ox19$)vvHUm@i&EdxnL{dbs zB<So1`47Gs!1)1watTZ{c$hVl$wwYzd%87zpdm&BerL+>@F*$UQ|Wb+q}N)<nS8XS zo8W07zM5co#5ML6E7Dgb^aU`PBsKWU`R?_glTKqIhowR*-j(P@Om-=Fl^*C}#Kr&~ zWr6J%jOJ7CfzMEj`UoQNxk*(sYVvzdVpYctBsK(t0G1DJix9h%Hj&TS4C3>5pX4fu zLAtK~_wG)kTjhW;qb9~=&cLK5PCn~-6Oy+W=E-)EUrO0h$v>~M+h0X<`V-7U^V`J8 z?CslXuC3)2YKBN|pbT{f|0{oxRf#}82!otjt(bJ%Zjkzo&o@jZhS0)bpaFAx4?xSz z{Qf{7^2b|zTFN8%xanzjfUF>s<Dr*B0Vy#Aa4jV0VWv->|7%T6YJu*L?*~X<$M$mL zto-JHfA)juM{~CecZb{`k^Th}TNji$dL-cyPXeV6ZB%X#wd8Z6GWxM7?r-*0sf<PW z+8@7s_2n<pZfd0AukUFZ=!i%TE{-U|{sN-ZK7C3_vwYk{Rr3~lJd*GNLmS4p%{&5a zz`nG-R#(8M>v*7ce&}jcLz!ix4p`?9H?_#Q^K*Ik{QS@S^XICTclAyXHxx^wm*>@b z16oj?pZ5>4EG(_)j;JR2i;!To(yS>)am7KJQ;9|LAWE=$@=tIk|M<)D)=93j_xrb? zT)V-*zWb~z!Q?{-zP|+~3nb5aSCxtpr^dfSh@|pUSSMov9UZ*$*;ZtEmi0dO(<j{L zat@k(%Enz?t!CSQ%S<Zm`gZ^J-Q7+LF_l<AHYxmkz?z7I$~^pR^VtM_EJ3hvA#a#{ zP?{e$`<rJL&Fi6Z$Vi{fpZcS^h&p8#rbZmYo)hPIya*{Y^88ava!;i>5LhruIB5tq z*%v<XhnmDOLWcGW3%%R0phTG@_o@3>8dG2^&^n~`B&013J~nA(&1=d!q&TZ2s1qGH zYqwEzLQ`yi;V4mwhk|?n4-ffHq{KQ>3)?>ZCpmAO0=!|Nw$BpIlL9w}sKPO;8G}&j zN(qHdb(Tl}V)LUEH}{>wbSB$@?NI|e0Y;&+2dbn5B9VI#atsQw@Ec6Nxp0h5Hup9x zr~40ejm4K$ZEi6Dyanhkgn};1iI#nPW}f{MY?{WN{HL4$q|p>Ov_Rnt!#zGVKg&{A zZlQl3HR6O7@Lca7Q<Z4O@Gy0PSi<%0s=8I0cIZYh){ufv{v>(1sD$m)Pb_c#MQ1x~ zW*W9GpOR<K2dyxMR%O{aq4bV8u=I}2N@HI?Z8Q@%*^_j&`?dPG)B2Q-UVtV+o|6Yj z4M1D~yqbK7-fK^}5w`35%_iR<DxY$m5{BM{cA~<kDhZ+;_>~D}6Jlx}{sT<O(_}Qe zl8lT>VsJB&?r}{uOAJ^#z9aCv(B*q?ER0;Ol!|O^N`oGM8l#5PQdl#hqQGl~FMsQ& zM>*3Zk8Cao?jY&|p#Q1OqF^J+$VRuS*iNc2HXx~h{sz#YOVV0dLTA3=#7`JI!h=qr zpvuz{q`^sJhpHP13`qR${#uH8C7pu*`iuIHb+zal;ph-iv#_`g$>#Qu!dj^6xkTLi z?6N1~$gqdGg(xjJwbb&k3`!FAURxUYsRrdgzKCP!jfjgQ;hGD8i2?ZtwwiCxnuq@Y zQ}SFQ&Ih@;0B#Z{VzRy@DZVdfPF?Xw3%&vpx1^wW7VNMjloH6tb;uHj%btxmdWeSc z{T0fC<pXPV43+V{Yfl!p30V<Q3V?Fqr+95bM%F)kpJ$i#V*(pAjP1USK+X>X4=6zh zg<Cv^hL<EJeX!PL@pHv@mHK#k;IrG>HiR9Q{EcJ~;HRfN#urX_>b)ZFOL<^2U;c@2 zCCUUJaxVIs_hyB?zZ=D<^KTBqnpOdfE6lJprBD?2k?6(WKjn$pu=D>#%`!3u?|@7p z>QqY-7a&-*3#<(IIpp99fL!<Z$tPT?$o6r<Njzp?p;uHx19s!5R0tMck>O~WcyC># zJePVW(RDQz8|w|UTM}F1n8e?}2NqjG6p&M|il67~<nkTp#y=kpD(|@q{d3OP8t*H? zVDX5w2tsv1MHG~NsNn6>r`;MqY8H77%RQNacDfR-K}^*utt5cLmP|r90RE)vyOd$- z1kk7L%*lT0K_ctQLVjkcoyxwTh)xw|Q-(tZR6<r`;KZd!l=kV<?wX|(7iD7ot4eTJ zi)iJ0=9rd#4u*3;YII12PcAV?CE?ZcPdw#M>5!Un+__YGC8Ro0-0OvqO8nzE?)vJ? z1{LEeXUlfq;mPu1*CTU3!Ud30DD!#Ucb|1)%r<ImGn2g@g`oqtEoc)s05FM%_L;o) zl!s@#bL6wmR?>JuM6gs|;?)jnIG9a!g+|jn{3n^1u~U&q54?#~=7BTj3loZ+V)2iy zt35D>aI-Pix8cMJY`hydJT|wY6L(x!$6Vf<!xjQTQvezQv0d&1aM;Lf_5AZ}rY_22 zw9i#VU6kdezJ77C_pI|V%&Djy2VsDtj3_|}T(4V0<<~$^tZ&+9>i3FD>ZYI2k<cur zxDZ_D=KlDuRY!rl_Q1&TNirdlCFNb+<E7O+c`+ALu9ZIOezrLQQ--8+^8P`H+FzEp z)%B5LC;mnD>Hhjx<+k%F4R-}A&cmry;2K{3$^U=mPHaducSwl&`HN%9y`jye7%q)S zGVSJX{%4<j4nMVXZ{j?nZ@~>%fJ~TI4%ic0VuSAI=ywCi8<U}z!5<9|8ORdi9?;pJ zi|1YEy?yhByna*s*}7OvQtN8rZITFWcn<9aNw2j-O~?QFKc>3%|Nh^n+&POSK2nw4 z;y_2YA3(1DHTwClKkzRDgzS*kfeR&ZN#JuL4@LUVhr6FZQb4-MABn{ZaNF50*{x>2 z`nfvZU*0wM7Dba(!+_SQ{{7V#Dq*#{et&V%{J^>;H9o^6#h*r04Kg+t(1XxwNUj_T z9*C;uW*>ZM@k2V;J0j(>@kj-*4(8%416&V|2QHQtk97Kj3dm~U*BKVQ8w!y03gic% znTlUmw@FY_oC6Ugk@7qzmE~JtJ#UX7Cf*Hr##ZMJ#xBaB12`+7h6;t3fVnfBRyD-1 z*9sbu)%wdbU7|w0O6wC<5c+BR_hy$wxI|r#>Q*=g%1~-*8y~8M+>dBNILxH%<&72_ z!er7`I7Ps%1mI}oWN7%cB!G91TVygRYip^b)cPJtX(<j@SMv9o#SBc1`p|HAf6t$F z9<*{4&UB@#vx?k2g|MFd22d4KQ)i_;!9wjjAUod+zP1{RCwO8v?DL(b@T0VY(xfZ~ zM1V+=AUyYHLrR~;d(1De!*bWB@;!xgKJ)n#S9ABc{o$MjDWLDigCfy{a1eBFVZWrr zB=SjlGtaa%*)ms~J_pU5RQtg%#^y}HSz+BFmsg*YXQzEGvO({JVCMY1-CW}$I)ybL z)yD%e3Hk$&5*Up@aC!kmQ}z}VH~tuLg_<{zmumizLynO%T~k%fn)0UYQ75cs8ilvF zN(*?h!YBptb*WK~#ACO1*PWTYtvQACF>5>{An*Y03l17!XfR6HM@@M}=2hb@TWGyY zPOm#f2wex{)m|L?)YWQ*L7%zFWvkpU;82y|&SGs!V(0v_F~gX>PdCYPhp+=pfTbc% z1!0be8&&hjK?9nwSzMhd^ogynH{75n{is`_*#T*YL^)NGy$|S5z;S2OFx~pmi_^bo zcw^M<d44Y7<>%*L-xlqaFh1?*L)Vl{zLI~5pbgbu(5o6{gnfg)2GfP>qLip7TJq?N z08CgRfmdS<t!iEU^!)tIJCVSrd@~O{H?C?o^=h(;^c6R};9b|chTNdI$F#r-(|@^o z*^>(gU~vLWAM^;Gu#X$o#;N4AEr;>!31kdyD1}ao1uYMspxGwmXA4+^T-jWfsM7M~ zNqw+mwauki0%WSvg-#)tV6x$mf9ej~?dc1_^jG7>C>`oC3-tt|YG$pTpyjFMqS*(o zSd>KQdudn!S}mHx^ol)2x5tat>$RNU9xvYt8xx37B~VxaScGtURoqshr;ZprIUlcP z8GE<N_Lna^YvLiSouISB7*zv7?S>vK!%7QX6j;Dr+^q^J05IU)2$+QsFxwDymGin~ z9veER#EC0#cgP<jcMjI?%?;SJSRq6}U~!P;Uqcv?(~D2C5U#xtJ#;Qx@Nb$&ag>uo z=tF;lRaO&zIZf_ikvrHZAk9@lh4-^PMW6wzEv7G>iwkV}3<~M5$+bQn2M2aqi%pqP zwAdtY$PB4ncKJZZG7wXmLPXZS^&z;Pxd7Eyqk>CTQ?<mBWdgJn^bf96pctE7GxJM` zpD^eTl8on4GGE4?q;LqQv$m#2`?&Yr^z~hKw=e!!ee?;9N*j<M1!2rg=W$$$$T6Sq zt>Ii7B(2hhm{(2(vkDiDp9;U?32gwk{C7?6NlQgRMWm1b!+27MqEszUh5=R&DGttv zvP5x80=`r*{8AM!e)sQJz?A{7{)J&+7A&pX>o5M>tN$is%;xFub;6AH>W}G(j2Ryz zj>{l}x-@VSUs%wD^{Q!O(-$@`46=r)aDvcDD0YOIiX?}io79<oAxDd!rM@_^V-MP& zfZl2uGB>!^)fZ<tLGa@S8NaXD1QIJaZFu?{524|L?-@k}h9-1Z{C=$71P#~Lscyo} z#ufE6j9g%ax+O=x02qzQLHp{_c5R-hM|CbXpJkDAb;)`KDdbtqO1E8lvYw0&g7x`; z8^+I_gk{UX%T^hGnx|{)Ds_gI-Zn$ZE+=z=e*}LgN-IAQ+<8seb$a_ts<Or26@$$# z03;>H8z^NPNN7A21NJU2N9iHB4$%m7%^^Zdo3=vkwRu6h8IhZ(CGx`aUMG1-ie*^< zE6r4EBCnGsLeH`OXObU&BSu(>qY8*TKY@T85VeT%CvLOmVdFY}UlsVHPm!hlaXg?R z3nxM4S0Ex+)IouHi8r>ck!=s0$;~}5C0sxTf`m_LMu2$_oidAAmZyC?(HOkOoM#Hp z&zZsnYrYS$Yk*ONW9RPhJvWvRR)~?G?xmhnUS{p!fF*B}%fTx-h#?nJ`}D-#Y8Qar z+vdZYyDWX0r`4!H>8in5DuL934}kNba63=h!piTpC4)MGN~@|VsewA(2RCFogZlJu z%c%^+F~ZzO5%B__Yy^Pg14u(m#`D7(9s6H_zlD~b#6~a=g0R4D?<<++YEx&kS*q=8 z-W||6A6MGafG}1N=5s6wpM>Z#j5{|MBq56YLp3*4ZG!u|{UwwK_gA^*43tSr{mi4# z6eZ0|P-_@f`}phwOh0FT<sSfoH!7d4fClnHY+i6ZBVSbxll0NSWT0~d6(A{=vtYlV z+MR7QkVaj_0JA&dlsYKLETLH{3Mu7`!z6_DjeR7WwtHo^K`P8DMc8Dw7EsPXRxm!Y zJkRkjGx)(v(%xrA@2*29OE@%C_7JKTqG#2o&j_>)3q<B1=TZ>Gp|W6M>5<K{-MRYC z&t;38pUZNNeV3Z9LD0iRkox?m8=npdP53AVCywM>9G=87RClyT{?kK3R{=q1fv!vH zx-z7{sxNcL+Q2@$Q4*$}@1<l-J5*n*L3~0K=P>cuW`y>mglJHO955zcAdc@q5U&Hl z$#y-0bc8T(E~`5Ye~f<#$SD+;y2?57Dy-JNFw;s8MjPb}(<pYsI4uB=MQ(R6+PKL% zu+@J!oqSXsin!OV_ArWkt^WNJ7{^VdHav1MtAHP7QxUO4Q|>s$;-sFyKD52D;P@ev z3NSyw3Xh<sk4Z1U2STPM4|+|>RkT^HvAC~si$r+o5JTdp5-XV*z6O@4*ZSJ1gUf@u z1nU^fgYZ9S(P5nkaI-wnO@SC+XE>-yvdVYrx)SZ6S)$f}H74UAdMu8~2NH*4qo}Vj zk5HqN07nmj6GZpuoN@NGqC4PXBdDM4YW`)2$?%-VOjDf_^A<mgy5ohvynX5Uhr>mu zzWDd*_Mnb{WDk+lhx>`!ki3HS?6gzb&s1s62uL;oBXLM>5Y{|N4>5<%o{gE`LUszx zMTzm7CxD($IH>wRbP4*S5CTlVYzfC3a9<UdKMt-S%`jscVgmibdQV0T65#@OyRL<d zFE2|ihkMSpL601v;cojwZ5_;sIN0kX5GZvu84H0`@a<d(yz(#vguj&H@kxCQ+o^&( zhO)L7-(A1>oe5CgWTXK}_6Yxytc&0GKoZ6_Spt%6kimT5z^|TUbgs3@mRps1RD<Xp zU{{N;ojJ6==fjN~5~PC%o2)%FB_-C>^A{>_V@71TTK;`6sU3|7Nb3s1CFtOt3h^f# z;S;+G&s;+wo!s67``P~Yj%+8k2gH&1QVUqvW73yIDmNopxydTLg|%R>yJ3!M#ScNt zT}lwsrEQ(g0PbYdH^@in+c(XBe)WZ#iy^H-Y=uiVf*TiCWMq&#bhpng;e_Vyz<Vo7 zi2Tp1{wAUd34?}-w~mNy>~pa-6X5e}O)wD+2qv|V95*gJ65puihwKuHb3%WR5>p_c z@)QWD$n^wIt@_*2ywT%HHGg?&SK}pchPfatlai7I<T-GIC~EDqpYN~l_E#0$TUmZt zmHfB0GH0hRVv`DR`Y*e)Ft-(Zwo>e)LbDki7zhYKFre0wdhwW#_fE8DPHdxm#K5`= z<C$=wrX*~(M_TJ3ThDZ>%#i&PvMz26+FJ}M{kP5Z^#$4w#7-pbY<-HlRQ}qnvN!=8 zp-6mTL~Q2g#X{4*s|bzCkJn18H_E~FM=~U?KdLjdmn?4Rg(0PhsGm<@+RMZpa<uHz zwMKA(K}b<#h^JeOG|WE)8*FE=2#X{ZTp;^}uH{f$M>E~K_wp}wj~kHQ*FarLug4$6 zT@U?*S63yBdO35Wx$~M>)f<(S(XK@=j-{WiuY{e&S^F^G6(r>lvW1RToR$r%{M3gh zndH}I6%C%L^l|Nn1!-6qPH;BhWn^iTVgqY^F9}u)nYC8OQ&-2_YGey1ZWY8rK-^oa z`A<FB;=v3|)Fg$-GYm2gq>|vSqZu^S_etwfLp?u#t^PeWQB?xpkX>7E9`(pDzG{wa zly)WL*-0(Wb^r|-k+>3U)hKXc=GolFsnS7ym7GeiQOw^R4(lnlFq@F#<SYKQ*p+B! zb20TKQln!S3kH%Nn22FbqGX5kO@7r#EHPxDqMmNW(F(>lhr?xS3t=Ks*GoBPN_@2H z)LmO^?JlA4hKy>7fkk8p<(QFKMcQ0LsyFmeb-#;RA64vo)J3Lbz2`ABOO`6)gKZLs z+DG%;(X2B#LS;&PIp@BX2PT<LXXc<z=-ePe&N{PuPws6c{Id-Wt={aM<A-t1(hs>i zNr)ogiASRFwI#1qz)-Dt+A5t;3K?1pVU1=d-WS+oG?An=X|WZk%3%fNk2b~^y$GE& zM@@xSF{*)6%F(BptR?|YcJ0LlP8MS8w{P#SNc1|k!?kuJ8}_X*{fTb8(+Ie?uBUqa zQ}$6*Rug@N9h%HWmw;%2KgiThEOygP1WySf<NY;}sXLX3!g&85d2hla$C0FI>!)Y| zV$i+dCgMKoBLq;_Hn%k`LR5DHI~XM5q;gfvtjU9-W-$N#d(7P<!sE=WtSqT_7TqF? z6%l^Bxw+YEuaWZ*(=9462Q;n~R@C^lY1z~vPOj@oP;c&qTf)fzg1cy|Ar4Q(mD*GK z8W3p_5orlwx=!XwT;fUT6>geE*3Iov<EUystB~P*PlGb5B%&Vov37!~VYaQ`F*-Vz z6nG?E2lt%58Mk~Nx(`iQL$}wZ1kV={0SWS!Og{U2gACW8X@X5Wz?3DSSXmMl9Jn*@ zPEU_jk?d3>ituH#YN~>aS!9Kl?3(i6k`k~aJltn0MFeB-#*BT*b|>>6+sr(>q@3WG z{VXOT*G0cC(<-ZQxS{ZZ%HhGe5-xFg6h%s6Qxe`nRFbB`7q~zfGch}Q?S<<0>U!K> zTl<z-f$-?%pdK93PoiZC3je<=A@Vs27;!G!zla5ipRFlit`lZi8JAoL$J9G*xdIC2 z4MwHRNZIR!0k$*lJrZcGAGO8JH%^nAa<8Wtz&?=W6lC*dV-;duN8Ih!JZuY6tN4=P z%sh#UhYvC&<N&|u^l)kkH^4NaH|?#U3VY9BJ%}SBW^h#0EJ~DgaV1UTuP2IG+Blgc zJqN3gU8o8(Y4F^}xv0_B?(yIvLMKI|;AAM|_*c8<(qgPFR1=Yu0H6>JO$1uEg)S|u z*+(Rm&B*YMoTwbc54~0U=#paQu5eA!=nH^k3mp0QVZe=<qSbVW$}+ze%|@v(U?k*H zk3qA9(2}$Y*o<|qaVLu6mN;k=1Zn`knKo7SEn3Z|q~69;6XUMIs9y*ysnO7eDu5&< zJ95;jW0gHqMHxhpv@!>A8oKEJ)^jOk$(}~S=dA1uY7xd{Q~=_Wk}%9YB_Z4AO<A_i z*6)nuk8WS5X~dpnXg0)&_&5p;i|WN2I0^xZhf#viCZCUR>o3SdCH1t;P9#`ggf)ZA z{m8{+h&G!h<b7mb)#f$#ip3(9Hg1&>xCZXR!5YV+MkdT{+_N=Vn^xka&~8XZ98>`p zZL?`FDZ<*Y+|w};xzMOWMGL8Iw_z6w>a7@vAvZ_Y7t9h~)6M&b4LQXT)mag9p$4MK zCUad*tKJ*UVrh4bE{6L(0hUloW-w{jo-0<4;S%+B2UMc>B(%grNlkd_#40IPfudH* zO#5{7Z3A?Ef6De{Qzf8E@h7{5B%>uy{J6^AXP)9!R<Vl`!HCY8-EZFOB$wngs*4C^ zJ4!*?M4WS?c22x2Ez=4YQyR5){{&t*Qgf2JF{?4ev!?Z<SNK;jE<*wQ2{h|wd-{aO z<!5wn_4D1``|SxEXB6DseFBsse?J%yDv6-?>!Vuly=m)p$qfh1WLS&btIG(LsBkh* zLDUED%ya=hZNFmTYZAs_3_wO)+XWU=rV{y$Tki&XOhvt{?{~lWB;;+T6UDZM7AS$> z8gf$OG?*A`&m*fd;3ICz7}R`@fvX!Taja8=Jk?Cs`+!2&-h#Nq*1(LpeUt1GZi0+< z*e{Hh@MM`zJ2!G~#czs&4Zsb6dEkeX*gd|eytI9v(h@OtmZX~wAp_-fw@PaY>#it1 z7<9hDOhQ7cjJr$>&{IxGe*bFYdlR=SeSjf&vm<#Xxmscyp$L2hMdcJeCVz}&!l+`u z@Tzs=zNFN4f!JqHT-;aL_9O#B>qDZLQERzCCju`pw{~gK=L?cfEt@4|Vb3hgx$Z+p z4LG?5-zpyW&MYi7ovTO`$uUYO!&6L3l!S8^!xQNY2VN<y5+Pmj!?xy#rH*xn-<+l- zin}(C7R2tBL~%M~Lgz9qekAqCXtX+XNd<cR;S>eHqoV-FSF<h}A)}D+f#APA_dEUs zm99e5+M9xbcUL4G;m+v?!16N0k6LQiR8?c(bv>#X)&MaQSW`?!+-UK-Ges=*#Ts6M zAphg%|KkfoezVYH<GPXgAX~Cxd?Z`4`nzq$j5(0qK|J1G*}2L5z2ALUD;tumU2YTv zQdhAUfbe9JFt2^AeL35Tc?Z0R#pxZ6*y{M2pSwv$?C(8oYi-k(^D8kc#{0v={pPr( z8Zxot2p~4V&Al@BaPgUEuO#927oWY87ykkZO(jh=zibaNslxBSB3*tfm81$!B@Q^M zDKN_j*+YyG3ak|4-#+ciG`LDVkQBXI{h-Tk%N!4*AQM-s<38IQ53AKOPBA2Y2mKD@ z6W}Z&Xgg(kVXP2S@B+{Uhr<Qc1Xv)HVWbrRLoZKWo!m$bdaSL%;-HgZ7WZ6sP=8?q zT&<KlvCyfszj|kE#l#q3Fn*};93OXrA!Xe3#TW1&b$Ud96ouk8$1@#SHx7ymRcWy) z%-m5}=m|$S=2<UCuj340vSK^ZTuThbR!I)MLce<PjWRb|jc%4RquN`gngB}|LJQHE zGq6%<QQT6o;WbxtZ5>r!48?n@+In|q8f!6gm<Jdcx&WP9ws)|r(9}|gAn=OSPGs+R zSJ~cUwZp!{l74#l)9zrhGmi|tGQtyjMp%?^5Tjz}&_ZBcIjd*LRu&G2R*bevGIM*3 zi;u_k`)tFQXTU~*HGpv9E>H;G!aQr_Z|_4l#Zbe1?e0;U0Jm)Jfk9D<kD3k8jSF1} zKWxNGnRu`5TX;MH)G}+ll_z?U*k0=I_d2qeEURkmzxeL$i`Or{dZGUD<%=KQYQH$K zt+Kj{5ELx7_RxjugS$TLDVmo<{b|Xv)=wU4?DawmaKhWJaaEEmZclMHxK-#m7$K=Q zAZ@1h<eWY34YUsXhJ*otL3POYBbGt|Bs5WH!-b(2`O<o7m6@)mOG-y)ns*!^yO<lX zHc3<iy=YAHh#o`9%TITAe+4bs?W-v>w417P<;069VO`P~qJ_v_kbwfr{T$u|vs3!- zwaa5#h4Dz;92QYtFu@=I5Se{ojVzzLJ1t9E6-Ij}Cl9xIR|^KqEi7Qo2C(%(**xiw z#RD?8%09&A&9k=hyvT|7s9b{oF^;Bsq4cg&q3k-ba@HwWr5uYoR9UdHb*~PaksLUu zx0&KB!KXtQXoBSoh(;3xDdi78>e`NpN1gM+wIcOmRREq>IpD3mj1<T11@^)s&W=Gy z7-SvGHen+1Bj5Zm=?iDyiAkF1hgkyZ9&6nN!kKyfZgV(R@Ez#wHr#~zXuje3*Ke|i z_Y^m1S;9t(3WY=%YH6eW|JU+Ct7{7lo?Hj*hZnD5k2FQ3tbiDXGf!m)=BS!k!x6xJ zZloDKDOvQhYsp^21T&L&xG2eSiDo3J#!UI61=zNIxP~$Hz#D>x16w>c-}!pe=_1aq z;g}>W_?sdJ(1inQM%%{rkPNc@`-4~#l%4Yaz719dod;?u!=Mw0p$Xjv3DP`oy4n^a zvr>M{_Fj0%jwixpgcV64PH<HS-f68|*Mx6-r4MWwB!L$q5@+9Th3njP&4zo#F~NcW zdJ1e}RUw|R;Z!&6i@(zC1a*nhtXj4^oezFzao`RnGKS*-caEhz&o!?(G>O5_@Yb`t zagPXcM-I&mw?^BzB?ELo5pE3y6A{)=>_LF*F((T-`DwAzS*x|3La#o!?)MMXR^Q$Z z!3Ukr71_=yh~p{7|3(b$cyNbbV%7lE#&xc~&)zHi66{)@@-RXkz`c692<Pj~{>u|Y zmeoEHyQ--_AXfzEv<EK1A)6T=HxJu2BKU>Qo=9FXK+y>Y1FH>l`B~jl4i-68Pysq! z<f5E!3CsSN;e{84uE+!Sn~%ak_^2F&%|itX`S;C(wAXd@tyC+I`T|ER{{uHUE*reG zTK(_MgIr8RaqPg3<~Ftb*&E^s`k$iuspuct2RNR{*1SgVq@f|#DHW)u)eseI1a}V2 z5c-Wx0ttoEPpk*h4K+TH)F{~6a%1`p8C|X(b9cqEmk>4P5oiZmU1ZU4fBS?liLT>1 z`gjp*KrC|#_W^y+@OV0&<nchvf?rex{LTSM!YhRHC3Xs;765Da=0iqD>>GMvNdCJ9 zf-`*bm9Qi=&eq{<y%Z{dQ(~ENNL9VrfYLb>*+ccU4rFNNdh(fGw7+ARR0L1~lmouN zqQXCgE^e*c$Bl+w(o@|OgV*_SlCenj9c+5->&cLn|7O~x@TgS}>x2Va8*UmbA!Wbg zgPDG5kY~SPs1t5Oa3fgh3JkxsxaO^SnH*z1{EwTmi|0ifA$pN&-)@m*SmYu2g)0Lw zfL&cuk_*)&9)F30Zyvt7q@I_uM7k5g?^Pz3@<XD{V1o;~LO9mkF9lM(T7A2f2rw-k zk<YygyBN@DtNPuyvV?jeUIElMgysRu%Zdc&rD?xJmA#U-UA~I-rC-}?-Ed&9HM$EH z*t#N?6)istp{vol3ydQR+emR@T{4zx7<=0Iln6I=y(obGwZ={(XnHdGeDfLfv!C>x zcHt=KUUD5}jc@Lb&~#!5_u#q#1x+_4x{H;d9zVLgvr0IjT7F*U*iYeL4TOjQF`}32 zr0;{CLVn>u8bWN57t-4c3<t{C$aSmnmvSE7-6=alcOcGN5NOcznH_PlJ0Uk6tONlu zNz-P>#dfRCO<ry<T|v-Or=UO`&qsR)@U^5tbjv1vsIVFugF}Lwi>>EiI1F6o^07sn zT_-W7qRbckBzc-iVxlT|zG;DW7Qc{}mTngL<RF;5y^p7*8=ZwK{4HBOu(?CRE`&_D zu}MCG;?%df|G~ai*_Z)K$H!skdxk7)a#1bp&5S5=0Kw#x_DWC_qi8uT8V5$bM>J{) zPJPQk?Hh7{pu;DDgD@Zx9kf+%DYUUYi)%qQd{O{)D`s}kf3Q3zRvDK3nv-3vEM2l4 zn**%?(C$Fxm&GB`A*s2H4<)Bv>7?LkP1}nD!Xda&veL+h&pVmj4VgM8W37H`?;7qj zhG?}qaRjbbe6w27<khPCMrjYW`)#umj~BG3avj8sBT$3d_X;paqyUVeWRx>i4uKn1 zB=9JJZ}{>gkX)+7u!+?kgKw6hI!;-Y<q8++18e+w38acM#L0-vgl9q{3FA;*MV~Y@ zf0u|}8Jjku*hyd*<gy%)l?*q-l&tSs+I}Ud+6*&p64qWo(3&37TQ<-Qbo8-3sB!7S zUd{kBnP4*~j-{@t6W>=kR&InD*li&qpRmm=DP|5TB6$Jvme6H6+F3-?XR;^jvoTi> z^f53hV5dqvsKf;$+OH|*?C}Z~hFJHsVhs^b<?4ZYKAGy5*j@qg;NpXvJbTRX+KkfN z0h<FBQoHrpEc=AAL%vj{AZTk3qV(Gy2%Sbcdm!9cAsy%t_<beB0}=`#G0JzOA@$Rz zP$!nVhR;pSNalARck<bsW!6F0z13Cm#|E!;%QA0qjDm{<LlUP|S%J{X(500l_>$A? z!k$l$?q%n0->p0?i!39dxnTn10NPT3i$wb-0j0iSew`h&_xtR_8L8I1HjrwCkeB(G z*s!{1cwo*+wW(sxN;RZ+T9y?u#wmgKPl<mP*U&U-dR-C17=xqchND<tFKuD(Uc}v@ z1TKeR74#z|KE9B%orI%<qZm?<gzPV_qunpJ6x{>)K%RjFuV%v42o?be{<};*$QEyA zae57Fb?({ZcIx2VL4gOpP}IbV_vH5S2ECx&3-=<->$qle$vckOLL7~Ko5f{yKlA9+ zAj8rC!cC#Yc7^@W@>idcvhDDkx#%?SEuCza3Z;msV26VWfy=!!nee=|s+rQRnz~c+ zntha1c^}U1tQrS2OsALtP*qYPz`OCu+rMbygpOh#vOR8J4xst|3~2Pz!T?)`<J|Tl zKUKLt?nV+je%SAX2-^+J4<>;S4&e_UAP4YI8%2JYX9;nr@Dihp=FY^BpDpOUDhL7s zXkP-1wN(yGWvL*)Y0*Y9S40Dh7dxkS;WIC<R?SyB5z=a9I->4))hC6ZEO9*Jj!ZFn z`{?(2c6+PuTyNq7+(NKuaeFJ^g>x7i@+5)klRQH#l?9Q2EFxO0gfAa1HuZjABxqBK zHbIZlJ2h8p(@8=*^z^l9pA44r^?sj8WD^&-4~Ne%ryd#-iJ`=~tfaP2bAJ5}B~HAu z#D$?l24UbUCIF2Re`3wkXtJmV$^z>^NE~quj{BT|o$c<sW4YPAC0<DftuIYrMrA%J z;9!sh1Av~_pTNueDcLEzDyJ7<e;2sUH=j1gchI??4iPai+f0@q_JfKOnd|{vIAL=H z3ZNd1c01uxF&KA}bIGR0;R6ddvy?(BMzFKOzss}cJ8!e|5@oFbts(+MGCK%t6e4WJ z14AJgkOA>QB2L^C2`o5Tmp%{<73i`o6~E@6-)`>lxgI*4hvwsx0ig*dQcyR68UY^q z`0PPGW1a&+(W`N}g4Vl2vB3{w@X=9-ZP{=<#L%ciQ<Hd!Vy$H}8__dmOQ{h;P3tc* zFC}$O_z97<pny5MxYDcP%3747g*z#erf7onFd1b>*A;l-gZzu{nRt9P1nD|LTNjeN zT7!Pg^X8tU$bfEf!ST7SyOLxIi$5VWoKgz3BcXTG$IeTAa#>doZKgTX+oX95z>IWP z{ZsW9iVm20$|Q(AgsmrzKI?@}NNGd!WTqTr^Ca540Mv#mfh-1?GS<#P(YE6cKn>sx z{V)dzLr@exL55J3BxK#t*c<b_**%jpnU+ANH$*RyZG8RW6zBLk`NIqmKbP{0@&%L2 zwE^Z>BGZUXhq&#z{T>oLntG73IX+|=LMdQrfs4CVJ)HCyJmX!2JC#=#DKR8Kxcm&I zb?GkBlQQ$|)l%Q~Uq{+2-E%h+C{Csq;<w3*=!b%unP3!s`3J(TEU);I9p1+5xunq{ zXp)n&b_3U8VYU=a62~>!cKzGSgsSdh4;Th|j4X2O1J*PcTNc`7!H?xevUx>;lBzdM zXGX}8CnOPYvJ-b&gP>r0Scw!HC8)-$t3t;_k^_>{?a+E6<J40RYdizyHCs-Lvb9>N z;?WdGiPeZgAi*9dJ(ow$dXAcRY~HG6_G=}MM#Z^7|8ctA9oN;rozx+n1&C?53+WNu zJ0YiS`}EbnoRWWSpekyDba}}jQp>b<L@xN^6y{*!P9ef$gq)CPuiIxj-~k>$4mU8p z*bi_VB1ais5DYd?Q>c<Jq#DvTKyKK<9h%=zHGyh;5okm?A=_qK)3sE$CNBUclIwuz z;u`3$twFaT9=D=GRPi1eD~vQjWLA)Lo#Nu9`)UsO<Ny2I`&YG+^hEq-qfkI2;bJ!= z`wP)i1+b>}9`QV*z^TGGlq#0ji!uyUy-{%WD2NgkJY>h8g17t;uK&+&BO!uGQeZ3w zf5p_fgjmyBdD5JH-4}uRASIbBs|`{(xLdt~<3%1AbxlQs?MU4!;VIuAK(Mr$nstiy zakx589X2~|uMH+vmb0YJA>(!p2^n3I;AQKbrhW6JihjISd71zvHRXCh=7~WjCnrSG zX@GNm^ww0#f#`4Cn5yj>%9}ICJx2)?&=nz(q;(>#(O4sCV@rVN<iJL957ZMgr<Y3a z`T+FUuG|f(tq@&XDhvuF@NlTH;Q{d>zZqB8SAbN9TLlO~1}|>K-3$LXq1k3Y^m7@C zTb}%VTZsc;mzXOFPlc#L@O48yWj3~OQb&ojkexa(WctRZ#h6xJ(T>R;VPnKG8CxPw zRG1GvM<^C$<m90YOQ5};KiZ|LNbrs-@W&m?pD+QD<S7>u_JmH1><C*7kw6~dvIJ%z zwA-f=P2b6^B~_zK6e+xgNl2uT4-!9;^=8rz61t{s5Q@v~OrV&5_=)C0c(7a7P=5d^ z4kPjnV_!)jX2O5ktt+M_(tDf>i}FqnPnF%4XhdB0uMcDl6d<6Q6uu*bS_ub2s6{x8 z4!OY)b^~acB?6aAk{997fYI6_O6)|HvHoM5g02lVGz?UMO(L$|O!W+2)^wS6Ap$=B zbXAi}$V18~g!cf>UP<N23JN>Fd2baN-C#6?e^oWJmb#%ptt49^)ZEaV!V8TiV&eGK zFb?@SwQ?yv5kl+ZPpxED!x77`$luW<6(f?R#^a8Nk0CvfkRg>+?4Kr!Rz=-v|21I| zVT4E|W-KVNXJ@Evvj61at;N#7IU<)Pfa_rq6K;($YT`ojIKlLMB9vQR>_P+ut|214 zpRGR>q4r$@E!$|$)3=XK@Q8`-nj8fV_y#WaY3Rr~tNcnPM}ZAn`})lfswy3@s>n!P z&(4@^_HUT8Un+=<UC^w7T+StHAEKmhcN$$D<cj}L?Z;kC4pS9)BM;9W;{-2=6|R6e zFbY9{bn=fe4NiE%x?>zLV_1@D2VP1y4)lrte6ubmQ(l3(tw=A<*o<er+vM!%g~@)t zHWJ0+k+6d+624a$aK>#MtV}tgUqfrO(AuG5lq!WxRy@ZQWcGOg{)H3;n2$>qOZ)WJ z@}jTCcs^z{7Zx|z@ra}C&xX*as0BNzu?#!p#j4F5!D1?Cmht9rK!cSiAENmQ<>$T! z3ng9`mgK_w(rW|P*QYNR=kL4dH(PO0&zX-N=1wl!*8AUlI?4gm1kE}4TqHpy6yvbH zNp$~>b;W^D#y*PY3e310L2M|LX10|``!>alAj`;@NadgZTpfuqI%em*m5rM1hT~C} zoSeR2avg!OC(9=UfqX4Ab#AE0>T22medYGO5HY~U9zzNa$VgmElALq!jtrbE1hHgG z;w@bgj3kh`Rw(z81BU_x>H0%M^xyPUt*xftN~k{HmL^6PyP}XfK!(Z5xVWW(<Tb=K z3mf418cQBp(ob=Ela0Id1Z!@cj3ZaL-P)0R)_Qnu8MU`j!J`<QC*fU1^>97}7nTf& zYr?uhi^m$O@v1!u(VjO^0J}gHhjkFa{%Eqq_Ff&=AM0j_vw>JwaOGT4;Q}UNLDWXo z#GqM<Pw589ZD7#>xK6CH?-_@CuWfBNU@62IO&n{LK&>Y%{Wq2&eL)Qf0K#qIFir8b z4B`R)VEg9Pj7wBRvxHys^SQYnM#b~*>UbdX77s9kPCPg;B+!!JnLv~xFuTV+B0!0i z{+QjX%`D?KE*CwxE0-jf0!x8E*AdSVg0Xu%TduN*1yWP;wF+k6ZH>;wofJh9lbY~3 zk?Kp$iF)1No<0m2r#Rl^P;kSBvQMJo894gukp;&|Dkl_nGj&!mxn~P<4MmA5ggimO zC{(tyoSaGQVjao#ii$gJb=H-w@4++%<QRTY5@L{Tt#Bkl$y||}a&9Sz1}B$LNFakq z+asyVg!0Zlxoo}I%>3^nFG<7WqQr1w<-}&W+_o%vsjUbDB!m8?wE6C?Swvs_E^QCU zdWanjOQz(E7q9ubwyR@vq>?Q)-m)!;a;<FvDA%?cHMqHdi()Fa4{<mD*j(NNX&Nh1 z+@DzO<lYW-fbc`ggSj+5Uwn2DrZ#1LI*g=r@Jp5b?D~J_PpMCZRT}QS7$zhXMh|dd z3iq<MqrRF<sIDS53^zF8@uOOR96-x2>y?m)y{M$?0+SYfNeZZS1u>IL^h0a`B)KPR z9<xB;EQX9I|MgfMGy*{bZ{nDcH8(CLwJ6>qRChIh{r5)gQN8B4gkO?2knIhmD8cij zDJ@~oq6~Q=Un!w8CnJm(86u>(Ch3Jk2p<{R_*^{V8sjj$>>H!nAO?ze_b&~dAV1pV zOcJ#^U6d8KetB`-)bxip(pE$U!zWE57X?xekhBeNj3va+x<na3xVc?2zEx<e$p6kI zdfRTioEwu)um=)K9clW%M1Cd}$v$~wehBK5qV6O2h1iH7bc!X>1oj$vVCWy^t7)DA zHA(MeTWO9$MI|7!I6o;yN6?aw<528qkOaQj9<_0`<H&3^DA_d-sq)skw|AH&lz_ww zDiS|Q##W(DnRriAG#VB~JpoT>;Ad|>>xdSfV*oz;_IDk6t=Gt$Lv^I7C0t*cByv$P z78o@rfR0EQU6DMM%RNh*mh{B_-b*GBvh6gJ3=Hy9D1ShQ{u9=PxQ0(7Egf?IiQ7Ou zX+_*Lu8#B%AS_6nA|M%(0}nxNy3YgYqljjw4@tE<Z>cWzmGrU#zMQ0P7!?q1W!!qz zSx`ytoh}Po100Y6AWIEH^_HK;!597KOB%chvorn&#R|V#nRFV;C60~W_JjB6YUW`F zE&(_>36L?BBq|%520$41e5Ac64D=*}=!9+|z=kP&1Gz!#Fz{F=WQSD=)HwJ|$^*ru z5&Q&It4%&y091y)Qf2kV!rH)Y2)whDkUp=cntHoXZ;;k-Fi>`NOewrfxX~&|#bDG> zM^dB{GAgk;?yPDz1gZkmc(W}lmD*%bg{W1jO1otkFg*B-NzoEO_z$6#0O{JNulmZ3 zk`)@B5yw+rEX8V}zFw_V{g7?6azr(^rNI<vMz=tE4T4^|LaivW8b2MWttK0!@pWo^ zjmgd|M5bf4`dd{<y;_GH@eD0Db2vUEPxi3Pq6&f!%3N*C(sSxlnd{k=xeop$*g8zU z7awS8MKV|rvpyLQ__ljI7~ELv%a7~@#8_3mT74~l$zV(4)$h#YrrdAKklSPq+`Etr zgzeKo{m-znkVh$aCSZo1gV$Q!<5-l^wB;T18!fcZ%kgn$X-0yxEE0=sxAK)JAL_B( z)qlHnCuR@07yw$6G#mt$+W!}>JJ=B56(Na3lsk~6G40m6o9mh-ti}twadN^30D2TN z2TZ6D|2Iy~zM#;pj3o)N?2z<_?3Z?vd<7y)3?NDNVMmhKf3M0lKB^{(1@bt^ea<oh zx+C!IG<@`0w{ROKdE;UIpZB}mn1L>7fnWtdb62EHL;cZkav+ru5dt=VzY<CZmhAAQ z8`Tc1Sye6<F;ef5&nm}30r$8Jsd;vJRpa@x%7^wEtPH{ZF;c#i82eHAYU=f_Q)3x@ zm;DL}qQ=3=^++s~p-W65^smG&GA$Bi(KWCuU<rW{b43(FcS_{)Q30q9UHDq@$8zd4 z_fApD+W2|QP!Tlcm>=QnOno+iLPQTLp4%18qJ{q(R|KDv-7!+PJLQ?bU?W_!hDm#s z<_Y+cB*Tg&rn8APJXiPamvjkyBJ?u}7fV=TDDI;r{Va{KRv;-*Qmoujhzm}v^=%Vo zkAZW;u(;rT^nT*G{k)E%92oie>bm8tm(p<k6A}m5IU^w)p-U>6i(db81J{*z;dTJ% zUI!U;pa4j~IB9>l+K|2N5ELNx9XMt|O3Sg(Y=^~moZB4{1R6004BR3)_Fjfd?G7VU zt#nU{JPms9UPkw8c8J97l3ku8MNw5%qTx;Kkfr+1Esy0!O$q)OmK#?x_X@!t36a}1 z)1D4Z?!w6dc~XO{okGMcW;IyIh}4ap$dc7h8IHx>LgXIdq=8Rfdve0qyJe}$ZiP?p zm>8jx=ER{#gw^7aX-<sG%Diyb0IY?viU2TVI#>pdrS=ZDyaIyav=;#X`d*!LoJWb1 z2T4S#q$q|DRZIo_SDrNc<MAKd6XH526G$xK4~0WIJw~g&Ml9CcO+!ykI3Z}i4E7bm zH8Mi38aZ*<=uewP;KzXdSsavP(kL9nL_hXVn?(jL4<(o^+{$tcqP7OMVsD%S2<t2s zYvM=AQ(hoMhHZFcb+TNB4#PJ5)iKet-)uj+B=%Ox00f~RuDT5FQIezLBXgNa!RpvA zTwE+fln+p2qk-0I(#x2_1+zjHSD03?tD_r=L3#LEx6p};+uh&8s3eG&Fo)E?5(~ZO ze)%ImV!M=!@Sk6N_2O@$b~ipt4zUvID?!C%v4c)<;Ye@@s-`doHAy_29IliCEFEG~ zm4O+&C0|mDjR=#jd8?Ib-)cnzu@y}<aBS2N<6@W5#*`-Zh2!oGkHo-jY#Lbe<z?DN zo@V$p;HJjM5#my{1jFOTD`8%%4-ZF4=7seK1pr;Lf;5nWT1~ooXsIzhB){Aj=eLEr zT@K&ZTfmsP-rQ(3YV0Tp$sxf@Ff7P6<xiEd(k-vHAMft|hROZ=vk|~xJfYf(umY2r z5MR>d4jh)JkBEtp54M0)V-n_;m4Q7kEE;)Nmd^fXSrBhNU`AkB>!tnGiywb|P=sBs zb|x!Rm>|Fan!zmw>57klN6Rst*UxV`ag7RKt#@(}%6^1(lcwL@>89V^eOG1m_j?ww zx^*fMZYJFHo=fvN8`i7=l?z%{`=tlHC;@^MtCX#6tj~x?6&Yqi<{N1FTKNsxkdw~Y zIRk3wRowr<J=Adu@E02c6-64Nttw)DH#HdWI{RU~qGx-;MZtwIOY&N#30(14Z(`Tm zS0BJz5XVjGCf0;Y@GF#a1nNU{qjHklFDxwzb-+w+T<r><e57W0b`LB_Yt$fVH!ZF+ zH_vg|Nw`=F_pYd?^62+yYxI3loE|o0;FIC(9WT&~sDb|ZBW(uAQpXtq1$7;IXf{oo z*FS%}uGtri<3ig;s{m9BtUgflL#aaK5r@RnSHW@<mAJ!>@+ZKmgx7E|pA~nOX#8@A zOXn9Q=Q^=>wtz-n_Jxj|m<UhZkVbTdSm#v+czh$=1BvgAbT&?0O7f)9M9)h&OwkMb zVd;_T&)wbmD*pVp<*`n-*+&wm9&uI<;yBL^*>jG$m_EaLvp;b6;22m}rNX@Cpjupq zu%rlI0Zg)tc>kT>VC<L2Q?Fe=z2VxGac<Tgi}CEdG)ws##!MD)vfsS_>4-QH0SPI7 zz%d_+NQcUa&1@e21|#>lqyK_&hL!5NalUvA#aVQv6fv^n;;R0vZXVrPMqoK9jtXKi zgofg&XW0d#893*5bh8RmuHB>n#YZMfDkjhuHNh3PFB!$urCdM#hg(wvb#hkOP`mi@ z@gQ)nfc%ERh_fgK`OGGZ1)Ir@S3ml{b|kdg^^-b@x!W`4^@*$yTVxX5g@%GiNdS69 z2DgxdZZP@gbLcVufPyx@uWBP_NiR?0hbVD4R~>8z<Vn!a{-G8^?{2lc8Qg!^BaQr8 zIe|N6=99KNlyH`R$Rn*AYa?YZUkU0C-^3o(<RBVaLzbVZ6X+6Mv1_6}RnNEZAHOSY zzV`E~vgk_}9FuP1T&HwA?PAhQ&STYzMhnCv)*Mm-4<#iWPF{g<3!uY1J3rx#ZALH2 zXSn7ou}*@d>xTGZW$Q}4?%GMvx*ew^d?D3dU1ci5VSEy^p(RL~E;RA>>9ZY|muocs zeWlX86CMrs8CgKF67#bhW82?kl|1gQ@F>0Rzv$`;o0UaaQz0hD1RFN7E863*e7eVh zrTSmFiJHrStI?T1SHG^6_1Hk{2r3tB3Z_b*&{OdoZg5Skd#_!$@GoB~&Gx-O%HMKC z5<02;lyX4`#CZ<d3!f5^lV~f=!{4;?t@H3=GKOeZ*8~>Q1+u`@Iiyf&4iN*GSY>d2 ze1X0W=Oe-b7IgR>N{B%sL)E;zT3t^stk&#{RR|Dlm8G~s-N?fgXun_rHXyVU-@>nX z#XV-T-4I6n&+;#*$N9&3p$2BVDrK82O_YxDoi=Z4pVe~LZn^BtMkM63w-JdJOrnVJ z1Uw%k^}>dxHe&C!r7kWU`d4V0I75EB5lQG|vk?>09z#v$VNN8Gi{QqahyO^Ozpc+N z=+88JImrpo_CbHaR+)t9XfZtZSoF>97s%zyRhU5LlP)^oQ!}X0h>7%x695b$56<uR zM%DcdjPw(upya9RFkz5q9X5sGfshb94CBx<5zsH`$uYMH?Zf{~GS2nFr)wJ*D=Gc4 zmD`j5uzQe`m;_ZMGa|;cC`e$>y5RTMt@jJo?SE0F6ApnR$?b8{)S?=c1lhuiMy?SL ziXI8L?H)g2Xh)lYRIV&~tdLuryZieLO7iV{>Mvk*gh&N;4p?)@8>%<Q;Jx!(|LI4) zIQd(ZDA;2wr*+U`2%$pa)d{iig6EV6zg2UVk6AbVVYgFJNG%8|Wj`>nA1fh{cZs0( z0kohp2yg<i(>{Ib#GZ+ucHB55jy(#<n3l(4tpFBfBK9T~ttD%iiPW3^4v2+NVEzxy zEq`XberF-3CWi>dt!%pl^Z;>yV6VmVAY{EVIqK;XCTDp7{;LW!S4%8qLzX=o0z@bw zcOg0~CG}z>(bV&28{B8O2J|l4bWDJ>P~7_hegZ@NyWGe7XY&Q8=q<;^zLi%=0wHT9 z5!<+0ebnIJ>Q?@{4#CU~vCJ`1_;rT19E1BAT?z(~i6d{sEpCXv>$uqWM8~O1KXx1d zCuI3d&Gq3QatOwD5lBzs0P?1skTjKVuxA%JdtJYc9<+RpkVN-4we`!@qcK$i?YQ_J zp-uP(Hv98OW7Q<gkI-|1IACUnEgM^_x?=0+*BuYnm@^G|)!7LZ9dD^si{`6Vr=3&S zqSN-5eI|D+Qoj_LQ<hj2(g-;CH=pT8=XKpDxA4qrbJO4O?)k=Gm*v*!Iub6Xl`=*s zWn^$zbMzus2xHRGWY4U#5q9u9_1<>?_>)`@;(SSIMNrWJ&M6&R1Ub0aX`rl0{5nQb z1wi0SaInjtEUn}D6X*gZ<98e-xiYFzVkgg!6uF_?$SqR>Q#{~d)=15N_Kc(TTU&D` zb`wk(BzuhUs^mVo^SJk)wJQ_I`5W#9QD>yxO{g`|ctSHz_L`W~bP}+=)Zp{j_p_wa zMEbgQ6qhh1;J6W;?mzy++;{);Kd)OH3;5(O8al;=6Ny{=-CYyhwA6y99ZE8GNEb3K zgk<K%a)FZwT&1=mJa_Z-5M2`3XJ=)6X&EA#m^NaCWQp|nPTLr~narGsQ4<lz*JoEq z-~^GEOV&B^WmQwD<mc*h5nEeGzfOpEYLek5zXMDPc|wK+$4e3nf&Evy<-Qz&>Z%z6 zo=$u*#WH~bRGYAokOZd|`=0gOT0?z$p+=)Jvpvs$5!wtKa%TG~ogt%`6&n@Y<`4!^ zh(&;4DQI8mSMQD4CRoSLM3n2O8VK^LjMQGxYmt0ZFtwM?z3bU4Y21OdAg?y*ctC*{ zVJZ87l9i=$POEdFq!+brz1y#=dqs>#&}@|ui4VD9$h{eVYb(7THJu41B+y!r@3pF7 zv+7T0OO|rO`6C}BjKExp;EzqP>kQ|wt@Du+25Ar^kAPvbAQE~pH6pI7Ln_p|TZr&P zO;j<Oy%?c!1Xw@9Q~o7EorL(ApVaxXC1<&ay8uggSo<#XOs**UDG#jW`G`xq8VV(N zFq@kEEQ!jpB1U(=p~<K|Wrb8-Ckd3qLF_ZFFePBGZPxC@=goQO!>R3Y5X!p8&c;VN zDaaW`u4$F#0*%emH_^MmZ_^B*LheW^#t>m4SssiKAa;;gPB_V6Oj8|ft@Yz@YM3k% zXhdrmB_iC#4CYiwH{)=+2UPHb`r8`nfiSX;GxOvxr+Y*5*bWs(hROsnD{_0=ycxwJ zOmMtFl;e<d67$XZ&E2JZfeksYi3FBWgHaxh1du;;S-K;a9AWPyKkgTwX+qMAKWH?C zM}F4L*__-;Td~EW%<3AF{3MD4Xu+Kt*Gv0!oDcR)^u0{dEqMwDw9X-6`!UA1oHl#p zKrki+y}Txv3Uzwti9FA8(Nc5Lu*aSw9q4f$ez8busQCpYXnVENEtBMlvH?Vh{fJ@Z z8xcoiA*M*>h=*LQek3ST-HSUOMkcC+&kNU~ura_&nX_rT$B*c|>bFog9wxXO7e`Ee zwA6QfSn5ts=8v5^FjKjwRYgHEt+a>`Z|(9^XX?DP=mg+ESlCM9?%)*{i;h6vKC2C8 zWG92RyC&;NN}f?I#m{!VvjD+M2`igq$4o2EqPE9Z^i*y2TW+{MF(}#1xHM)?Qj;{g zDiIA=t+=nAal7@jesY4iu9ZKf<*MN13`q_NFa#1WG*iUXZP*G!#rMbNEF=L#7{ED4 zX1!SQ4XY=!bJ_`MLx&k$M29INL~-gW@iD`N*)|FtBOn_PH;%Ld76V3kxltB1p`qtA z`WY(0IXZz6C1%%DL|NA)7cxmgQGht&I*<&1t$sY#{^baU%Z=gn(SZP@K@*U3S9RDk z`qA?EnmK-CCltS>VZ;<M3<Dd7J&g!~PLRAlfab@8-ko)%o}6jJkk3E~EBIvJ=|qJi zZqY${SQ?-cy;ea8-$2aWiu~%(@#$5pSyW9A6|q!Hp*zD}I#)j35|T19Vv^UAYp&>o zDzB>+GQEm!w;s@k;ipY-s%2!Y$PqDTmZ%)8g!w#>jYp;XL8}znn{S25Uy<5soi)`g zGWr-+Yg4_=Q7muE+SClV4Da|PR<586Sa91_4c}J|{S#C;9;A~6W=B>voB(Q1&$K~W zeCu|gqn5BaSJ(h*vNGs3qK>9#lrn_i#w8#N(jJgA&e1Fz?VSNQ5(W_2#{M90<%=)h zzEBU<1gO>8A*tbYl<<$x2|@=?9k)gevR>Y7*VSs^)=-4xHIUajA-@msUt~;KF4y;) ztTI>fN+|NEs`y!vM*&HVXlfL|2#kk~!RfuR+~!0JB)uxlN|$@Gti>6T@tEs1qz{sg zkOXw(fvO6Y;NW`Qzw>qHpm2s=0lCK>1W8DNaiQ?Z$<4*?FS{+*#`}d)c>7a^UE#ym zBq^K8H^KG&i_c_K7D{1@TU*QZdxPi(4?C9qW-Hyz_6h;Wc(6-~94bpL%dD^dE6Y{g zQp+1$t6+F8N;0cEOq*n-y7pT2j5mv0_P(#<f}V?tg0&io&qxTiAEo1Nwp&Sd@m61) z9&w}U2J8HdO5aZ1Q2VmmjT%EOcG!K8XmhgV<vzl|B?lW+G^kbP*{hRDZroFpTic0m zF7zx^`VmEaC6pVMVtZ<G6q=V;tLCd>_u<2Ci!#IC#KEgetIMk1d|DqKvR}k5O~z#` z=8)r*6$VC!@nzpkH)hUO?_oJ#AE1JkEI<?)q&~E4QItSOo1<@&S;~5$Dc{cF)%Mq> z<iqp<qmyCHYs$v3z|GFVb{mnsp`h&1TT2?N&Gr@&9T>*32kUW&bsj0*P{B2pHl?rO z>DhgHHDE@)<$53N_Ao1*DhBdGP*KRe``m8tnLZ{Kc<=eywd@mX6o`$GdGw0F;WB`~ z0xqpo>C-&WV$e2{^=eQD#`OBR{bCN)Dvnv^`DQEo3=%PtGZSV2EtOYFf@JfoS#@m^ znuP>WC>V|#!hayVQ3U>}<9j+m)PMhQI(}~FE4$xpPoLKJo1amF)z4VBy8T8PanfL7 zY!)iV_3`EBt<hd3*inhjzxhP|9eg&Qb=UGy<J<i**pjZ(eME+P*^6**L+hE;Ip|tf zj{D24m9{(P@wQI;>rRW9GkF?cXTeDq`9<pF1j7{>_eeoZU)SW9W^mgvw(U-haxl$= z8o5;<`J+iB=$E;u%zd-DGHuygU}%>!$IgHJhon;f&;RT#0!|}Y5${9*XJq&724}i4 z#Cg?qMI;cxi)1Ka3ZJPlD&4SNn+v;mu;gNMwz#h7xEwt1_n9PftH|Mm%ifRiHNry5 zmCJg*B%(W`Lg68M98`UhY+$#c<Ho4a&S>kbS39Sf)44U)Gpm=Rp2e4#5Q&8UuA+Ud zUGr5_T2G9r6hujrSEuE#M`_Fx$VdYhp6k+=rLtRBpQ;6`=I!NRZ0bB~8zpZqbT<yG zyToY~qvH-w`!*A4?sG*5Y7e`wQ!42{e6^KAzhj3SXp4%FWDbxJ3McYHhsq>@)wL$$ zQyEvdjK;72BXo!?JwD0}Y_1i$NyVZc4tqO8hy%9>JosbaUd+VdP<%YD_p*FjQRk_h z{5+{=NXX@Q5s41dnzVWms-v>EDS)x@RnBWriOzF0y5<VK#cgi7kO?@1Q(;(6AY2yx zPTh3Rw#>RTo=xV&4b;GC$wo~|BQOe)Y%Py@lUw<PW6^WA_pO8~bLH3src7q_X{*Hb zYNgau88?-BMf7|~n*rjXo*;{($|I!<CLj`plyNRvk$DK$|I1Fb9WAwXLkxs|AF9zw zY`?_aTo#hR0MSv4iAGt7rQlnt%>65(O9tE0AsKlR<Y1Yp)w&}7Hw|POB{r2NwdSY^ z$2n>UX|jE+7G+M<`S8${bt`60(d6##^u=$i8J|@PjNDeP_v)xkqpqC-4JBjtcBhn# z)k>ya)C{#quDKGfR;C%s5n3H*R-0%YnBDnP)>m^$fE7d35+I$z#qDd7;Dv$B$v4dr z#1%1c!?4Cj{8VjbFow+{j*dS`jAD4dW3jvOck<VtE5&B3%xDR&T$OQ^4H83g4mp30 zX&qJ@$)?miG||aLb$>6DRDZ<}=65rbZ>X2=?sWa!-0R)l-H)m<Z}|C(FIwU3Oml}f zYinRaZ_MYdZf4)0UDvA4b-L;TL3z<dr^M|Q0wByQ(kX;=Q65Zp<xB&*_FvExg3`#c zw|;-h_HrNb$WrEqDTd>cV=n0wkjp!BR>=XmN9vRyA|(=zARl{~4H#`Y*W0<xFK32) z&|~Abl8@lORx$woYxVcS*)>apT_=EigaxEZIZMSjq+V_3W~NciLZ2Twd+g7S8VNKL zoXMcsDpG1nTI5DTUZhWZg-eVp6t|flGr<Jqb^7#~(QP`?-p$=WFB*xEuJ3oh_=q<* zJZ#>}ULuj0WI`9OBQAP?VrYGSPP~TCzzyCRmArK8$InGh4PqLi0A~@FB`z#8w|?ao zId|`Wzdb<@9|d=JpOR=Te?OQ#D!0D%QC<19OKj9mBfQ+;!)7Z6YIe|pOlq=$P%+Zf z$%2wJLin`C`l0#O3wzZ;fTPMW#mKD%)0dx;dkZC>*`9s7T?f<G)0FjsTa7@X2xgs# z2K5E{Sl=4|=G*P}TiB;n;-N1-(?M1H(Vz^MMQmPd^4F68svv_nhBLN)$pjkB+1?<{ zz<LbE{<zi?!mz?t3+#i~gqmn^?g$br+r1zqCE7iv8c&)Fq10(zxtA(w(#xKf2Co`g z+Kyk-2Am{#uDvXeh!}^x%&2MdRP?mvVe4iI2eRwDrSY5W{`-CDDbBVy@&M!pfIXqZ zBv*v2?vcKt6W9Mp`uf8|Rg4he{l`l7>w}&eL(xDEvC}tDYYAz4v}uqGfaHJwQq%~g zYqU5CeybE%-DZM}ut<A^agrh~b@YU)8iT{H+adx(`e9Qfuhn0FO@jNK;wlhZF6c=o zO;R#`I}`Uja44x9@J#XXQ>gxA_{o2lqrS6z@Ukdw!A1a1R>yb9f4+;8I^{I02o~ce zD)9-;cVbM9{=M4olvgkUjEMp+{8K@eOUfSo=+znfp^_u2k$TAGb%n5WozB`Asvk+e zhX=9}y6hmQ>m``@3>sIj#P4RFwXMVROJbUAU;N}Fpu*zev|(|q*Xjqfn3E3BC&!)d zkg1mx=wYHR*!CNXrNyQ&niB?CWw~^N%Ru>){DS5gcgCXxSJhP}iE<87px9m5w8wI- z9|BL7cO-8(V2|GGXOFcYK|3wD8Pq=Je&ceVsld-S$KY5U<j$1%fH(qBsW{z&QljVQ z8x|H>0YwHPc1;O<Om@jQPob*{;jt?#G!XObY$2}u21+k>F4BJQYt}MJaqYSU4S@41 zRQkwfftmD;2FTD}0><0!n}1WgPIB^o`Qqf~df%<d99+H_Z$o+Q_0(%#^=~qlRf^9D z!j!lu@WODhmZ8zUDR3K}^P-mtI@<!7e7#kW$@oYTmo@85$c?-h`#KmqNjBwTfHTh; z?+alWxOwmHG!RFtnvbmnd|VbLG}kLou40@iO(mQ)S2Y{*(Tr4^blYbw3pBeaQENF5 z*>(dyyR-ZfRjabVu%k?*$qt9)Uv_V^UqxVD*9v?@sgFP}a1cQthm31lfvwzFl(kVo zB<;kc)E|xlp~_G1W%_;oDO2L(Z~|rl{f!S9I0q2F*Qdm`0w2C1?CH(J$KW;UmzG6W z)DcUdWKPyw;j{{omTeuwJNlo28eLtDB)hNK!(r(a`17r5^fC7CSJ*N>$XR!F6;<d& zn15aJMFA?}c#@vzRWP_4YAx^Dirk3wjjmT>#&KMb;JPBC4or~)Uml+}*;?h@nB<u; zc_B@{jmIo4mn$}wTFzG(4@t9b&4=Yj*>TnRU%SorEso@a4lIyOdQE*v#bVCzK&Ls_ zPh^x#&d8BOWC^*OWNpKx`02Y1YXU#}wG+kk_!%ixB*h0nGnA}uMd(%c^@+$AOh#AN z;OBYilGZ+O6EBpENwd4>>MCMVpu(););?Vj4pyn6afw_p6{O&SVxWjAE==*xT5V?P zTXV@T$2z&Y`#XPL+j5a72^m(<;Xwx^TJgK0!C<M2EJbQ?DF`FCH;sdhy|h)XT)AAw z!ocN5#n?wqB7m1h2pd?(-CgVDy?P<};B^BpfJK|EY3vhSi#Zgp88gB?(D8_XPd(BR zn@Rqc`SJPJYiAj=p-+M=Qj=lu^#ukvKR#r*zPg$y!n7H=QA7*@Dui7P(n%miRlWIy z_w!-5CGFVN^>9lOvpKlN0;>ad6X}kY%i9yYufXO0H&=+iM#0rpkWpBY@J0@LB+d!D ziotr;0#a~1bdWzyfZ5}Zc@Rb9F$+<hamz)8S;e||C2x-f%EXVw!&7B$Sg}ni0KT3i zQV{QWyBw^8rRHF<0uQboNuacKT6&UrFUN*yYZX>y?KW*-SOyL7&8N-r9aqki$-(&e zQH?+kS6l_ix(mY8F^h8Y5I5?<K#9J#<D^XH>Os=;AkSRY@#~Id?ow_^>@7kLZ@G)H zsGY4GBiC^cp*(=AU%7;RzyJHDyjnR++>D^5fQ*>f@@h%5EEP3iyDJ17EL#y;EBQ6^ zjO2n${dFTiI3|z-s1)IPEIG@q5m5U=Oq<+!c0h@bqG$gtx^~XUZIlGA!zdGnU8EZH zenro@{#Oq7yxj3{HoIJAWhl-1BGO<GjQaRhorbvYAapCZ&v4^56{w@5-Ac`gSM9IX z&NwZ+95_nCjY+ddUpIq9C!@hS7z`ydZfcIse7C#5cBV31{=`<0aTTvW%o@EBwp{2| zsO=T=n1|xfBy)z7!N4+JdFFN(J>_<nr%_J6ZinD)a@+@I+f53ne|lnXO5`BPynVQl zYs`Im%s61KULSHzkYve88nGZtdl@bXcL0W9Z13(wx_<>j*R_kFV4uRSUxuN0gPL8S zhmKxxLqRou(wzv7naUMJE@25kBFyBdeP(q~j!Hp-y{+~iHiv^C6|e3R88}?1JkkW( zSj4a;>jo8mz1e?xBIx(}yBC^l;Kd>IT{wesvHrIw%b>0w@CsAkwVeWK05U*w5IRnb zrQWK@=uJv7yt;UzTZjwf2ExEWmSh#LuH+^>L!y(^G5L4AxJ?xPQw%1RgEfu|6sC+c zO9Xj2H-54>e#DG-Z4Y4v@!W*lN5<u&5aX!Sq!;>6*#XV-Afo8q=HXBLi$s0?)iqT` z1TU8xl_=H#4y-=e+D4;zy!-V-e!URKoEZeQ!_A+B!|mn&biLXR;SX_6kktkpzJNfj z)=z5+S6>k7NL<fYXmFSireJE?JfZ1D5@B|M2moR<v@omb_98YAVLiP%z;@B5v^hN7 zXUdLj43-h{Kl37vf*{E;@@l2*nv!D22P2ihK7kKAj5*XrIk={zB)~8%@d;@hx_RBZ z&>7>fU{N|NkdF6S>iAzD9;*GHs!x`wHclM;G68f#P>zH>rxVbyq(O#x-);kOF=E{H zkX0nR<kSpP#4<gU2e0bwAO1=2J=3_iV!#%l${%0OKG8EKpZRuep@Ne2kY`CuB2XXi zJmQkgZXwTZS#hKt$aqcZl5(fMIK|@R;E#{TEWfW-ho3ed_&4qj`GfHQ3d1pvxem8A z%ZJlYW_;AAtBQv1TU<xD-awGaS=6@cRZEcdvN5*Yq)KqTQJOLUCHPUN*6ym?^ae3h za|0mH4IvQ?#P&8tvq3zMt0lS5vpjQH9ygnVgpl-@02XNdNt7Ug%Qq{Ue6bWs^eb#y zfZNSg@FvrkgNrHya8WfDf9#MqY;_sCDQJ(#Ny&Oki24nSt|=09sfU08jpHNkZ#LEh zKA;O1u;&L+#nsy?T9^m?9@a!$SXfR`U<f0@N&=bC5RGDF-O%i1-$m3!P8JT(6l_Sw zWjH8&qB4htH>z}N(|*`(4sthmtNvD%G@y$u_h!(!)hBW}$zT6d0CM)jJlpR#61(`N z{y{89RpWqJXd@^R7l{jmi*+hqsooIj8pPA~_dNjRySrcHuQeLj-QDXF&b^%psg+mg zkNoxSh+e+u(E9l--;`T<KKo6C5a6Vc!*8N?0dMp>e?h;yB{exUXq4RFgqao_G${op zE2bCXd+mI)f)j2W%z6o&ttOWMeh+g6E>cOo)bF3MiZoU?(b5Okw)vU!Fr0@0H|Pp$ zn^&+wC(F*^S>64D4`BC;9=4IScA*NtF4F?0H_?V`aq#x5kS|B5=B7_-)?V)md$Q~m z+%2vAM8ML%Dp|XyTCQ77oVK;7R06Z^lWwVPwon<e&d)D(Izvw~2bTjLdGR^)dt(|t z>mhB(>vSt79iB@GInHhdGSz1lq7jN$&sD^wk89sW45O1%rUcPsht7{Gx3gFfKcMMY zE7?ebno(7Tzjg%8FD+YDAJW&J2a}sO;@*zWQOH~T3MQH1L{9c`ZdrC7MUw1k0sBLR zg9d()qms1ds@aEhs}Z|oc_KqDU7r9fLEJexlMkS*7zsn&EltPOC*SL~G#kjQL1~;3 zU|LjJO8Dfca%}op!mU1wNspFtDo-xI)`F{sVDe^pcBM0Ci4y^w<-YCU<3D#w1IEJE zOWY8j<)uFob*d@qKJv4I0Ob|XUqZmSnXKW4DDPEFzx>li(P*7?ax5@2fHo&u2_zfL zC8Og(Pla9*f88EnXHh`^c2#r|?K=XE)zLXVCuc<(Zb-9c&KxflH}EX+!#qH6WWk(7 z>rdItK0jAgM9c%>-Q0K~7MdH8fu8hCd+t`FdtSKJo<nc|bVjjY&c<h~n(!&x(6>aj z8jF{#m1!t+O~`WXl8~i<8a5CEYk$Y7(k*Lb>)mJ^g^exw_5S_GbKAQHfJVA7SuAlG z1|#WW%jv(t7WxNO`{ZI-I_3U&cJoVuLg;S7Fo;ko+)=MhLuQZRi;lVZ#-DE=CUs#I zW%HxA=Oa0&infH!{v>=zO4dk-44ZfT({A^(NN6Dw{&M%pni@1c&wEG2{*kj#;rs+> z`Bp47se~J@Wig5M#m8$*%Ay>!g#*~ul8_V;aXM{|2iMWIpaGC`lJ1JHM!-#3nG%pf z$e7KhC0eMoN}<ryN3>3JW1WT1!r`2isRvs>;d~&2x^@Q=-)I`1$j?IQo4heUxGp&o z1jo7-I6C*T0xoDYH4gfcTQi!c^;|1p`p|0u6$gz!AO5x*`{f2`s45^si2ocIPErhn z!Wmut+jG?B>t5C+fL}L;1rEa!3}4-7X{2tXS<eRZ%jK)VVhVV+MZ*gWmsuO5b&d5i zD8V3<E+B7WcCgQMwGE)%pAImo#OqH4wB&*f#}VkjKo*Ee4pKKU7U^elW`r8UFZM{( zCk5yI`xw-#+N{n&Sx~N{uaS_oNL-E+5JXd!gnCtYOJY3?Hz=38r9^K-VHJ76fb=H1 zLAkK%SD?M&7Z-4c1R8YRX&l|nmF}HFC973<gPM^D_#4sDV4fzSr`}#SC|4E)Lj;cn z+-%sC)Y7=7+*FSQ(=9?Q3o*E()26}%Tj>S&<Wli*fYnIIXiWGS3gK<qntQ?u5JFv3 z`EHeH^uv?enkNv?L-SpiB*cuW>sMfJT+1>|$gWAOafGa`G;r|=ZDp;>F2oR=M{qcJ zVGOd2Ta}(mo_6={zb{*XEM<jbvNHzhL-)x|jD0RC2#72Sp~cEj%OBrF>(cgaV5oX} z`?%6%V6L;A-RVlUfJe3OpAev*|H~=)*BcF2?nGqzW5|-kjXeRlKB_rN(diEt%1vk2 zd-8Bqo)A~TGJqKy{_oy&HdlvnP{(ZAtEJpAWR|WJYadB9P^_@V`(*9HaHge)stpJF z?*5*@A;B<&`EgH(I?#B}Z8T0%irSp9QCnn|=CCD!#=&jHB}w~IbSuXkxGvuvcWY(& z(8=oAde9kr+%q{-;OzlJY&g8EmxR1uowll_D!|P3Fs@0HRCs!-t_}yHUq$fx9-`bQ zw9!G;7Vl*HRBz=uld8;ice}!vaJ4n=^2Yjwhx(IyC4vXDS939uuJjuFaKH+j-(yx* zcl<ZPaQBEY5iPRzKz$I{1#pVZFdCC5nu5B4d)lS{F`WWqDJe~H{owCtFLn0VJ+V_p zjL+ICI{Vh;GY+B%JPi1oD1fR-q7nvEp~Gwm9(v>)7kCBP;G&a}%r-<d7!+)sPl8)g z<=glky=yPe>~i)#1O+YEh?3l*Sk)9f$L1C|xlt3QYvi4kvB$7CHkUM!N*AyOSeJt? zP|L?ZC}=JxA;`0q*f|vU8<roJAXM34fW<%x8i(Eu%g+EiLeft}kVCMoqt&PzmJd6z zPnI79uq#Pav_sMaC+qRoR@VzNKTOU6cyoerTo@00lq<Pf@|qTK!w9nl3YzDSDkt#P zC(r{jNvDibvFCSS1jYW-hTh8}N;Tv~50c#KS1SVP9{2&H!ndb`3SaLS?t6ir`gLu} zSgjh9z;u?Mf~zvP-#CU|F9s%I$eE;G;tZ+o?yjj92PqtY`U$!#{yH(Yypp@-7cV~- z7zw{sWD5G7fk9naJ(@fsDx!ke_(O%c#+cEScs7(CNXOMmORLq2qba*5bQQ|ogN{a< zxd#v9C|S~w9>WSpA`p)(v1)so<#%NbBj^(;Z$gfVh=eP!ZyDYliEDlg?+r>Cyn=oV zSP5IaY3QgBk|7Zi?b+lxZXogVn>JKgbd=H~ygEShVLmy$2uba|(sR2g>-rx6$G!ZV zKmPc|OQzA9LT!j2zN9AV%GQNJA`Cx}VitfPgzsXZb&EVdMzCA1E_H{(_B`2%E6aLH zUtvs!jKlYF{}e#6wRF95+{l3kkD3?eIBG(;_O2f{mL`Y-E8x$Np-k{2O)ZASalE|j zrE&F3LjU)>U)LYA`;#y`klivU0Qw?3(LyBULhp^<ivB&?SNb`8JJ41oIsT$hEZcSu zE^pubnjVf<Y+%}kb47wtRo0CnB66WbjB|!qORaf5*y286L{lHynS|3aPZOs$mcfbl zh5f-Iy}`LivSINpLI;}G8Wv@Jmj1e_?#uO7U6u&?4gyF8Ah;yIiosA>FDHlls(M&| zkj%ZH(up5)$kqhF2<#F>4d&sXBLU`WvEu_NA~lfE3I+%hx#IRa?1u8<S~LK09H>fQ zqasv+_!$?dCV(+z`?lX1mf_iDP$}>yV%a^y1Cjt=E}PJPVeobGqox{zq2RDaxXSkh zsS}`VfbhpdG_y|hqrsPv{?be>mM93IQPc`TM)GPjwdQT|CYhm0a-3>3GK_0beX<($ zBdI0S#0|Z}PuF(gks6SxGlw~@BmztLnYG5NV~td)t<w%to(9l;Vc7(#kZqpzNK_A= z4t?LZ6@sa<HCX(@8t^#7-T?)hFAg%38%CBSh&B`TmbR@XS;B)*p{R)`Tps@{!N8>O zsCBRBzJnoTw=ZB!Z$Afm9l`(X3sl&_4T6elztK$pR3oBd4<U=RfsC6F9C$udJVc#K zk}0#|7d|_CjS7U9M)LWVVSxtCzFR6($Zt-vUEx58@vU+LO974g=H8%H)<>^`kxJ!o zvBM|gfm3$<SU3tsjf%h0gBzn{?(RRrs|klngEThK-X6-hA|Q$|@|5s7LWw0cIAxj? zAF9QciE6cy@Q2k38<qHj>WrLpIs{_8%u4;ZeNVhFvH2wf6>}p`2_!<$BCP~bL$xMn z)MB-y-zj$=6xMKD>Et~KmTZ#sa?2vsWWo|@N6m-z9~0b(wBXz0y4;9Onm|M@enmxg z0Q?6YGQxV^47Yq3d_+m-gN$tRc|pqB#K$fo!6If(<fT|%TEhwic@udbgPc&XA|OGv zpzh5x)p1STr8>@Mq{`yEarYi`f2j)&7c$(!KUbwd?DYWOuAWqQ+SWf|TcmRYP{%QD z3<AUOJ_xNUgAlrkYwKL6Cg-elpu-8O3ZPd6BG5P-rdt2~#5heB$$HD-00f5#8UV`f z{zRct?e#>}WO<`*LMXu@#-Z_e>Fia#zNp*Tc#?GGqrDr#mP}uqJRyE5ki$oY$U1eJ zc^?(4D-~quYNa2FL(@f*D)t-2>BtPwGbp<tSth{%QJ<X<lx3K#h24oB%8R5$5@j*x z;>Smw#O}R#R%{SD=>~BQOBi{~A~Q-N_@x-vCA;Yd$PrDQr2dP%64!cB2gt>K<9aWj zt=EBLrT~SCdx03vTp#+e_F8wdqb}fYg`;IWKabf&@Dgw`R!+eIjL}`M>zmis+e&OB zR8L<RNx+jkx`W|x`7L#Da`guof<%j`VU2)xMz3m{$5$=CKDEtw>}J+BdM1i2CotSE zSRXaIF0yo=GlgHY!odQ7!SwiF3L?OGqMH?${6rcXBf`nAM<XgI&d83?OBf?t0Zyd{ z^CC*1#9(A_-r=;jnJU#9ZUjGE`Rtpb04-3GARUd9^Gf%zsXoZ|@0E~;!K*_3hG;v$ zHPb(8VtGl+7!OE9$x(oYPC|(Y@n)V)9tMD|p16(!@W*%vSp&rNCt_lg({?CMudk=K zf;}JJ7Ri&$9>r~LGzv=xQmf&T%2e8G#Vd;BlN8wRICI_@0FNjX{(U7Wg2<(U1_O|W z{6!qzdYdNCQlp)p2k11W!Gh$oQ23FMRgJ2ljqha9B^@nyCqls1)wUGQ&ac(KzL9^} zogKin@*>G27;RusBu|h&PKGD$blsBz0$ORehWsK%Ur3t#*5T9=x%k8d-@#EA3->k& zEb{KC2`f3xLUou~gnKZhaM&k6axm|c-UL&QCgU@90%aThasR8p#aipAtYq1SGiAmp z<i!zLTQiasU?=Iy<eL_+d@kT(p#l;$AgIX*4t|#)Sng*1Mk|AGKg42KT6a%jElW;- zC?JF*g_tIC(G%Jmn6}-ku{$3lvRDah#0gtPwoL@Y0XfxGV%f1D(QHs&$UX)DSA$c8 zNVH*z7tbDKm6-7v3djq&6%q_a=mh!$XO?>M*wxULM>=AdCAiv=Yo6;sQ{GcnLR&bA zZxSePN*EuAiWiCuyRj3izzginrPVuet`D$xkTOCt4gRhHNh(tqS=AIyfgGdiZv~pP zv3ce#Wdv?nfXiRE>P*+d$<`=OUQQ}a0cU=|IwVe&cSO_h^61ydC{-EKceSe7iA@u< zYHE>dj%%6FTMH77LQ@E1PnJR5qfHywfUK*-f5D;ALp`HSMTG!?A^XPTQGkq6q8(<N z|96ID!1_t*BJNB%7)ba`6NBpO<Qw>vNmA$G#u30MyXL7|g+(ky1hV!KQUdMqA=0fw zzW`vMl>n=8zE<5Y+|@dEZbd%CUqlu(&6PTzu)7CMCP`<GB_t)$D&fr%g31|c?gDyc zQtxW@78^wMC9FZ$?Q8;sNnVH*%*k?`JlX&e_LAyIE$ta&-!?829T-zc6&1MwyvaZv zbT{-i(cR$4G2Lj?g-2I{!XM_YWI7_-8Wu)fi55>*B?GPG(baI+=N`GfusQ@KN#=Dm z_FxfXn?X}-Dtbo-zUsPpAq16kpX+Q$)@6=CRaGzdjT$xxHof|ub4M+MZ(#z~?&wE% zE#u7P@=r!-Hw?T|Zx92e7@TEt#64j>kk+S!N~I_<ykdpYW7tbO&bkK5rO#3-g1kl! zmq&L=@CtEWco^gHU<!BJa09icHarz{a)WmN=vuh!lIjKKMe$c-3DXm0FFipRkQ=8e zV098htNi_hZsEG2nuJ(T>6HPcgm#7M#JX<G2-QS7au<jz0uVfHCyn%lMQ<eWsf((@ zl>BmC9R*QoIT_S4_zyvO8Hr$bz^;Q>%j>EE;+k<h!?Fi;27WU=F?LpLJu&Sf_=<Tl z8~3^zF$m#O3eq~x3GGg`^`^IH2Q{iqE7e|CAM_3pKyo4Q<?<%>39%R0#!9V}QNu>7 zlvm?ya<~%&i_3(G*+f?*=O+-dO{mDEVnf3Ny8!}XO>ki^nK@P&I2{Pr#FkIWU5>Ny zYt1cjT&ON{p9zW;N?|g^0Vg0=2uBKQRF%ZT`R`qw9al>h%1AS;?L?g6NN}+@>%(=X zKPlF8khwx8sS-V{w<jUOA(MnK{15|=m!z&)#uM)?w8#ehssW_TI?8jd!DO6G@R!Mq z>M|uu$XdO$P@tpURV1O(yfgrGfSn({72MrgpqqnT9o$UZYNg6Vk$H#4WnBvNR-d#$ zR3#iMWa(omkPud`kRny}8K`wPY$NB(KI3?Du^>k%J#Y-NfirWUTlUpq4ICKb4xFh( zj&dj%fw>TCMMRnEN`Dc!!_<972u^FQQ$4>(DV&~=fkKGE&Vk}LhD{hhzCk<oo10Ds zhK+{dtdhFe9?L)Ia977)-~kMTIybZ2YOPpE8df>iW8bVLi?KjfS)u3~;Nr2|i_Z_C z33ktVVZ6}Wk`lGh5ik@&t^rWu5IJWNo*UtB><;-+FPf&<D@DCjX+f#QFvC9d+d!8K zk2a8b0(OwNMwQS<)<w108*1cqVk7y4R}nns2hdz~V31A@x{j{w+y!O6F~fDJ-rVd~ zt6|@pE0c#whs3rVW++j0X}l^kTTpbu5s#of%!>m+sv;5+BsokR>_invsLh4e0EBOl z!iXt0x|$}}Q>&n8MLKG$3z?4Kfe{<Bo9!3I%gG&;=$xR&T&wY5W%<xZr0788B+Uq~ zLj-k?r8FCeX-lI)JMBTZXszKdBk2GpRybDCUyT-_qbWzz``F5&!|nvQLpDw-2ReKb z0w>^V24qP+QeCqw)E9Pbaej*&J0_=OP8t;lc;|$m4de)NLk?O!q3iqI;qWW%OezoP zIL#EJLT0YPeW|Cv_4Ra{@A(p2GE{^?0#XJZBZ=(jy`cn!Wv;P1I(;7638=_~!;aF? z!DP<`wB(VpF2_i0k`dZY;|q(Hq*fH#1OW%ogW^Hs828~%(MMo9v;U0lWiPg?PAaNz z_J8K%cXK_i(;0}dNV_<jfsb|v8R+Eu1JlNqG+-~cbh6S1jqMXKO&YY`L=V4leTj<~ zoKZ%edYS72mCON|CFy`cgIJC^MsWB!(y9G0g@Yl(42O0Kx44yMNd(C7Ljm1X`;W2- zz%yYw0M1@O^acCDnf4xjqOTzCcI#T@XTm*LCt!)v9GrF)>+slUI7ND>h|w@(H8Dva zK<aQAkU)2PVby55xI<t%mkg99C~Y_eTJ;(p4E++7k*d*7M(r6N4a)px7B@+DSPF#D zkamn@O=^ge;l3G_IZ`GEn}-(JmcDi`33YNR;cj462xRUMUDiydy7pUk*=mdKc3hCL z94H(y;-QyG4i-fIVCX|Nqf<gFru}&FA(rO0PJI3R*Ty$mCO+OTk}9MG<CG?Jce=Vj zNijX(>^xR6zAZ5PRZPMRn2%(c^k121I`qbmu*OcVoXae<-HFv(BI;vH*c7lgk}ng0 zR_XNsz1Fm2&$+10GgZnBVYt#K{Vy}$51S07E|?SaaPk$WM0rllvFqrQbg)#PqL5Dx zqotCA-64-)RwB`eg*O=I#`r$dH5nRf!>YGBh`lz%shBuz?PfXHPj!p*1sTiGscuHf z)%mrX8!6YUlnXoLs%X)0&X{|<dfY5gQYyOKw^i!8wGNzYGL{lU9h1_Mv37hI_`54R z-vppcOQ=W){bWDn<WY>t35^pX0XEXzN~Co4s)%r{XS5%22;@n|5l+HK5`cC}I3I;7 zKDvE1WY$3&iJt?{xuJZO%_=PsT5H!+C!1zH62u9?^S;3QVxqi&hN4T`FIb&dpC=NA zyJl_jC6HOde{o*t4!XDyvNjKgU#03nnH@7eD+==Bf$4{@D+f43Z`!BB?_xon8H5Iy zdLZV2Z6E~lBt?UHHvC4Vy;RwSsVjh?nD|+oz;G4S5sJ!@h#mD*zBA$Adg)2@7XxIk zHd}KXxRihvg4P6@P!R&f>7%w-V4trO<*AC~Vj}^ZvJ_okR)-j*B-5tk3{0@F081y= zCee?;LUp<NAf0VzTds=JQ3VG&Zr&=HD-792G2H|0CxTsHnu14{9M<=zgQVN$^uSpU zWYA~fa|?ak2)wJRpQWL}fgdQXf|~?&AO2>pNTAnLX$An=*={ZwQ?-jIk*f+ZT5x67 zxYbaCt}k&sOJvz_06+=_t4G2wW5LpAz-6s%XG(8i+6&DtIiIj%R^$!GU8LK4RhjO1 z_8oQ`QP&Ae0A!h&{qU;N+Z9j*$Rmk&kuY_5h#x<~!&N{wTf+UI9Rc-2;^t2274hg= z>5ZC6mW*6nN1YUvjMTH8oox6)l)*5*l^s@uc&-A-cA;d6!27FK8xh&7qYDrKN<;z^ zGM<K!<B(Wl_7m69K?Un=CFWqVZ9~hIlBwMfiKNv7<T?W>VRg$EK5A3jhuQ0cI_U5^ z*k|2pbt11Hc1`w%U6SY%B4IoNVbtlfhN?rlkAxxEOQ@qUj|qFO{emS;lYg#`1gIV} zqXz;}a>xORF$kIO2;|48oeXvRE~HppQVkgaXw#w;er?hPz$~M;wHfU8qgW4`Ob(hY zSTrJlDp)C6RGMwgqMJ>_?9o~f)tGR&ujWC-Ma8d-0-Fv5-&C1%GcY&&a(uid@wtq< z{FgK%D;*R5?@$OXJa{)kRD|ZC45RDVMwFQ@j+!HuEwv;rZO}mL0eC>f1}X#W^(gl} zwZ(O<>?nzxQoHTFT!aDYl5ChA1Q7z+aR=MS`pEU<gtoqnYhra`GN}_%z(DkLpM-QJ z-@st{Yx2RYIvF!^)WBF3CJE{VUgzG5Yd%P8Mtv=iIljnKMU-0tb_sF8^p{)z3lpvv zurzVP5<?2(6DiMB9mZv;23+=4^W}vLt^mbc2EOmZFdO0tRb>tr+*FyP88%yfZhqS` zCKjB-DG$;Z3r$ww`|Hn>!<YRqM<05wknAX!qzDocTI+6iyVmRJz5>>K*eDwXW~CGm zX-v=*iCg=_ZGRN6^$ur-0+`4g1PL=GX&q+kAsCLO18;Y^*&BV6G+(4%!tTq0FzFq7 zujq}Wy{PuonU30%H#g7=vb7trW_yoBEBQqTh6;%fmvElgI*c~Eq@h}I6RsiZ^xw<0 z{#{B-l};s>3Pvc2!6~7ylFyL%F>$oDPc?qi;y0S*I3Y4q@v+L7#QKz1eHP`jX^FZJ z4O%i9B>7;ht8hBgNXV&Ce(;lPUFCN5Oz1BvDJ)@vP8|eDkk07gZFZ5Y$lX2_zwR%> z_9deT4P_m`Tfv=<oG0kf?bCK;w_mzR`_R_KBa&}&^$PJT%59oD$FJ!{X8|!~z;t`? zU8;7;G>cNm`KyQb9@>S~in0jPsuUm6DQOnfg%dyu0@R+A&|bD5SX8xLxxsZ1zh`a7 z!~|gqEO5lby&kdjORXNHmbHGmLB`DSq`|1f6H>4);Maqf;y0*zqW_VEMa6*mT$d~k zLipSW(9Ny~Er+6#Q&Dz0r#{(~Xmbtxz>Aqg^K9u;t;ON=!;0;JC<{O;#T?!8DbHp; zb^9K844ED@hopBWqK#dp8f(W0$z&Pt+Yi;lr4D$Eu!L{>LBeJsyRg2zMwV)06{|dD z_G-5^xCuWbIO&=@F|7VXjOq0rT2Wg|B`e8idZVjF<_`U+*fxn@h|oEF($&^CsG&u6 z<IV!%pAeyr9*X<HAiHI%p45fTV}{i#kDw=a(twZ-%QTI248_8ChzHib_B7DK{jA$v zol_#D+WTrwa1{BY0nPv}gFn|$^}SLBwxkNTZ@|Rf%c>AEOqL#`fshBF#HnMTmF3Ug zCc|~9?PAdVkbV&SL4msn4^`6|o>~nVZVM(v*6=$;@W|P1Z;ioZ$t*Nhn1~2J!qBj< z!!t#Oke=94Wrp&nfEo(eE5K5wMGkTk3+%+J)V|rG;$f4zhXtOGND&U6Cc|h;axF#3 zD67`GJV~QfJ*w?fV6I85PEA+_E?!tEQc1(Eb*0c!-j>RxKG>J2_y<}li?T5XaKk{L zVPF(u!c^>i(%NfF9ou~{K&A;x9%nuyXxN0VFW*%ojlox2Cb&=KKo8}5P9=g0wVpq% zCj-;6C`fKb7A7HW5Kq22udeTkqnfJX?I>I+UxW$5_=-(WoUPsCDY0iSpzokdoLu}r z3?|zpr7VavL>|1VSm5<!56*-~l{}ts=({}VT!_Z3sG~u;4;1R9I_y(zU_u5&NA|{| zCdsZ7bDJLT$B2^A<Yhn$;I9es)?8IlO7%7$9v)pg_{bi@g+_4gC68gw^$lteJau{y zEelnD9}WtpM!gaBDPkWF5ciQLumm5#E#5KC*`bOt+v0J-6JkHdRtTB~Uq=qeF*X+7 zC$zm0szplEBQHS}z*OpKh4Kk)?;Q_5Mi&q#kg>Q`h)MCOBi`d#uCe0)^DT3zd<!C- zRpACC-HvH*)MvNbcuF&IH)8_KE0SK4f%X=KPfROO88G;8=c-CLjwIhbLfnotA1%pY z9~Ra-LWApIK?X0_mPov&3Reb6G$l1KvguG3*>nhcbYox+D28<0XvwnzhL0}XbQPvo zfbs;%;`6}HsTwiAz6J%i^EjR%FeVTaV-YVS!eIS#JK}7?6SG4ST~c@9VsuhmAcidG zDQ#~y9sV@53?Z|GNd~I)rw&SQ(-A$4Vo#>#igcAYdT&%XstxPJ4WSc&GXRVb1}e{7 zdj@y$ZqqU9k65rIvIZ&*6evvre$<vpvstjI*jZIJ4>>5{Pa#b&`Mt9e_K^uCPrnXY zNSdB;BZ0e%c$b=}4GSeJdb{2Z>j(2LG^`}JK)Hf)58#NFExoN1uemGgf^kBl`;x~X zK*&Ko#enN)>i8eX=+kjS;Knx}9*)0WxPuVP337;Rg+zvNl~wa;+7d`{(Y|`Xen=N% zj1qo9o-&`cMX;!z`hf<kTfkM9Z!T<tLo)LiNhs_`&{ydtWj7%>fXJc&V1)?Bg#9Dq zN{|U#v^-GbU<E{oP}8k=$I}bj;FctJC4!`q7((pW_As~u?XqCs0^dpb3k$q$?ceN% z?^f(WxS0u=#t4a>L66yBMZejpAhHXail8H95JDYyJcOZrZAVG6-iCz@h~$b6nY0r) z(S+gg7nR0QE>WyY7*u=N8_`Q-PxY>y<3h>IQbVvMUTbn33c1#x&?YndxpD}4l=xb& zCeJsnv{5;@?e6ZxFE_|Ad8S-|eiif|F|K-_rZPr@_Vqh$1j%fnS~|f?62XiM02Gci z!l#--d8$Wpv9Za(dZPw)wbJcUH#?J4Q>>hd)_rC@s1N0?W~Ld83wy(HtD<&Gf@TtC zM)Hm7l6g8c&32EUxn;1aN|I5W4kfG-MLTRWEwdNkGq;Rr<{HI>a}0AEVVI*a`#mSL zEG4Ns76T}PfQI%O*CmS(;U}UJZ0<4O#=Cc&cWmG4_?n-+jigh8+ZFvDln`es!c(g< zv)@E=2CDDKZ5|dL=@#9B9OaqT-DkgxH+aV%J_d45_#owKKY<mB!z<#>YMw1N))at7 z50P6zp0Z3xHYIy5HR}SRaRFY}+rI^gI=^=+*FzBjD#u2{Nr5-A((cH9>+NqN`&+<B zP{{-}z8Q(kwh+$kDEGgu$yXrUw6vW|x=Th2R7VmTphL6=NjF2iZ?$vRDgcpH!~w?a zItAP&EV|OG=7r@EpclpNp;~VQ0f2oM#&@Iv?52Rqx?^>*B~}4mN)RVGy#yIfq$34L zOPUv?C9Z3o{)~+ffS1Bp(JsNi1-2Apq4r^gJ;yt-xj1q(2m_<p=@X{2pNXbDP@0qr z`a;B>{5SBw=dwd^-;hDVPeGHaL5GsQbK*=lF1l&sqM6naI8`JynZ-yZn8YSB0wT*Z zt+U&v?_q5es|;J~%AW38&@`rn`lD)k<XUDy3u~6vt)IIU?T|FBz?l(&$0KTks}Ejp zHB*sgSDft4cqr6?`Sr-V;eq&K?*NPiR?m3r;w>e4viQIC)`1!8``wnc_m%u5Lm4(m z$XGJ8V(dvux2g~ix{9+)t+x+M6@C0Zm1tNx!VlycbnrQO=p1wRH0j{f4!XP(Gc~}{ z1==6*3>Z0X@p_mN-G>+7y@l+8eX45N5VY{-K@O7_UuohC@>aa~;jRAJgc^6R>+S#J zt`h(UwOv)rj}i)Nc|{Slfsm*nLZh277+L_{PCQ{hSIntvkpPGu`4qv1Nd~!2qGafm zp*++g)`Ub$>l>W^jT=mGL;xWvp)xhDNyA#%(sK1I7FP`j(F7#L^%K~0IXn%kUaGZ5 z>Cy|y@i#2F8)zPvPoEV;s1u?<mfV)T+R)}1mzVJ{YfQB`DY&7IG3D0cyl5Q&CIi9( ztc*x&Cky)O2^vhKm!BJ;1Dv*phpO1r8-?(N*%ziXh$aXtgnYe!#9Lpwe0jgyJqQh! zoQvcT3v+G-Pj>~7z(@Vd`ZzIuPZ%QHb}$HZz=7a@$bhoy1u8{!oY_>S+7n?lkc zfC(?)ry!LmASN)w77Vjr7m1+`>vC6|K0tq)nb27<l@a+gB?8-l`dC}48x5vwr=@s# zz~Vd{+F1bdD6k+w{n{)|3+pUq@YJb@?}Z+&yZxIlk~gSyvin_M22lc|?j_R&T`Pi; z)K^4-NzTknfD^qpY(<5}wgvTul|XnWgM}g%NIALBl`OTo*!$`Lhk}}S=vkOT;_-=y z@c2vBte?)+>Zv|g#~K^V?zn?Ud7T{&oA+B8aOn)X9z!Nn&g7UAWFwu~%)CEWiJRbn zLI;l4<mM$8sZfnjcIAgKJz{h!p(W$K40L|<+H8?Q^Dacs532WI28Cq7BcCU!`h@DR z|B4i4`!j}O+=>CQt-GV66zc}IAra0Jm=<XD(TJl?3R&mFsNe;4MSrH3)=*Kw-<x0p z1RhLUp~NICx^cyktm#q3A(#l<z;L|+F>Nv#S-=}>C{5ExeV)-v(4nzY6TXQ3fQ$oL z`LZ!RR?(_yqk_kwb;C*MkET{7a7z-w0#Pr(ZjLXltjyFq*QN6{+k>g=C8W^@)?WoN z0p_H|P#fEX^bOm6zP}PPi&13wVZXz}EW)&a1m2MtElb%dOHH_>>obk8`#x*}(L+S` z5<LNVf&;EzH38O(f#ToW4A#V}{!ZZ5Wi00IN}H|HlA5J$1E<3}lmJBH71`LZ3XO!V zwn`4d*dDWqrR_~d;*;-5BO1LQ2N1NqB$y?mI!1D{AS^qmwE<>lV?@Xy8WD)UHtjJ= zwkSc=+p8M}Qz&EvDNEFop}iWMGD;wLLMhArQx0$Iuv1ZFg&Y&yG08s)xhBzCbs~4D zr4J^Ax~@hPl5sVZpOCtd{H7&Gab3BgKH0`^UQ{p?994T*6QNPp7>r3tN6f3ZO06bz zZ_X9$%JJE>qg9F!D=-oTI5BJf5-Oz8TXO}*`pgn*k>omn1RWGh!1?IXH1kZpwH>bZ z3eoc0+AE7k8J<C6P7AP&F+5=nf5?nre@xLH;(mQN<tpnseIZL(N%$XJ<)q099MlN= zg)2IwE}c`iP~4LV(Sjwclz`z3LV8ZH&vfY;!4A7_Ce(2`p{H2ZwGU{f-t&T;IQS{K zuG?#Nu|7~T$a`WK>)Ch^Z>8E8dGiCMSMgAq<M_lEj19F)hzAa|D`%z&A1@g4D-IOc z)FEUAb5@gHyOQ-K%HGhtVa}7KCiGb-pc*17n;?svOmPi$$JjJ9SMH_fRCbTT4a#L3 z&7M(`vIvk%#x0m``nrP+FV5)vAN6q5l3DxWOj`zaMQ8~T$0VTgDmNwj-RQ`C1Yyru ze8~du9ht7D(Cf{aDd{OlWF$Z~ZsnQYYq1r=H7;@_5l6@O$y8z=kdSX-n1q+31d;+r zr0S;0?s$ICjWKKbaCR}R`MK^V2ld41j3os~FLr*2P&KtQYkFo|%}A8#sx7@hS}{>| z7I{%s!R}F!Lbq9Mx2XDpUbCEpPm3&7WM{P#9x$oVgYdoXBSjs!cQxctoGXn5EQQqv zyc@1lXuk1M^w#CzYYjqG*HRV|Msz^T#!LNvzdJpMEiQGi8{~`u-2E>0l%?|8*63X< zS_?tY1wv86p-BkRcX>><#<J(FmCFcd8-{5x1@QghE7bRtMnyYcggA{z_5`sOCKJzR zDos|GVG-KIIZ$yiXleQbELyz{Ib8c{`LSy?Q6ZmEZAHXi31L{x{SLhQ<W!hsN{_Er zCT!qM8B|ZWF4>(hrNX2W!@e{%bGNHrne*-5rx<O}t|4;)XY0a)D+iJ>7j~nkmowQ> z>5f{{-we547u7e`7w}GxI}`{Q(qrjLEO)w+gXb$z4Z`ugn7xO9g)$%)E968V0IR;& z(?1pu>5s(&3#H0FxFOPY3*$hO!cUe11XdwYnRr|?03UseR{!(#p{j_;V@&uCb9Rzf z5=nx80k30k9{b-Vho4TMS$`2Ex~%mYkXj0;4g+NeTM_$R|1(#4b`^TqWE|vsm0K-v zKu?k>rLYpVO?<C7Bs8d?D}Z=XLLwtjGnl!&s=xjQ4e$n)gCi1m5NVh&kU2IV&baaZ zuwq=2*nJTfa7p<fTowi_V4%hDi?l5`&Eahzv1Cv#w$&9^=N1y*`%GeWu}(t)OvJHd zpu?QIP+Q!6MXU+|zGR~W5$wbb6~oYF%9?^qx>;1Vt4l4|DRe&glNe%46gEIpx#1%o z8T~FOxW$sR!6=9`OklVPxxWzgs;vYjfly1xpf=nE#s4q>nnPDANhPtRv!St!t6?;N z)JGRSZaX@0g_#9gIr-&M!^kwcLe96_mO=xFIn8y@NFjZ2u{w)a9zoZfF0#&D_s8Pl zyUpQP2|taatmMt+_8<yK$s9@Y3~+~5Xi2lndLQ?AS716T60iV5w+420yv%!_!beq9 z4`Qhx-kUHUa#vvl^H}xE?NwX*cvOtHAsP3u7jmM>m3+KOdKLQmqYUtzgYFFYo{Y)H z&^13gYI8{x{Q9Gu+-Xf82@D`%8u4z1?0WX=xcd-mI$=}9ro#VSK|i?MN!K}MKa<%< z4ghL}84-G0mbj#tYdq1jwYs4e2-}>Q{aI6Tx!63QOvAA6u&PZMkj<LbZId@!Tml1c znO<#JX*l99ON5@`4`N@|AaKbdWjF}iCZEcO^snWE_6SOJ`Nwq)PJph4kOL*iqL5>W zM4E%e(Em<kW%HdM;pB11s#tghx84o{tJZDrJJ*--$@e>u$J+IU7ljnGh?7JR+WykV zsr_A^u@u1Hz_aZFzFlgprxsG{Z&OY_txpm-PF~IsV;_^_m--$#JyLEwRRAIo@DMEr z$OOuHunl@$_Z;bZR|s1|H^K{3F4jp1ttI)=jQF2vL^SbzMv`flSTkt?E|J0E-fzR? zNXX{GQsJT%i$#hA&?cIArV*o&P++VOp+}mYyo&M2NX(@z`FgEz<Nve60Nr&(>GsHl z!XcrQkXt1{upd=`v;eJ$3u+i}il%70ODoAu?yHPshl3^rs237@j+P@=gn{(#_hDRu zv;mIj41WgKqzpaHm=LFjF*xWTG}J>!xcXcO(eb_vG|672+^LF>)It(o+!Zc(E$Sq= zLJigE0OM1Vbu>HORu~ozFu!#1(*j1$gmv8MhJYm0SiB`*>wx<iD=$bkfsYXg2@?hQ zj8uZL1whw(qge$cyFM~HSbh%`DtHF{mJAo8oYy|U!Q71_pW5sf`rkSt0@qp1pL|(z zhQMlv!;CQ8T!7f!V+~}L3h(Z|!o><SXL~%nL`}N88~(P%^6CbLZ;2G&d}_Z6km1rx zBqEe;6}Gel7q|%^k$Ii|EQM=EQ{nL~GYdBf$w@IP6FjOtOg1y9v<c47e$C_g8rWgE z;TaqdaCAf`B&jtR)g~IkQXj7<-x&UewoQ0kD=q-Q8=#3H3DjueJ*KL@anU0iSIjMk zXi{`&qdMD07F~2ZGZW*}*mqtZeyHl!Vyp;vCz%o@o4F<i$N@zAKrbR<k3dN4!^BQU zcx~loJec6d+tgKxJ0q%cP)gEW;vLms+L6A4N+&W(YB%yg2lYv*k#nlS2mlYLVb~$4 zK)Dm!VR>xf5MF%%xcRkI_NVF|)~WFfbZ<y+eg4VvuW{If1&(d_xS$8=?nHX)IPHuc z+z{%)H3@2==3D2xQr)OP&=FnZ!v+RoB}AwX-WdpquC$ohl}^$GM^1RpBM&WnXBbP{ zqh-_t4>5;L4LY$;M+MJNvSV!^K{&EtUqM$6g=fr!2HBan&kt&AXzedj{o&imbpoHB zkV&VhpM*qH8J~vb6TQ0DOST5MDL?^acqCP<hv`bMQVW!-Ykz}SzHmWM4$cu$B|?`Z zI5JgY<L(};&r6EEer4tk$Rsj61LY~W5vqnHmYZa$Ycmsh$&eBcL)^I+x=?wNuUen6 z23D!=@=Nu~G1pxL9-oG^gmqnL(9!dmQF9rx11Qd~rhXITUviuS05v};pMmTkwjQx@ z=;;`p$Xtbbua{410eK%=-Q#-<=SmX5wkF17f;4p#?C{p}O|XyNnWHg_lPGg5*j-6o z-{44W;`a+{>7R;3F6TJq6W=AF5OKz8iQ4I`b*ZnnMRi~fCXR^5Oco)`7zD^Q2Nb7< zYfjbHYB}*+#1mXv;rc-nl8U{GbldD83@SvwPQUI3DwnxpjWZl@7}x}|CCQYreJcG` z?ndn^J(=EAYsz6+RojEk8UjZ)F`#T>P|Dl`MUqH4?JJYzq%Cth%TpA6;Is)^2Qh`l zch<-vYcHCvk0o3y1{$orLBICXcn(TxbOE(d%;g&tH+keDW;?<^U_940J%pa=*@jG> zy-4naT!(0dK&&|V)C}1dg)@bY$f-HjEq-b8DG=I$6lW2*ZCLeK^OR%Fayhm`go))B zY?{08f7w=wRs=dv0n!t}ag-n#A+mJgZ6>P~1R#R>;7)1VFV8gJ-nKTEKD2S%RN)7z z9GG016oHnf;1T7{h=U4m2iQOo=><gO8Y;yW1rBWfk}CSL0Do77%^#aC36Yr4{&oxA zGRnPsM+61|7F1;&!EdY2*>*Rp_eq5%D)2oZRK+jIp^Pa5g#-K*1kUVe>v?ZC>CZhd zPoyf)xv)ghib?JPuOS#hAtjS5xb?zB0gf=Sw4Y;!;T#6%3zJ*{_XeN0kH;TtB1$Z& zV!NWfX&KjfT(O^V?oAC&D;H$ry8t*V2$k@j$G&BBQ7WPCU8qxhwPK0SBs>RiKPw(L zDB<l?qu9IKcgD>m*Qt8Nu07zSD6@p<WDlQqAyd<TXIxBNYUr)B9e$Jq8%-49NcH}I z=H7)jZX`?7)=#Mg21fV5t>*orH41Rqa<{*(vc0ydYi0+H1T)FBg_1JWN~vt`VE+5} zoD)GZc*|tka?R{cyCjhe2IG3-ocFx%=(oD8o<O$|r+_mU*byu`t&ht2)MWShT4CD` z8|aGD*eWI;5a#-2vf_x{ziC)YI<44j1sZpS@H=(I4}+L!1ds0uUGIPu$h~1$K*NP3 zkr?bwb|S$rgH&h8TUHyX=<rG9OcnM@9!x>S0e^-{P^i&_5lUl9TpT`^RG)CiOL)6t z1d$R%ui&I69&>(TE)Aa%oSSsHz6xh+K~x&_1>vdIh1j;PqV~03m|SInz&XV42`EF} zAPd^S8mbePoHcWg%SO^0nCL{fC_R?MSt)d2#>)EOuEM57cZr->%1EY{bwNCH5utOl ziMUMe?NT;Tes3LvBHYJe1bbRS@WHHOLz`xzzT<~{rwVLQvah!1Y)|%f7Qz)~iZCQ- z`!wsIAMD4o?mefuu$<nm*60DV*3UT<WC;6m41xTJ?2(ng|LH~Rf@or1?Pp?#4I8^_ z>yf>1MbsI)oZZy5&5ekm+|2lesyQH!h>$tVU_>Zb@<rlMu4)Yo{BfiP5A%9W&jK*F zg2WLvb~7Wa)~sVS5lO$iF&?txKmkxUfsFD=0fQJg@~j0km~s2c*J>QX1HfHGdN_d> zw10@voA2nPmXc9|kq)`>vk#Y7rQ3S?f(Zb3eXUM-ZA!5}7^-pc9%|{eW$6OCk!{0+ zg8P!Rh1j>WU6@rZyu2y&aMe0Uxh4mY%FnH!&9*!EU90W&^%fZ5JE7@&b9qzkG@a1S z?j8USh9`En74AEnMUWlq<iT0_MW3kCMdU*oU&Ilg*VNC<BCA3oQIQH-TihKua)d!Z zmS_jyKiva+7JiHehys^5`_^mWH)<BP)E1ZG4ZAKjWnOK5LxiI$bi$K2?j?lm0$}9C zQrYF|t5Pdj82iu1yPHCBB<wM9!d@4P0Yn1M<Qo&{8E%wFjg&a_G=Y6VO@j}x4Jh<q z0u5AgcdszB1g<MVQ<7_ih=PT$j*eIJeePu1(_RqQh=>{VCIk*x>+C3TeOb*M9Tr@V zSaA#L$lSvf-gKw^p?Su3$k;TEI3^$;7J+v_xzIwi{J>qRzMys!1lw~fIH24HMMFYx zij7Si9*H$Gl3in?uH<VS0du<ssveASS*!8SI%GBVD2a6)h;LX3Bp%~)WC!Jp36B<_ zvK{G_{s1;lrI(uz6=XI%holWsA5cy(97%wb%n5UC{K*IvQbjuu8Gx@A6qN@rpyfz_ zynSSS(R#XHJs3BgCA7XexqQ~6&6L|LFXA;YYd>Gbih?i*d|t@bmB`<jP8nNX2DRHW zU7`%rAG8(>6<7xjAxPaPzIXoV^6s5Z+jMsirer767Yk+`tXL%QS|f<n65)?M7l{J8 zbPN(&5UVZ`lqLY1n1?z}x_Vr-?{r(){f<G7qF<6_24A7*MnY)bVg>3N#k%nk?9<+s zgnfK?aVdV7DsB%<-P;4D&wxV*Z7B#n;a`NR)U>_3h?=r9(LwrH=pe)-A<UnwiTSXG zIxPO(^8G~aHwVLJIgJ6}uW_b=OGD^epyvIX`Xf2w5F<k$iVjA7%<hQHF4@$2x@qXE zn^zZ0LyQtaa7Fit%(ot^(a(@8{nAY%2n>jX09IGdKxBTH0ccIf`@lEAZkGn2S%5A? zzGS1x%xbnnBW5Z<iAl<IWn2^y+N*MglS_3CB2lr5u5We-B3Q6Za<}~z=b#KH36`v( z(-1(GsydlVdmi@vcjO%uR~J%7B1ylRzl`rmAZ~ded>DXg^wae8FnoXh3mvA<N4Bf+ zD}q%PIg~I(6xs2p?t2;*K<WAG;uCRpxYhU|C<U0_KEO{uhar)@t9#4v!?b<k|8rm6 zV|#4=DgTvnSTO_edLqA?ml8L(*Y+1sR&@b<P7FmDcz9;gQlPx{niSwNbjSyuo=X1+ zZSd;1<Lq`xUna{IWCR(}ND64PCr(ns!QypgJ!H1S>J&qB5~t9g0cba;E~{W}m*(~> zE^a>`{~@`Yu7s8k)>nc0nh$X{O!q^k-Z1N1NF2w{3mFsVkPtc}eN#uGV9u+|LOO73 z4;rIw3A-oN=_r6_;NymB--j~<_q<lam8x)SA*EbgURSJd$BhpRN`hBF0z;BAkeW4b zaSZ;sZ<*D!ew9X8?--CVrm4;88ji+gaeI3y;kh5o4^tadFJRBgnWGY#0cS%Irflta zox-5?wbaxW3aCz`u0;MtgmHn*1Rne-+5pYE)PJa6j{v*@6BQ|8oLp>*rr8G5s{bLf zuDu2Lb9FcKlaTj;p9EYRRBpts%^(;y7{jdmt)Ri4nIC4Bz9REAgdmn|1{P<VP5|_( zi*T?b;Qp>ctqVK2`XmRseUy0$ZjfEbhLnF4KAG~(Rk5l*Y_A}xomoEwOqZJRicbgJ zeXnn#Ez!E@HUHSI<XD&^?1Z!neo~HB-L7nJ$0)hFTFBD@hoSpa@}>BPkjd`;79GV@ zh+X)H(E%$OOIrb5WhH`btqEgx&87wfT%=6ZE0f2TNZPLf`g@T`7*Uh<vaIheI>j`v zl!Oi%|ITb19Q$~#Ssrlc63{T~p{t+nmMi0~y45{wSp4<|r$c$W1?Bdff2H3d`IYbR z$pU3oEK82LoON5Hto{64>MXWvmECMFcSN1!T!F~e3Q-E;HY9g&OlZ48av9Q>8xE<P zyCB|iR3+*SRCiJ858Dmeq?AY*B=ZyVt`Z`X=#2<8e)8^S({)QviO1aRv^pjHPAkCs zRf_i#!;RhAT$2ag%sY8r9DQ27iKZ$z0)aClyXL8Kn#gQ0tG#*px&4s(aEjekmX`m7 z&jR*_vlgEL=$BO*P?z@dS5)WS{c>(~$e?bkQ^DlMW|xDR2VN&xA?;-ys?NdrK<kW# zPE$NdF{q(srfJO1qAaCBpZHlKPZu&O+Wum_<1`8;Sb&M1#S^<a?WQK}v)`txG8~?O z`3a2ULm@t|qxj3K@ugiv>N%9b1oQ~BlJwV`On%%pgYNxVJ(Fax!EcbrikPEv1WHc7 zz}-Lk4LPtLX6@@N)OZ}A=^_{r78VTS8nFjov-jKyrk%JMYY@i=Mw1Cjx?i!rXBlDQ zzN_wDZ*&nGgnag_a_~O};JxuYFUhR3zH>1F5>u{8<+>|&zv6$|u>a{Xkm*|x#Dt;( z1{+7)*!OUAT1S=d7XqW;3_>zuWZ@q8=L5+WS+Sy$z-bm$H>baS9?dgIw8&PF&B5?l zi>Tl3hBT=k>MO&sZzkg4_zop9nF%oU0pEl2q8&$Wm0^3fZ}dI$#s$Ug-zfKAmF)lk zf`=X%DU;AwIVr1O`)0}}ONVV=keU#uvh6lo&3M_=b#Z$S;mERj4|sm}fupeE619~n z53yNTi8AtP5MxA1jq>(9@WfgTfASt*hCzdZ9)GtV8~=mGJS~QYcp#bXNSdUuz-j(P z@1A;ZbBh#_SU~L8Td?=7&R~FW6XAaRCpg(s$;ay6GEq{{D+wTj=)f5y1G^PGHq30% zNQ0=ZUuJvrSm`msUe%}Ywh&93sBj|a69#ich{51=QwM+Pj{B|v`Z0XnjB-ql6*>H| z2wj^EXWnZ@gMky12|x-WE+le87z~-38FoJ4DmU8E_^Z30(|eCS6V{7{4K&t~6B`em z5SqhS>q(@E?{b}!q`DTku;X=e2T)>cwdloF@!nd`Sb5OWArB4L4k@)}t8mk+-0m@t z6E0Je&ukiV4+R#_9HPIKU<o0P&R|$G&uHl<f1oko9>?c#cBX^p>`adwf4MJi%O`*M z<M)rhbMCO`p0hJCaK(mT?wIq{A9X5z!|EplaF8D5P$pa+!g3_lcj`8*y>rnX4A0K& zVN?z1@3qcu1i#bdwd2;tKF&A44OjjHK(lq2ECCAUaJ8-xq;C&Y?%1eZn7%;DCG5qU zB;AZDT&5)PF-F+)IBA#d3G2}Fs2a#(rA0tZMM5gc-eh>DZRpD_BDwu2uE^x=FLHFO zPwMO+2(PaF7#>pB-P?Kc?t?&7a(tlznNkKygxSHo2Whz^ffwe>(H+9~&6AwrAeQzn zw3wIt90{W6;10)G4A6mxA?+2QBlxWU{7<_z{MUb(VPVQYJ2OQ;ZZ?k5O`}sC+xqaf zresDF(^^FwT_?UHu-`!g7FW3ptjpEks?W9&N%xCM&A@G$a~MkOBJ6}X+#%<dbb3l5 z!vVL)tYUIwSjFIYp&D5^*#d5V`JL(p<gCA!q~6;_2@H3!X7LkygmIJj5VMC>h~@|I zj%a-7%_}Xxz29j0;^Bs=TaqnTB+Zq1AQ7|X>e!B^8XW+ljBh;=U5XHvLA-@I6zHQP zOCRxL<8@y!3vPv7oLA=sVX!#C=>$|b5c1dFJyHS7Cc)a#rSkrGx6V+w<=@_JVk~LX zFBNGyl54_$SViSP3Ij2}kg%uIISezzrr|xun@!wMe9-pl=(o!|Q~OFXJU}nA!Ijm5 z-C%Qvi+%N>5=Rf8#&j#leMR$@A&Vf#`N`zn@+Q}ocL!kmk;9Q^_T`=n5YQt#AG~H9 z7{np19r9468%~7X-R+{<tqK!BMJo;%W8`@`L_U?J?R0TB$9>MgW+zQME~}KFB>998 zw~mi6X(vu8SC=cBaLvroa0lVm0A>uai!(Sj7-IdK>W+@p&M?Wf`lHF*UVPYYW%?B! zw!s?9fFvZ=Uvb8O5bxjEE6mpn@cvDd2Ec^<2Xt#nE)wFGkkCo4c>m5`aR^$h3w)=8 z`zSHW$o}H^mczUUGmeH+#&2eRWBqTp*J9U~5YvjPvHckf$oY+p#QDus?*CP{+p4UO z1mY$$3PyERb4~A*jCEBwu&u{BSdn-TdLCLKmE>+o>&eC8bGbH!eQ?DRT?*p}aVrYp z!RG4lNqpY6f$Y;nDnp-?P(1BGi5)(zwwB#z4sLUWFjvX8%`QX|S{ngwOALw7rsZ}a z9#1-E$?^)QNXQEbs|fboUYj^MwFOagJ)&ug${|#`nZ=evEIBt2s1S-iKk40Lde{8X z<km_%xpcNo2XVM|%Kw0&b0sl{H<F+GruckCZvAl8(WePaY(M=}{j9#yOnZbp1*(Tk zDZXcstf7vo_FG^4*0l(cQKkYb#u>_gCA2HZ`#5|!PP6*XXY)uHvx6<kZXj_2FCC{w z=lYXJEO%<4xDJZ(ChRpG$APEn0v)(w_O~GvHz|QAz&m~ceKUJ%-G;wYWo%OtG!08q z=&>|m=n!N(P25&N{6lS{2A-}e`eg=bV5cB*^8z*S@g|V1CQ-bx8;5f_2z&Q&vT4?0 z7EU}?l39S{ishG>=%0yFB$WK|wzy#&A3Mg$69O*}#uQpx08C~H_@-~S9fJA;A#CV{ z0ikkO#r$nQu5Q2pF`E3UAe?~lk7EbBq`I{L1hxoLXCZtdLz-k-cPG6o7iDz^$QOf7 z{sYaH1STql;Sc~xK|I6e%j}W`j0MGog&QlGHQ^pS>ipQ&8k-m=ML|{$L0E%_aN|OC zu@~kfGO`wpTR?CotTBSt?5ki4ZN$(4{WbnQ39njLpPUlzN0Qz~-+)mE)km@hdJlD^ z4dTjlz)57F(qxtGq7TLHLkNw!@4sbf-CoN(G*TD+?fl>0rHcjANdYxQiHDt|G>&$d zxGbv3Jq0_Zo}Nmvz#$5WR+-)Iul(hRW=F6dHY9}HNMjbuLweJRaRA~xJ^g!eJ8*=% z9_pUe32=#wVsP;uNqA(zXrXR;m=^l~VI>O~e|JpL0%1=i21byEw0<-CT>G*z1Z&6_ z{zm(%??^}da9WRcCdnz;ngbyqDnz&~(NgSqv26LzJ`}ShvO$`x5mrz5e`K25Gp6OV z(sPXB_*YC(w%b?tSI4vmR9R#jK@|rEt>ApAO`SUZ=awx9!5==~Rl8p}!XNn}n8XSB z;;^i++W67*siQmNzDS_X?^K`Tm~TPxi&;u4Jj52To*EaTo7=V~F#8s7#`DX$5p#{f zP;Y$6s2|qd>7Zn!$k#X3=Jk!pUd)~HVM&Z57m{qG72p#$v!++<8$qBE5uINwibUkW z6bXPgBs@i1K_;U!_@uTk$Pc>sd^0yLzCx`5k}Axw5QlZG3+*^Kq)Zz0xYar-NTCvX zpd!I0uxyv^kQUlFJ5_WD{0+X7nNtv=AlOFG0|6|srrQRMD`mgjT;5%3GT7Xq01p|l z7UFTJj7DH=2aPMmzJq>BX35N|g4rcMi!(2HBqDNlp>tgLO2I`un~Cj8<v>(#L5q7< z(G>C(PzEG^FQIa>6oc+YtA!g@WP<N=+X46iv<oY;z7vFnm&R*0kaw!dmVc_%WZsFg z+stN>jOTa>r7IcoF^h&a_23nU88i1a4t(mXr7wqNk5mA=967-0Ipk-fI{<81DN`GX zFqrU3$~5D|Sy8p*ca{WmW{W_5M7U29cX1mOmIljh5t)TQRd?8tcZFM~?hjiosv;fu zA?LpHPwK)V!2xSc_?y6kF4@B&OiHoqtdi{mzU6Ww+0!dR?u6A$B1Nq!`#^8W_?C_2 zVe%d*Ea0z+VLU`PB8-h|_JQ6bZFa9XYbF9S7ZeOc0|)>ZyYm6x@?PJ9`~h45pxxmB zBLmc?i@Cd})2~PNf6BMqngKwPX|%?N3Q1Uk+|Pr)M!E*yIT#hmz7?>Q&^@A6N%H1k zg1f`?$j^bw&%S7}*;V9hd>|f1audw9goHh0W*_ox@>SRMR~5uz0WY$%L*G!-pFK<` z=~wBC>aT+27a?hstMHf?P@+BbSFP+<L5qXlcSw(=c)peo-&gvg`l|qMvt7Zhur9I^ z-j9d;D&izS6Rv*UnG|rcgi^S!mazLRL7W?N@quP;u5TjNrYBwy$6)U0FrfrV?9tRQ z%WV2Ap@Pd1_rd5cBm8nCD--xbd<0E%Z70{(HD&4{(VakhwnUgUA+yJX2J(<oyeZN# zN==ajF%5Iw%wnqo4FUwjpl+!MU|6esQ0yM6n9&AE*P`4)$Kj?XFUC&lL8HnkVori? z?*xjV8%=@u6H1L_H`qb%z_^<{k;7>}y`r&dJfugUSSr{xQac))Riab$GvYxr8yZo2 zoRy@(t#D^8MJXNY-%VArz~gzD54~E$O^k=EVwb}~#&O>i?i>T$!l%*&_6)v~uweoR zdqkp`Pg<~+KZM`5X&V-uaLoCT;2CiPsDuEFA=zkbK39;!d_x2N9)KWbc7%At2ndt# zup&@f*`euJ_2xY-MERIm3Iv*PQIba>a*%Yf5jm%DS++SXG%(O(S_ry7v|(^yL}WOn z_5?kJ^=Zaw3u~C!K!O_p08adwW<rZpJ6k<o4%UwV`yDYj)=)YBEXe(r|FWGUT?;j| z4@VB{v~bH3{OR2!1K;(ax-mnwzJDZAbbs^L?QSG*K#<)nk(vB9%_0W9g@*u!uyYhd zZ%j|S!I7ih%)ld<4KV`qM-P#>{0+fDqxGlhdXi&FJ0RIW2#hwM3g}m{1rRAx?qm6W zm_o*(QwJMhv>Ma8v;@H=EaBEHWzFYAEBx+jg7W4BKGwgj7(vQgMT<a;!;0V*JhBj^ zR3HJ2ORAgu)Iz)TYoIP?ok!AO=J@l3nl*tQh1^Rv<#FJqjz5<bJz5&h)%6M>9HiuH z5u^tkH?mX>>sM2&&#WP0UxA<D4(4zHSC)ClXbUz(x^?vkCqM*?EHWlk;aQON{zu_Y z-;~TS8XsXOLjDB2NXO%}F+DX~u5PF6kO@yvX!A*Z!Z?YC&ho*0XsSQ6VJg@nh+{2R za;U3ZDrAa|(0Kb46}RtqA^2cFe){$=e_y<O_3~oz^zGZH{|?PBUY~`;X`l(^W8;X8 zGOS330AYmJR<f?!8)OzqyM=Yh@}ZIz1bu=2H<G(4MyS!qW+?=`0!OT|#r8hw2OlMo zQkH7sP!vHx1a@mtSr?l9$TYjlekcc`35TE_@u_2-stumnob#Rg?NMK2=+~GO^6|MS z=D^Qe5`Cy_iedki6Ryq4S339GSHipmK7gd~HPA@0h5>j2^@P=qMI1pwGe+E9SUz>k zNjdq_`sVtLF)T=$dMj=XARN3Dc^Md_@mc{vCU=uA>fIxq{h*Z)z2_B@zil1h9RnZ4 z>2RHwBte-vIJZ1>6$}{^;5#Aaj$_dqCJz&Ml#Ea%idt_U`kf+=EW5EmH?j^vuIZ;} zbCEu8-fFIny%#6)`GzgbT?r=pyuR7?d1zcqP^$pG^1w&H<L}wiW9kI!WNeK)tM|Rh z`nK)6B0GUdpY<f?7&-Nln38dpxMN5h!W651Vg9o@_+fG<yiUc(7s@&)ta(7a7dWv& zYOG1!!t<K4B_cIWV>VZ{F&zhE_q{AIU-e?R!AY$OS2!5}48>+?awA0D*WtAPs@FyE z&Y^FE?SR*Y(16)poi6OY?s6lD)~|Xaocu&e3upy}b+LY<V?A}>NPB+uD}#h23(+_6 z5U5rVk1RivucS@C`jt4sVk`+_$~jB2rQGanQepM!&KNz7J$)}CO=NASh44Bsg%QMP z1O3g$*gWaI)44Cv1j~eklU_OOh>H@G25LYciALtwB33L|FD}dY9j{5JJeHRGjbwSq zbbwDWE<okOo}H$+R&+(Pm*<t|TORJ3`xORD;v~2z$froe>U6H_40Fy{{oPir(DvKi z;kf6_n*o8qko1z2t)Iw}8S0K_Wb`#pcdN_Ga|4*1deH#(2+g7AL%@#a3xJLBB#w^# zpkMSe=G0M!HDU`Z5Ya?nJ%~qKA->v%YKKZ&cx^z&b-FL9V;H|A%T`M|H)(;{BO|UY z24X`cGxU}$9h~yvLoZ2AZEfehPj_UC@K}jKCk6_9q0RwjZxQ1XWn~44KYk4k3^*KF zx2H#Y`z^jo8Vy9le7IJ{2kVhk#o=mRS+3xku!<8HMg19GE@1Cw$T?xJ(IMB?%N=mK zW6IhnA$2(dlJ``|-1MORLA3xOR6J2IB0cC!MCqd_7o_h1XxF7c*f`K-;rI;&2=Gqx zI>%S{CEqku=L*p@LF$d(^jO8}eej`P1GNfi(3SgLu#=+1hb@DL8ql&irMesM<aZr; z*d(b79^)`0V2rO{GKVIIXdpwOE?!TZ&7}39L<S-iis~Aw^~OUuzN~jjX+^&PRdcB3 z*a$}|e01hy06NvsC%k>}FQYbEvr^U7a>uAyeY-B5dHj={o)OJWGEo&R>tl3&Xb*T8 zp)A-^A+$qQwe&p1gUp)ojo+P1RAli1fFCnha&eQ23=vM);=4Cf$}uq~hu(AI&+l(% zdtyRS)bnB?k6ssvD}%@z^f=#a7&>U`;=4l+uIz|;LI5MqQv5oH25?<UdcRq2?^Q_0 zhqnzaiG+1E!Lh)?Xs;cZ3w2TT=2JjVpF;XfU<uHcL+Lf#IXWLS*aPYLnA0Ll8)@bw zIM4m2j&d4#i%VF2;qhSGCsl23A*|#o=v0!^21|Ry&LyYzeH%{qYpg@5SsWl)hMXw^ zc83rkX}Pm2V#TQ7EfKW={(qK7NDArmZZ=}y8SO3tqsvDBf%+h6qWbVplF-d8lzf}m zGpCSm@;(#aM;9-JXVHh=qlC-HOt^3HzNq@7F>$haRvbP`B<jK?@`I*9onuzhKH~wd z{cYMlW1F?*Eh9mnOoKJFzGPRR)j2*A>YPas;kSrnEffUdXE65&p}#PIFU9<6t`26Y z2vv$-=sBrHRxX+df>Ab89W}DLIoA>qazOpf9Ce>g)!ry%Sp?O?L2-@$h!i!KxqkG) z%<SmqN%rt6A!fNItC5i6@T=Wd=H>kjxkunn<)v%_DeRLN!<=|(S(>mDdTV@tweRfd zoz;SNx$Rg|n*?fyB=qWX2^HEs8@ojbEv_zqC4^)VL+>~DWOgLc>FK8|S;&8PAdizs za}mVx&pD|!+!Gdy82r<c;O3fyR5Plkt16Zw?ihEnj_ue7f-qz?q+s(>cngUgj;xfV z_h+@kNa@dMR!F7cA_+k4Wbo-&I<Stp!c&n9p#<RCW+6Zl4rzQ@AT&G>O*oQKPXF(G zuXQlR*T0r}CJ{yjG#SbLC*!9QjJIAH8MeD<wNqtoQUf`%kwD@VAepRH=7OM|J-F`n zVMC6_&dH}iu>t6VD6``39~+H39rvd89!zE_36*4!0EQPxo6HHWjnzN7Zva?JSb`wt z74=tSAerjs(&$r6bB^{jG7ee@BukFr?4^m&bec<JPpLl}U%sk@O2CrbJVqeNlGYv9 z@6h=6+I$k6i6!hADf;68DD*9IW%MQTu@+NCI0oVR6@Zw6GslWgsxOW`nOb22zAESY zNgneEpp)=r7x;edBKsEX2N+!maf0H9r=`u!b;nsG(~y!2q#{Vu#BL#f1^3EmXU13d zZq#kS^04laqLeai&@GcIW3?Y>CZI1yE_Mhq48#Svi_tehoO&YyX(TfUFKq_PH;|WP z%qGKfPmI$fg*#4MojeCQ2EJR4aYAheeD(aqUK><Vd{y@OOzyGAf017Fk)VKF6?m~^ zR@N8ymC&9-pfSxdT=j*VVj_pVrfGcV#pEerDQVEvq$$-=4p=Brwh?O(HVd?pWS|Uh z+*c!CHBs9TQO=>$6B!8FlTDDGlblC;eP2OoTSfrQG&%o7AmHZabUxC9+a2)%$$^k` z0wWZ>#P$PN&zY`7H%6o++#3e34z{~^^}$RtwrY`P1gJ#5Ya%PAUKx9a?`6}wQ*Atn z6U9r&K#*>QzL#7fn<vzrG1Rs5P`H%j1c3?&REaV`tu4LGC%*>iP*x*y@!UHOSEDZs ziUKy?%PbDUC15`rVCYv08%yJYcszliSK^EUlwXZaW4<7KFB>oie<)(M;%`MRlUB>C z%xBrfb{}?9B&5>02%0S9C!PtA!IOMqWLHR(bQ0&AL0el?eq=2>YYNm{><ns|ekgng z1O)NkAeZZg#%C9lYa;XQ`vu}lABcwnTwX#q3$q6fIh*DzR|k!Mu!aP7DU#L4Lw1F& zScu6j%Cgf12Mbz#6gL%`8=y~w(gqwLBpSnZK2%V4gCL|es3V{=jB-FN;D7^x^4AxS z{?HiX`cg&$PSh2`KB_!Krrd~2<xma5DI-j$M|x0CXu+jqoI{6fPf$lSo0P@Gr(Ubn zU&Ru-0OEl_^~gqWs9uC2iW|uY#3UEwIhapuYxJGSU%@{;a!@@~qL>2rH;YRNcQR`r zYX`~5@zqDzMn|1qoZT1Ec8Bf4AYsw-nZPNGe#;^rIj&4q%y7K>5v$Qklr>mS2?bIl zCS>Y^+93*z878&s-Xe8GzN~}ZsqORTRMwru;Ju{qq50Qfd1^cnl~CS`y1>SAv@o8U zEf=mMppPEeau7R%)Yi%2N{Twx=VYZUFl<<@QLB^<29sR#V88{8oeZ0%4(rd?gNIGu z1M+dDuj+r}!TRy-jg*9LIJkfS1s5et;ht6D;cFpz{&qb<6%wF7l%0?R;C41AMij5+ z4GV3T)6@1GKJ0_R(135PKGW5s01ipStl`$9RRE@pOmtt&(ABRE4T}PABEwR?up9u4 zd7wm4kAgpdQz9T^m>H===JhRud8upQHepz^<k-E5y_{1w#z5-(<hUBAOlJv8Op<S6 za(wG84JLd^2NQk;vK!1$KJ-{kqr=yc0?kH-ABe0@DB;Ln2V%ga)jVR87d@zcw<3B> zsrl)^3V?1~ks^RtNx|+e`=wkwP)H==^wcCw#8C=3eoeSKi$(%U-Ip6C{57&}k<j9y zZVRw^WP$BIg*FANlF4u(98aDBd3v0gl1xIa=9*NvOQ7BOAxz_dWYk6)4!%7!N8;_o z?VLj)%_%!>Ie;1q#MU%^FC1nm+<M|7qGiAoVPp`_hmk9WvSv7SBQb@u3;x;NKzbzP zBRuEB*aH&K10aLz)`0^yZ|pwj2SVv8MM)_X01FmV6v_woFfR&NGu#`rna1a>ltCle zl7`LXs-U?-k?fIV?`M)^g3nOSII?GW<Dp~o61yV2YjD9MZ>#aA^=9FEhU(AlFA*zF zs;m-#&O<~C9eTW`@qCmymDb3d8mw}?2T%vKOAIhVytJHfCH3waOb9<xq9~VzKvA3^ zmNA%NQIo)S_m(}458UDORHH}JQJc|?3Uo9UXpzGQf>BVXr;kTR)@--6A9C2@qs8MQ zguwt}ID9`GfJS|VI}KOM$z5nt$jk-M%F+Z#2+}lWD8r$Lm~}UN2c<W&PG}`X9&X|_ z$XvW8<_(bntXyVpA^pww<?g4;&He86rjn5Z1ar55OYVLLU$`7xkkCL@GbXnh!Fl|< zT6HVpcj+fzQ8EyAvJ6Xq%_IR(Y<!U}Gl3Ei)kt~wMSCC{oSG#ZgE6RdrluWaFOl4$ z9_a-@)YXUdg<-xx0z?kfd@-7GsN!HggNG5yk7kt`DT1T4PZFt6Xe=BGjfzk!zQGJC z6zJdtroX#g{h8Tn_)-i{kNkdmyTeBg{|?BRkD!-N*8H=mJ}e57uC|+#NB;_O*>~pJ z*%=SiKQ4aO`xhWxg`f9i@$=hfi&w7~Z_l5;d;QA%`r`H5^Ot{lwK)H`XXkG&UcP>{ zc=q(?zx?&WUVVD;^vA`Uzdn6;9xTq^zJ2|6@OR(+`>WS)f8v367q8!#8_!=oU%Y<7 zAD%w@oB7LMpT2tj<N4dgi`PHDdT##o@)g&A{BiN@^{b2Xf3vTaUtYfY`F!#7t6yH$ zcfNS~^2eXw(%AOPa6Ln=&Igv2E}ntgPR5GqHr7EdC$Kd!Qevz~giedpY(KceZmW>( zE?dLrCXJrF*a*cto)Jr$&zSH@bY^D;O;{G3-i^`ee|?oiQzr*X$D$BIs9_F}^Qsi( zaO}WP0Hpw$r9#)!RJdW9@*hJWDy?UVykUHYO5p`rB$UdEyaiSrVL2gh20sgoJv!X? z+>Z<vS};HjQH3R|k*4UB_{8m|vomb|v$OM0t4iq?v@V8t&HS4|BZYIWl9h(0#qkcC zFGw^mvDl=kn`818;0lASA9-5xD{vgyk`7d${8-$sPpS{YF%|2jp!$&AO3Zn2uYv$2 z(rToO=Pcn7u2tNG_TtHNDTz^v0X$Wh?>jfu=o@0JLjM{OX~n}W%C_R7esVAI{cdOF z90ABvq}xJ+YiLeT|MJ5dDEPUk%c4qCB-`~GOO=KM1qhilj$O!V*aD3K+VtpAg@!~C zC^2F(5NAdfNhHQYvk7#EziGYE4+aT{VV;l!1HuZ0m->S(ee~>dn1bNa3!v%nVv@L3 zmy>C$9W2I&YZGA7?h5{i0DJO-XwwR<4<u$F*$jPjd&5zEN@N(4C|sfVVG9&lZPnNy zkE+{!Q#ZW#KzZTf!igDHvM^}n?F~oO4b8e`NUB?k_XbYHx^DM#>sF835am0hg3(PO z$cjpN{f(pDC<}Bd%8?tLMvxwRNTQ{{+5nqdrIK!s$rG_I9&`=KKhS8B{YzMu7n()M zt_4hVU}b?YdDRTe_8^IfDvWN#;s~@9M9wv`a9}+UyL_;Y!w@c<iR{C~uGod(A-Vf3 zl=edK2lfXH0N^9!xxkUI@J`)4?544Oiy{eEaoXhg40i`gcJ4O7<UeZ0N>YIpAH**S znh<Vlj}4E!L0#FqAKR>X;2JuX2bIb)RJzDB0%a9P1WEQjF4Dl&Egsdo#cF4*7s?>h z2^L3bE)t>FvPq5HC(Sgu=TYx^A4a3bD%bpWS1hlp)7^(lGRhqF8c0b=egz1<UPDe| zE%S#d8jc;DmW14p<KleY>!RVd%25a-ki#E=jR2*;L)&V>;mF5I#r1$&OLAYk+o~GF zXJ<P2VbR`x+CQ!*mmT&uiHWh!RU0|Zm4?h#)2#?S;!41)1@MEcKpEL1H`ZLB*Tv^$ z1?%PAifJM?Y<)ppGWDOvrdK`9tJ*G5jajo&co|cHBp~vEaQ@3teQ?*<d^`E`is-}k z&xTI<_Vb^`;C>Ga*8TEywY~n6k03mQ5du1RjWFx~EVOFN+wI5ApS;uLG|>C4LH?CR zois(C$oUW3zPi4-`+V~BM~w0F=Zhcy{o?%H2{f!Y*l4nAHlxdvzhG9}oII7kRi#pR z$*jnmqC`?4+U>}<)I0HTI7Rzmr)=h3&hQf^1KHe=jAX5TBzErEnH@$y7N3baoV?)I zOJ>puyx;YY=5Lp>;<XcVbAR2JJ6C%}j*OwtNpW$7hUelAhvH(xd4xgr5l-vvdU5wr zJUHkE5c%RPu0Ke2`hjQWz1k-(J$#wZYvKqPc12hdZcQ`wj9Rax>t4(}OBR$8BPN62 zgWX*Yg17^ojI?9dY8zP#3c%{1OT1vcsyrbE@6PS9zR@zf{qOru-+-ejZi<!cOAf=f zB<w{H#i45r?V%8i4elC_t4_JOju7EOmgU=vU_V1;L~IBp<7=*t6oZjyYs6W4c`r$3 z5+?@HfJP$7suX)G6Cd@+eZ%62;A#=5S)xND5g1##3~$f}2|hOPUH|}dhSS8o!(yi= z5e6aaG|O*D+y{Ju#oXE8MKcpm(VV-w;=s>Q@u|=ypLY|g_Bbb?P6!a>0?|g|F!>kf zN3U89mnExKcp61tvuyRtI(dXic*1(nTrk<TveHy1%^w#8mQEzo8tlRDMEw(;YwS_> zB0tr9o8pD15LwcizvX~$mfI`gdI{XOio6Ff1AQXKdvI}1k1r+7ItLd6)!zypL>4sh zjOafvHgLT^`NN~8WYN>GMW3C$(;qnomscEST8jOXN00u45B`V#H~WXw%~%Rd@{ske z_Horgt3kgC&F^|^uyGWmOCirvSu__agtUlEqCy%32EG-UfZ@N~$4gm(;u6ihSu}BS zXbJ$9EX(y0h%jyoS%!F{S$4i)UCX02<_64L!kjAk7*e1%h8Ag~h~|TpJ{>wfth>hC z9#*^y;NK4igy9>!Bzb)J^FyRs9m|M%WJ|*;yUSHnQE~=Qp#|xp+_Wq5I^q;vX}IAe z1c-HDu04^#``E0_TII7dsj@axcX>`3H+rNt9{<jfnoDB`YGi!z`2aqL8X3$z4fblg zfnM{<^uil<Jrbw|X|C1y{-k+zGpb^(lpo5KrX7KLz;J=LT&O`!7^`GC0}n$aM_AZY zN1$^{+wWgGoRFqN%^Al4hd6jptQYL~QG}OOq}+kE5#oSQOS|zK51lwhCz{t1WX!=v z8#i1tYxfVGHK0Wpch`_si2%H*uX&a;))$Nl<USJUfjGAjRbe}7$MM|GMw5hj2!FZ{ zg9O`|mT-811o*kzUj24h%v10;9NJgu5=;rw-)#*KIy{-0aBYJ$W8n=+g49PXH)XTV z3N8Hga=04o2_AyxBs2;?_!<v6ysf5OJNj^HwKH&haYTPf4w}wl8;hkw#zFue2FVAE z30cj|N≻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
gpa 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%0DjU>;Cz)q(Ac? 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 Qf93t0{|_n|Dt{XP2cJC)3;+NC diff --git a/tests/ui/auxiliary/macro_use_helper.rs b/tests/ui/auxiliary/macro_use_helper.rs new file mode 100644 index 00000000000..c63149a6819 --- /dev/null +++ b/tests/ui/auxiliary/macro_use_helper.rs @@ -0,0 +1,55 @@ +extern crate macro_rules; + +// STMT +#[macro_export] +macro_rules! pub_macro { + () => { + let _ = "hello Mr. Vonnegut"; + }; +} + +pub mod inner { + pub use super::*; + + // RE-EXPORT + // this will stick in `inner` module + pub use macro_rules::try_err; + + // ITEM + #[macro_export] + macro_rules! inner_mod { + () => { + #[allow(dead_code)] + pub struct Tardis; + }; + } +} + +// EXPR +#[macro_export] +macro_rules! function { + () => { + if true { + } else { + } + }; +} + +// TYPE +#[macro_export] +macro_rules! ty_mac { + () => { + Vec<u8> + }; +} + +mod extern_exports { + pub(super) mod private_inner { + #[macro_export] + macro_rules! pub_in_private { + ($name:ident) => { + let $name = String::from("secrets and lies"); + }; + } + } +} diff --git a/tests/ui/macro_use_import.rs b/tests/ui/macro_use_import.rs deleted file mode 100644 index 6490a2107d5..00000000000 --- a/tests/ui/macro_use_import.rs +++ /dev/null @@ -1,12 +0,0 @@ -// compile-flags: --edition 2018 -#![warn(clippy::macro_use_import)] - -use std::collections::HashMap; -#[macro_use] -use std::prelude; - -fn main() { - let _ = HashMap::<u8, u8>::new(); - serde_if_integer128!(""); - println!(); -} diff --git a/tests/ui/macro_use_import.stderr b/tests/ui/macro_use_import.stderr deleted file mode 100644 index 1d86ba58441..00000000000 --- a/tests/ui/macro_use_import.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_import.rs:5:1 - | -LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use std::prelude::<macro name>` - | - = note: `-D clippy::macro-use-import` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index 60c64ee8146..76911b0c565 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -1,11 +1,40 @@ -// edition:2018 +// compile-flags: --edition 2018 +// aux-build:macro_rules.rs +// aux-build:macro_use_helper.rs + +#![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] -use std::collections::HashMap; #[macro_use] -use std::prelude; +extern crate macro_use_helper as mac; + +#[macro_use] +extern crate clippy_mini_macro_test as mini_mac; + +mod a { + #[macro_use] + use std::prelude; + #[macro_use] + use mac; + #[macro_use] + use mini_mac; + #[macro_use] + use mac::inner; + + #[derive(ClippyMiniMacroTest)] + struct Test; + + fn main() { + pub_macro!(); + inner_mod!(); + pub_in_private!(_var); + function!(); + let v: ty_mac!() = Vec::default(); + + inner::try_err!(); + } +} fn main() { - let _ = HashMap::<u8, u8>::new(); println!(); } From 8ffbf6f94d9cc77ade0596ee104f3549b8db452d Mon Sep 17 00:00:00 2001 From: Devin R <devin.ragotzy@gmail.com> Date: Fri, 13 Mar 2020 18:54:32 -0400 Subject: [PATCH 190/526] use hashset not map for keeping track of seen macro refs remove stdout, fix clippy warnings, fmtcar --- clippy_lints/src/macro_use.rs | 131 +++++++++---------------- tests/ui/auxiliary/macro_use_helper.rs | 8 +- tests/ui/macro_use_import.stdout | 0 tests/ui/macro_use_imports.rs | 14 +-- tests/ui/macro_use_imports.stderr | 44 ++++++++- 5 files changed, 97 insertions(+), 100 deletions(-) delete mode 100644 tests/ui/macro_use_import.stdout diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 4c89647a574..9519fa6093b 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -2,7 +2,7 @@ use crate::utils::{in_macro, snippet, span_lint_and_sugg}; use hir::def::{DefKind, Res}; use if_chain::if_chain; use rustc_ast::ast; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -29,7 +29,7 @@ declare_clippy_lint! { const BRACKETS: &[char] = &['<', '>']; -/// MacroRefData includes the name of the macro +/// `MacroRefData` includes the name of the macro /// and the path from `SourceMap::span_to_filename`. #[derive(Debug, Clone)] pub struct MacroRefData { @@ -38,11 +38,11 @@ pub struct MacroRefData { } impl MacroRefData { - pub fn new(name: String, span: Span, ecx: &LateContext<'_, '_>) -> Self { + pub fn new(name: &str, span: Span, ecx: &LateContext<'_, '_>) -> Self { let mut path = ecx.sess().source_map().span_to_filename(span).to_string(); // std lib paths are <::std::module::file type> - // so remove brackets and space + // so remove brackets, space and type. if path.contains('<') { path = path.replace(BRACKETS, ""); } @@ -57,13 +57,12 @@ impl MacroRefData { } #[derive(Default)] +#[allow(clippy::module_name_repetitions)] pub struct MacroUseImports { /// the actual import path used and the span of the attribute above it. imports: Vec<(String, Span)>, - /// the span of the macro reference and the `MacroRefData` - /// for the use of the macro. - /// TODO make this FxHashSet<Span> to guard against inserting already found macros - collected: FxHashMap<Span, MacroRefData>, + /// the span of the macro reference, kept to ensure only one reference is used per macro call. + collected: FxHashSet<Span>, mac_refs: Vec<(Span, MacroRefData)>, } @@ -72,34 +71,28 @@ impl_lint_pass!(MacroUseImports => [MACRO_USE_IMPORTS]); impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { fn check_item(&mut self, lcx: &LateContext<'_, '_>, item: &hir::Item<'_>) { if_chain! { - if lcx.sess().opts.edition == Edition::Edition2018; - if let hir::ItemKind::Use(path, _kind) = &item.kind; - if let Some(mac_attr) = item - .attrs - .iter() - .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string())); - if let Res::Def(DefKind::Mod, id) = path.res; - then { - // println!("{:#?}", lcx.tcx.def_path_str(id)); - for kid in lcx.tcx.item_children(id).iter() { - // println!("{:#?}", kid); - if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { - let span = mac_attr.span.clone(); - - // println!("{:#?}", lcx.tcx.def_path_str(mac_id)); - - self.imports.push((lcx.tcx.def_path_str(mac_id), span)); + if lcx.sess().opts.edition == Edition::Edition2018; + if let hir::ItemKind::Use(path, _kind) = &item.kind; + if let Some(mac_attr) = item + .attrs + .iter() + .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string())); + if let Res::Def(DefKind::Mod, id) = path.res; + then { + for kid in lcx.tcx.item_children(id).iter() { + if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { + let span = mac_attr.span; + self.imports.push((lcx.tcx.def_path_str(mac_id), span)); + } } - } - } else { + } else { if in_macro(item.span) { let call_site = item.span.source_callsite(); let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = item.span.source_callee() { - if !self.collected.contains_key(&call_site) { - let mac = MacroRefData::new(name.to_string(), callee.def_site, lcx); - self.mac_refs.push((call_site, mac.clone())); - self.collected.insert(call_site, mac); + if !self.collected.contains(&call_site) { + self.mac_refs.push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); + self.collected.insert(call_site); } } } @@ -111,18 +104,16 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { let call_site = attr.span.source_callsite(); let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = attr.span.source_callee() { - if !self.collected.contains_key(&call_site) { - println!("{:?}\n{:#?}", call_site, attr); - + if !self.collected.contains(&call_site) { let name = if name.contains("::") { name.split("::").last().unwrap().to_string() } else { name.to_string() }; - let mac = MacroRefData::new(name, callee.def_site, lcx); - self.mac_refs.push((call_site, mac.clone())); - self.collected.insert(call_site, mac); + self.mac_refs + .push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); + self.collected.insert(call_site); } } } @@ -132,16 +123,16 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { let call_site = expr.span.source_callsite(); let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = expr.span.source_callee() { - if !self.collected.contains_key(&call_site) { + if !self.collected.contains(&call_site) { let name = if name.contains("::") { name.split("::").last().unwrap().to_string() } else { name.to_string() }; - let mac = MacroRefData::new(name, callee.def_site, lcx); - self.mac_refs.push((call_site, mac.clone())); - self.collected.insert(call_site, mac); + self.mac_refs + .push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); + self.collected.insert(call_site); } } } @@ -151,16 +142,16 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { let call_site = stmt.span.source_callsite(); let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = stmt.span.source_callee() { - if !self.collected.contains_key(&call_site) { + if !self.collected.contains(&call_site) { let name = if name.contains("::") { name.split("::").last().unwrap().to_string() } else { name.to_string() }; - let mac = MacroRefData::new(name, callee.def_site, lcx); - self.mac_refs.push((call_site, mac.clone())); - self.collected.insert(call_site, mac); + self.mac_refs + .push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); + self.collected.insert(call_site); } } } @@ -170,10 +161,10 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { let call_site = pat.span.source_callsite(); let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = pat.span.source_callee() { - if !self.collected.contains_key(&call_site) { - let mac = MacroRefData::new(name.to_string(), callee.def_site, lcx); - self.mac_refs.push((call_site, mac.clone())); - self.collected.insert(call_site, mac); + if !self.collected.contains(&call_site) { + self.mac_refs + .push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); + self.collected.insert(call_site); } } } @@ -183,22 +174,18 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { let call_site = ty.span.source_callsite(); let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = ty.span.source_callee() { - if !self.collected.contains_key(&call_site) { - let mac = MacroRefData::new(name.to_string(), callee.def_site, lcx); - self.mac_refs.push((call_site, mac.clone())); - self.collected.insert(call_site, mac); + if !self.collected.contains(&call_site) { + self.mac_refs + .push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); + self.collected.insert(call_site); } } } } fn check_crate_post(&mut self, lcx: &LateContext<'_, '_>, _krate: &hir::Crate<'_>) { - for (import, span) in self.imports.iter() { - let matched = self - .mac_refs - .iter() - .find(|(_span, mac)| import.ends_with(&mac.name)) - .is_some(); + for (import, span) in &self.imports { + let matched = self.mac_refs.iter().any(|(_span, mac)| import.ends_with(&mac.name)); if matched { self.mac_refs.retain(|(_span, mac)| !import.ends_with(&mac.name)); @@ -218,30 +205,8 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { if !self.mac_refs.is_empty() { // TODO if not empty we found one we could not make a suggestion for // such as std::prelude::v1 or something else I haven't thought of. - // println!("{:#?}", self.mac_refs); + // If we defer the calling of span_lint_and_sugg we can make a decision about its + // applicability? } } } - -const PRELUDE: &[&str] = &[ - "marker", "ops", "convert", "iter", "option", "result", "borrow", "boxed", "string", "vec", "macros", -]; - -/// This is somewhat of a fallback for imports from `std::prelude` because they -/// are not recognized by `LateLintPass::check_item` `lcx.tcx.item_children(id)` -fn make_path(mac: &MacroRefData, use_path: &str) -> String { - let segs = mac.path.split("::").filter(|s| *s != "").collect::<Vec<_>>(); - - if segs.starts_with(&["std"]) && PRELUDE.iter().any(|m| segs.contains(m)) { - return format!( - "std::prelude::{} is imported by default, remove `use` statement", - mac.name - ); - } - - if use_path.split("::").count() == 1 { - return format!("{}::{}", use_path, mac.name); - } - - mac.path.clone() -} diff --git a/tests/ui/auxiliary/macro_use_helper.rs b/tests/ui/auxiliary/macro_use_helper.rs index c63149a6819..7cc4e1d736a 100644 --- a/tests/ui/auxiliary/macro_use_helper.rs +++ b/tests/ui/auxiliary/macro_use_helper.rs @@ -17,7 +17,7 @@ pub mod inner { // ITEM #[macro_export] - macro_rules! inner_mod { + macro_rules! inner_mod_macro { () => { #[allow(dead_code)] pub struct Tardis; @@ -27,7 +27,7 @@ pub mod inner { // EXPR #[macro_export] -macro_rules! function { +macro_rules! function_macro { () => { if true { } else { @@ -37,7 +37,7 @@ macro_rules! function { // TYPE #[macro_export] -macro_rules! ty_mac { +macro_rules! ty_macro { () => { Vec<u8> }; @@ -46,7 +46,7 @@ macro_rules! ty_mac { mod extern_exports { pub(super) mod private_inner { #[macro_export] - macro_rules! pub_in_private { + macro_rules! pub_in_private_macro { ($name:ident) => { let $name = String::from("secrets and lies"); }; diff --git a/tests/ui/macro_use_import.stdout b/tests/ui/macro_use_import.stdout deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index 76911b0c565..bc8762df593 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -12,8 +12,6 @@ extern crate macro_use_helper as mac; extern crate clippy_mini_macro_test as mini_mac; mod a { - #[macro_use] - use std::prelude; #[macro_use] use mac; #[macro_use] @@ -26,15 +24,13 @@ mod a { fn main() { pub_macro!(); - inner_mod!(); - pub_in_private!(_var); - function!(); - let v: ty_mac!() = Vec::default(); + inner_mod_macro!(); + pub_in_private_macro!(_var); + function_macro!(); + let v: ty_macro!() = Vec::default(); inner::try_err!(); } } -fn main() { - println!(); -} +fn main() {} diff --git a/tests/ui/macro_use_imports.stderr b/tests/ui/macro_use_imports.stderr index b5e3dbec572..6bcacd0be19 100644 --- a/tests/ui/macro_use_imports.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -1,10 +1,46 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:5:1 + --> $DIR/macro_use_imports.rs:15:5 | -LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use std::prelude::<macro name>` +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::pub_macro` | = note: `-D clippy::macro-use-imports` implied by `-D warnings` -error: aborting due to previous error +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:15:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner_mod_macro` + +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:15:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::function_macro` + +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:15:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::ty_macro` + +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:15:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::pub_in_private_macro` + +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:17:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest` + +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:19:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::try_err` + +error: aborting due to 7 previous errors From 1d9e80ad7b5b69caa8b9f9c44d47f26c4bbc4c7b Mon Sep 17 00:00:00 2001 From: Devin R <devin.ragotzy@gmail.com> Date: Mon, 23 Mar 2020 22:13:35 -0400 Subject: [PATCH 191/526] remove session --- clippy_lints/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 89f55986f63..991899f89bc 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -60,7 +60,6 @@ extern crate rustc_trait_selection; #[allow(unused_extern_crates)] extern crate rustc_typeck; -use rustc::session::Session; use rustc_data_structures::fx::FxHashSet; use rustc_lint::LintId; use rustc_session::Session; From 8bc106b29d3d2ee382f6dc4a2e9d6eecf534c6ed Mon Sep 17 00:00:00 2001 From: Devin R <devin.ragotzy@gmail.com> Date: Sun, 10 May 2020 09:06:33 -0400 Subject: [PATCH 192/526] fix some of the review, rename, fmt, refactor --- clippy_lints/src/lib.rs | 3 +- clippy_lints/src/macro_use.rs | 130 +++++++++++++++------------------- tests/ui/macro_use_imports.rs | 2 +- 3 files changed, 60 insertions(+), 75 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 991899f89bc..021fbe932d8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1060,7 +1060,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let max_struct_bools = conf.max_struct_bools; store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools)); store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); - store.register_late_pass(|| box wildcard_imports::WildcardImports); + let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports; + store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)); store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default()); store.register_late_pass(|| box unnamed_address::UnnamedAddress); diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 9519fa6093b..9c8035f54a9 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -38,8 +38,8 @@ pub struct MacroRefData { } impl MacroRefData { - pub fn new(name: &str, span: Span, ecx: &LateContext<'_, '_>) -> Self { - let mut path = ecx.sess().source_map().span_to_filename(span).to_string(); + pub fn new(name: &str, callee: Span, cx: &LateContext<'_, '_>) -> Self { + let mut path = cx.sess().source_map().span_to_filename(callee).to_string(); // std lib paths are <::std::module::file type> // so remove brackets, space and type. @@ -63,15 +63,37 @@ pub struct MacroUseImports { imports: Vec<(String, Span)>, /// the span of the macro reference, kept to ensure only one reference is used per macro call. collected: FxHashSet<Span>, - mac_refs: Vec<(Span, MacroRefData)>, + mac_refs: Vec<MacroRefData>, } impl_lint_pass!(MacroUseImports => [MACRO_USE_IMPORTS]); +impl MacroUseImports { + fn push_unique_macro(&mut self, cx: &LateContext<'_, '_>, name: &str, call_site: Span, callee: Span) { + if !self.collected.contains(&call_site) { + let name = if name.contains("::") { + name.split("::").last().unwrap().to_string() + } else { + name.to_string() + }; + + self.mac_refs.push(MacroRefData::new(&name, callee, cx)); + self.collected.insert(call_site); + } + } + + fn push_unique_macro_pat_ty(&mut self, cx: &LateContext<'_, '_>, name: &str, call_site: Span, callee: Span) { + if !self.collected.contains(&call_site) { + self.mac_refs.push(MacroRefData::new(&name, callee, cx)); + self.collected.insert(call_site); + } + } +} + impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { - fn check_item(&mut self, lcx: &LateContext<'_, '_>, item: &hir::Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) { if_chain! { - if lcx.sess().opts.edition == Edition::Edition2018; + if cx.sess().opts.edition == Edition::Edition2018; if let hir::ItemKind::Use(path, _kind) = &item.kind; if let Some(mac_attr) = item .attrs @@ -79,126 +101,88 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string())); if let Res::Def(DefKind::Mod, id) = path.res; then { - for kid in lcx.tcx.item_children(id).iter() { + for kid in cx.tcx.item_children(id).iter() { if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { let span = mac_attr.span; - self.imports.push((lcx.tcx.def_path_str(mac_id), span)); + self.imports.push((cx.tcx.def_path_str(mac_id), span)); } } } else { - if in_macro(item.span) { - let call_site = item.span.source_callsite(); - let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); - if let Some(callee) = item.span.source_callee() { - if !self.collected.contains(&call_site) { - self.mac_refs.push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); - self.collected.insert(call_site); + if in_macro(item.span) { + let call_site = item.span.source_callsite(); + let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); + if let Some(callee) = item.span.source_callee() { + if !self.collected.contains(&call_site) { + self.mac_refs.push(MacroRefData::new(&name, callee.def_site, cx)); + self.collected.insert(call_site); + } } } - } } } } - fn check_attribute(&mut self, lcx: &LateContext<'_, '_>, attr: &ast::Attribute) { + fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) { if in_macro(attr.span) { let call_site = attr.span.source_callsite(); - let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = attr.span.source_callee() { - if !self.collected.contains(&call_site) { - let name = if name.contains("::") { - name.split("::").last().unwrap().to_string() - } else { - name.to_string() - }; - - self.mac_refs - .push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); - self.collected.insert(call_site); - } + self.push_unique_macro(cx, &name, call_site, callee.def_site); } } } - fn check_expr(&mut self, lcx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { if in_macro(expr.span) { let call_site = expr.span.source_callsite(); - let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = expr.span.source_callee() { - if !self.collected.contains(&call_site) { - let name = if name.contains("::") { - name.split("::").last().unwrap().to_string() - } else { - name.to_string() - }; - - self.mac_refs - .push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); - self.collected.insert(call_site); - } + self.push_unique_macro(cx, &name, call_site, callee.def_site); } } } - fn check_stmt(&mut self, lcx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>) { + fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>) { if in_macro(stmt.span) { let call_site = stmt.span.source_callsite(); - let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = stmt.span.source_callee() { - if !self.collected.contains(&call_site) { - let name = if name.contains("::") { - name.split("::").last().unwrap().to_string() - } else { - name.to_string() - }; - - self.mac_refs - .push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); - self.collected.insert(call_site); - } + self.push_unique_macro(cx, &name, call_site, callee.def_site); } } } - fn check_pat(&mut self, lcx: &LateContext<'_, '_>, pat: &hir::Pat<'_>) { + fn check_pat(&mut self, cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>) { if in_macro(pat.span) { let call_site = pat.span.source_callsite(); - let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = pat.span.source_callee() { - if !self.collected.contains(&call_site) { - self.mac_refs - .push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); - self.collected.insert(call_site); - } + self.push_unique_macro_pat_ty(cx, &name, call_site, callee.def_site); } } } - fn check_ty(&mut self, lcx: &LateContext<'_, '_>, ty: &hir::Ty<'_>) { + fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &hir::Ty<'_>) { if in_macro(ty.span) { let call_site = ty.span.source_callsite(); - let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_"); + let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = ty.span.source_callee() { - if !self.collected.contains(&call_site) { - self.mac_refs - .push((call_site, MacroRefData::new(&name, callee.def_site, lcx))); - self.collected.insert(call_site); - } + self.push_unique_macro_pat_ty(cx, &name, call_site, callee.def_site); } } } - fn check_crate_post(&mut self, lcx: &LateContext<'_, '_>, _krate: &hir::Crate<'_>) { + fn check_crate_post(&mut self, cx: &LateContext<'_, '_>, _krate: &hir::Crate<'_>) { for (import, span) in &self.imports { - let matched = self.mac_refs.iter().any(|(_span, mac)| import.ends_with(&mac.name)); + let matched = self.mac_refs.iter().any(|mac| import.ends_with(&mac.name)); if matched { - self.mac_refs.retain(|(_span, mac)| !import.ends_with(&mac.name)); + self.mac_refs.retain(|mac| !import.ends_with(&mac.name)); let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition"; let help = format!("use {}", import); span_lint_and_sugg( - lcx, + cx, MACRO_USE_IMPORTS, *span, msg, "remove the attribute and import the macro directly, try", help, - Applicability::HasPlaceholders, + Applicability::MaybeIncorrect, ) } } diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index bc8762df593..2d4f71e5d53 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -22,7 +22,7 @@ mod a { #[derive(ClippyMiniMacroTest)] struct Test; - fn main() { + fn test() { pub_macro!(); inner_mod_macro!(); pub_in_private_macro!(_var); From 451363dc59b3030fee82e4faf04684c068f619cc Mon Sep 17 00:00:00 2001 From: Devin R <devin.ragotzy@gmail.com> Date: Thu, 14 May 2020 18:20:07 -0400 Subject: [PATCH 193/526] still working on displaying nested imports --- clippy_lints/src/macro_use.rs | 291 +++++++++++++++++++++++++--------- 1 file changed, 214 insertions(+), 77 deletions(-) diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 9c8035f54a9..8dddd6d716d 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -2,7 +2,7 @@ use crate::utils::{in_macro, snippet, span_lint_and_sugg}; use hir::def::{DefKind, Res}; use if_chain::if_chain; use rustc_ast::ast; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -38,7 +38,7 @@ pub struct MacroRefData { } impl MacroRefData { - pub fn new(name: &str, callee: Span, cx: &LateContext<'_, '_>) -> Self { + pub fn new(name: String, callee: Span, cx: &LateContext<'_, '_>) -> Self { let mut path = cx.sess().source_map().span_to_filename(callee).to_string(); // std lib paths are <::std::module::file type> @@ -50,7 +50,7 @@ impl MacroRefData { path = path.split(' ').next().unwrap().to_string(); } Self { - name: name.to_string(), + name, path, } } @@ -69,23 +69,31 @@ pub struct MacroUseImports { impl_lint_pass!(MacroUseImports => [MACRO_USE_IMPORTS]); impl MacroUseImports { - fn push_unique_macro(&mut self, cx: &LateContext<'_, '_>, name: &str, call_site: Span, callee: Span) { - if !self.collected.contains(&call_site) { - let name = if name.contains("::") { - name.split("::").last().unwrap().to_string() - } else { - name.to_string() - }; - - self.mac_refs.push(MacroRefData::new(&name, callee, cx)); - self.collected.insert(call_site); + fn push_unique_macro(&mut self, cx: &LateContext<'_, '_>, span: Span) { + let call_site = span.source_callsite(); + let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); + if let Some(callee) = span.source_callee() { + if !self.collected.contains(&call_site) { + let name = if name.contains("::") { + name.split("::").last().unwrap().to_string() + } else { + name.to_string() + }; + + self.mac_refs.push(MacroRefData::new(name, callee.def_site, cx)); + self.collected.insert(call_site); + } } } - fn push_unique_macro_pat_ty(&mut self, cx: &LateContext<'_, '_>, name: &str, call_site: Span, callee: Span) { - if !self.collected.contains(&call_site) { - self.mac_refs.push(MacroRefData::new(&name, callee, cx)); - self.collected.insert(call_site); + fn push_unique_macro_pat_ty(&mut self, cx: &LateContext<'_, '_>, span: Span) { + let call_site = span.source_callsite(); + let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); + if let Some(callee) = span.source_callee() { + if !self.collected.contains(&call_site) { + self.mac_refs.push(MacroRefData::new(name.to_string(), callee.def_site, cx)); + self.collected.insert(call_site); + } } } } @@ -93,104 +101,233 @@ impl MacroUseImports { impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) { if_chain! { - if cx.sess().opts.edition == Edition::Edition2018; - if let hir::ItemKind::Use(path, _kind) = &item.kind; - if let Some(mac_attr) = item - .attrs - .iter() - .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string())); - if let Res::Def(DefKind::Mod, id) = path.res; - then { - for kid in cx.tcx.item_children(id).iter() { - if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { - let span = mac_attr.span; - self.imports.push((cx.tcx.def_path_str(mac_id), span)); - } - } - } else { - if in_macro(item.span) { - let call_site = item.span.source_callsite(); - let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); - if let Some(callee) = item.span.source_callee() { - if !self.collected.contains(&call_site) { - self.mac_refs.push(MacroRefData::new(&name, callee.def_site, cx)); - self.collected.insert(call_site); - } - } + if cx.sess().opts.edition == Edition::Edition2018; + if let hir::ItemKind::Use(path, _kind) = &item.kind; + if let Some(mac_attr) = item + .attrs + .iter() + .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string())); + if let Res::Def(DefKind::Mod, id) = path.res; + then { + for kid in cx.tcx.item_children(id).iter() { + if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { + let span = mac_attr.span; + self.imports.push((cx.tcx.def_path_str(mac_id), span)); } + } + } else { + if in_macro(item.span) { + self.push_unique_macro_pat_ty(cx, item.span); + } } } } fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) { if in_macro(attr.span) { - let call_site = attr.span.source_callsite(); - let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); - if let Some(callee) = attr.span.source_callee() { - self.push_unique_macro(cx, &name, call_site, callee.def_site); - } + self.push_unique_macro(cx, attr.span); } } fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { if in_macro(expr.span) { - let call_site = expr.span.source_callsite(); - let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); - if let Some(callee) = expr.span.source_callee() { - self.push_unique_macro(cx, &name, call_site, callee.def_site); - } + self.push_unique_macro(cx, expr.span); } } fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>) { if in_macro(stmt.span) { - let call_site = stmt.span.source_callsite(); - let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); - if let Some(callee) = stmt.span.source_callee() { - self.push_unique_macro(cx, &name, call_site, callee.def_site); - } + self.push_unique_macro(cx, stmt.span); } } fn check_pat(&mut self, cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>) { if in_macro(pat.span) { - let call_site = pat.span.source_callsite(); - let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); - if let Some(callee) = pat.span.source_callee() { - self.push_unique_macro_pat_ty(cx, &name, call_site, callee.def_site); - } + self.push_unique_macro_pat_ty(cx, pat.span); } } fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &hir::Ty<'_>) { if in_macro(ty.span) { - let call_site = ty.span.source_callsite(); - let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); - if let Some(callee) = ty.span.source_callee() { - self.push_unique_macro_pat_ty(cx, &name, call_site, callee.def_site); - } + self.push_unique_macro_pat_ty(cx, ty.span); } } fn check_crate_post(&mut self, cx: &LateContext<'_, '_>, _krate: &hir::Crate<'_>) { + let mut import_map = FxHashMap::default(); for (import, span) in &self.imports { - let matched = self.mac_refs.iter().any(|mac| import.ends_with(&mac.name)); + let found_idx = self.mac_refs.iter().position(|mac| import.ends_with(&mac.name)); + + if let Some(idx) = found_idx { + let _ = self.mac_refs.remove(idx); + proccess_macro_path(*span, import, &mut import_map); + } + } + println!("{:#?}", import_map); + let mut imports = vec![]; + for (root, rest) in import_map { + let mut path = format!("use {}::", root); + let mut s = None; + let mut count = 1; + let rest_len = rest.len(); + if rest_len > 1 { + path.push_str("{"); + } + for m in &rest { + println!("{} => {:?}", root, m); + if count == 1 { + s = Some(m.span()); + } + + let comma = if rest_len == count { "" } else { ", " }; + match m { + ModPath::Item { item, .. } => { + path.push_str(&format!("{}{}", item, comma)); + } + ModPath::Nested { names, item, span } => { + let nested = rest.iter() + // filter "self" out + .filter(|other_m| other_m != &m) + // this matches the first path segment and filters non ModPath::Nested items + .filter(|other_m| other_m.matches(0, m)) + .collect::<Vec<_>>(); - if matched { - self.mac_refs.retain(|mac| !import.ends_with(&mac.name)); - let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition"; + println!("{:#?}", nested); + + if nested.is_empty() { + path.push_str(&format!("{}::{}{}", names.join("::").to_string(), item, comma)) + } else { + // use mod_a::{mod_b::{one, two}, mod_c::item, item1, item2} + let mod_path = if names.len() - 1 > 0 { + ModPath::Nested { names: names.clone(), item: item.to_string(), span: *span, } + } else { + ModPath::Item { item: names[0].to_string(), span: *span, } + }; + let names = recursive_path_push(mod_path, comma, &rest, String::new()); + path.push_str(&format!("{}::{{{}}}{}", names, item, comma)) + } + } + } + count += 1; + } + if rest_len > 1 { + path.push_str("};"); + } + if let Some(span) = s { + imports.push((span, path)) + } + } + + if !self.mac_refs.is_empty() { + // TODO if not empty we found one we could not make a suggestion for + // such as std::prelude::v1 or something else I haven't thought of. + // If we defer the calling of span_lint_and_sugg we can make a decision about its + // applicability? + } else { + for (span, import) in imports { let help = format!("use {}", import); span_lint_and_sugg( cx, MACRO_USE_IMPORTS, - *span, - msg, + span, + "`macro_use` attributes are no longer needed in the Rust 2018 edition", "remove the attribute and import the macro directly, try", help, Applicability::MaybeIncorrect, ) } } - if !self.mac_refs.is_empty() { - // TODO if not empty we found one we could not make a suggestion for - // such as std::prelude::v1 or something else I haven't thought of. - // If we defer the calling of span_lint_and_sugg we can make a decision about its - // applicability? + } +} + +#[derive(Debug, PartialEq)] +enum ModPath { + Item { item: String, span: Span, }, + Nested { names: Vec<String>, item: String, span: Span, }, +} + +impl ModPath { + fn span(&self) -> Span { + match self { + Self::Item { span, .. } => *span, + Self::Nested { span, .. } => *span, + } + } + + fn item(&self) -> &str { + match self { + Self::Item { item, .. } => item, + Self::Nested { item, .. } => item, + } + } + + fn matches(&self, idx: usize, other: &ModPath) -> bool { + match (self, other) { + (Self::Item { item, .. }, Self::Item { item: other_item, .. }) => item == other_item, + (Self::Nested { names, .. }, Self::Nested { names: other_names, .. }) => { + match (names.get(idx), other_names.get(idx)) { + (Some(seg), Some(other_seg)) => seg == other_seg, + (_, _) => false, + } + } + (_, _) => false, } } } + +fn proccess_macro_path(span: Span, import: &str, import_map: &mut FxHashMap<String, Vec<ModPath>>) { + let mut mod_path = import.split("::").collect::<Vec<_>>(); + + if mod_path.len() == 2 { + let item_list = import_map.entry(mod_path[0].to_string()) + .or_insert(vec![]); + + if !item_list.iter().any(|mods| mods.item() == mod_path[1]) { + item_list.push(ModPath::Item{ + item: mod_path[1].to_string(), + span, + }); + } + } else if mod_path.len() > 2 { + let first = mod_path.remove(0); + let name = mod_path.remove(mod_path.len() - 1); + + let nested = ModPath::Nested { + names: mod_path.into_iter().map(ToString::to_string).collect(), + item: name.to_string(), + span, + }; + import_map.entry(first.to_string()) + .or_insert(vec![]) + .push(nested); + } else { + unreachable!("test to see if code path hit TODO REMOVE") + } +} + +fn recursive_path_push(module: ModPath, comma: &str, rest: &[ModPath], mut path: String) -> String { + match &module { + ModPath::Item { item, .. } => { + path.push_str(&format!("{}{}", item, comma)); + } + ModPath::Nested { names, item, span } => { + let nested = rest.iter() + // filter "self" out + .filter(|other_m| other_m != &&module) + // this matches the first path segment and filters non ModPath::Nested items + .filter(|other_m| other_m.matches(0, &module)) + .collect::<Vec<_>>(); + + println!("{:#?}", nested); + + if nested.is_empty() { + path.push_str(&format!("{}::{}{}", names.join("::").to_string(), item, comma)) + } else { + // use mod_a::{mod_b::{one, two}, mod_c::item, item1, item2} + let mod_path = if names.len() - 1 > 0 { + ModPath::Nested { names: names.clone(), item: item.to_string(), span: *span, } + } else { + ModPath::Item { item: names[0].to_string(), span: *span, } + }; + let names = recursive_path_push(mod_path, comma, rest, path.to_string()); + // path.push_str(&format!("{}{}", item, comma)); + } + } + } + path +} From d4f60b5ff42a4e8b5889879664002f90dacd6c04 Mon Sep 17 00:00:00 2001 From: Devin R <devin.ragotzy@gmail.com> Date: Fri, 15 May 2020 08:36:56 -0400 Subject: [PATCH 194/526] wip: of handling nested import paths for multi-macro paths --- clippy_lints/src/macro_use.rs | 197 ++++++++++++++----------- tests/ui/auxiliary/macro_use_helper.rs | 5 + tests/ui/macro_use_imports.rs | 4 + tests/ui/macro_use_imports.stderr | 38 +---- 4 files changed, 122 insertions(+), 122 deletions(-) diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 8dddd6d716d..1e1f27e9430 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -49,10 +49,7 @@ impl MacroRefData { if path.contains(' ') { path = path.split(' ').next().unwrap().to_string(); } - Self { - name, - path, - } + Self { name, path } } } @@ -79,7 +76,7 @@ impl MacroUseImports { } else { name.to_string() }; - + self.mac_refs.push(MacroRefData::new(name, callee.def_site, cx)); self.collected.insert(call_site); } @@ -91,7 +88,8 @@ impl MacroUseImports { let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = span.source_callee() { if !self.collected.contains(&call_site) { - self.mac_refs.push(MacroRefData::new(name.to_string(), callee.def_site, cx)); + self.mac_refs + .push(MacroRefData::new(name.to_string(), callee.def_site, cx)); self.collected.insert(call_site); } } @@ -147,78 +145,123 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { self.push_unique_macro_pat_ty(cx, ty.span); } } - + #[allow(clippy::too_many_lines)] fn check_crate_post(&mut self, cx: &LateContext<'_, '_>, _krate: &hir::Crate<'_>) { let mut import_map = FxHashMap::default(); for (import, span) in &self.imports { let found_idx = self.mac_refs.iter().position(|mac| import.ends_with(&mac.name)); - + if let Some(idx) = found_idx { let _ = self.mac_refs.remove(idx); proccess_macro_path(*span, import, &mut import_map); } } - println!("{:#?}", import_map); + // println!("{:#?}", import_map); let mut imports = vec![]; for (root, rest) in import_map { let mut path = format!("use {}::", root); - let mut s = None; + let mut attr_span = None; + // when a multiple nested paths are found one may be written to the string + // before it is found in this loop so we make note and skip it when this + // loop finds it + let mut found_nested = vec![]; let mut count = 1; let rest_len = rest.len(); + if rest_len > 1 { path.push_str("{"); } + for m in &rest { - println!("{} => {:?}", root, m); - if count == 1 { - s = Some(m.span()); + if attr_span.is_none() { + attr_span = Some(m.span()); + } + if found_nested.contains(&m) { + continue; } - let comma = if rest_len == count { "" } else { ", " }; match m { ModPath::Item { item, .. } => { path.push_str(&format!("{}{}", item, comma)); - } - ModPath::Nested { names, item, span } => { - let nested = rest.iter() + }, + ModPath::Nested { segments, item, .. } => { + // do any other Nested paths match the current one + let nested = rest + .iter() // filter "self" out .filter(|other_m| other_m != &m) + // filters out Nested we have previously seen + .filter(|other_m| !found_nested.contains(other_m)) // this matches the first path segment and filters non ModPath::Nested items .filter(|other_m| other_m.matches(0, m)) .collect::<Vec<_>>(); - println!("{:#?}", nested); - if nested.is_empty() { - path.push_str(&format!("{}::{}{}", names.join("::").to_string(), item, comma)) + path.push_str(&format!("{}::{}{}", segments.join("::").to_string(), item, comma)) + // use mod_a::{mod_b::{one, two}, mod_c::item} } else { - // use mod_a::{mod_b::{one, two}, mod_c::item, item1, item2} - let mod_path = if names.len() - 1 > 0 { - ModPath::Nested { names: names.clone(), item: item.to_string(), span: *span, } - } else { - ModPath::Item { item: names[0].to_string(), span: *span, } - }; - let names = recursive_path_push(mod_path, comma, &rest, String::new()); - path.push_str(&format!("{}::{{{}}}{}", names, item, comma)) + found_nested.extend(nested.iter()); + found_nested.push(&m); + // we check each segment for matches with other import paths if + // one differs we have to open a new `{}` + for (idx, seg) in segments.iter().enumerate() { + path.push_str(&format!("{}::", seg)); + if nested.iter().all(|other_m| other_m.matches(idx, &m)) { + continue; + } + + path.push_str("{"); + let matched_seg_items = nested + .iter() + .filter(|other_m| !other_m.matches(idx, &m)) + .collect::<Vec<_>>(); + for item in matched_seg_items { + if let ModPath::Nested { item, .. } = item { + path.push_str(&format!( + "{}{}", + item, + if nested.len() == idx + 1 { "" } else { ", " } + )); + } + } + path.push_str("}"); + } + path.push_str(&format!("{{{}{}", item, comma)); + for (i, item) in nested.iter().enumerate() { + if let ModPath::Nested { item, segments: matched_seg, .. } = item { + path.push_str(&format!( + "{}{}{}", + if matched_seg > segments { + format!("{}::", matched_seg[segments.len()..].join("::")) + } else { + String::new() + }, + item, + if nested.len() == i + 1 { "" } else { ", " } + )); + } + } + path.push_str("}"); } - } + }, } - count += 1; + count += 1; } if rest_len > 1 { path.push_str("};"); + } else { + path.push_str(";"); } - if let Some(span) = s { + if let Some(span) = attr_span { imports.push((span, path)) + } else { + unreachable!("a span must always be attached to a macro_use attribute") } } - if !self.mac_refs.is_empty() { - // TODO if not empty we found one we could not make a suggestion for - // such as std::prelude::v1 or something else I haven't thought of. - // If we defer the calling of span_lint_and_sugg we can make a decision about its - // applicability? - } else { + // If mac_refs is not empty we have encountered an import we could not handle + // such as `std::prelude::v1::foo` or some other macro that expands to an import. + if self.mac_refs.is_empty() { for (span, import) in imports { let help = format!("use {}", import); span_lint_and_sugg( @@ -237,48 +280,56 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { #[derive(Debug, PartialEq)] enum ModPath { - Item { item: String, span: Span, }, - Nested { names: Vec<String>, item: String, span: Span, }, + Item { + item: String, + span: Span, + }, + Nested { + segments: Vec<String>, + item: String, + span: Span, + }, } impl ModPath { fn span(&self) -> Span { match self { - Self::Item { span, .. } => *span, - Self::Nested { span, .. } => *span, + Self::Item { span, .. } | Self::Nested { span, .. } => *span, } } fn item(&self) -> &str { match self { - Self::Item { item, .. } => item, - Self::Nested { item, .. } => item, + Self::Item { item, .. } | Self::Nested { item, .. } => item, } } fn matches(&self, idx: usize, other: &ModPath) -> bool { match (self, other) { (Self::Item { item, .. }, Self::Item { item: other_item, .. }) => item == other_item, - (Self::Nested { names, .. }, Self::Nested { names: other_names, .. }) => { - match (names.get(idx), other_names.get(idx)) { - (Some(seg), Some(other_seg)) => seg == other_seg, - (_, _) => false, - } - } + ( + Self::Nested { segments, .. }, + Self::Nested { + segments: other_names, .. + }, + ) => match (segments.get(idx), other_names.get(idx)) { + (Some(seg), Some(other_seg)) => seg == other_seg, + (_, _) => false, + }, (_, _) => false, } } } +#[allow(clippy::comparison_chain)] fn proccess_macro_path(span: Span, import: &str, import_map: &mut FxHashMap<String, Vec<ModPath>>) { let mut mod_path = import.split("::").collect::<Vec<_>>(); if mod_path.len() == 2 { - let item_list = import_map.entry(mod_path[0].to_string()) - .or_insert(vec![]); + let item_list = import_map.entry(mod_path[0].to_string()).or_insert_with(Vec::new); if !item_list.iter().any(|mods| mods.item() == mod_path[1]) { - item_list.push(ModPath::Item{ + item_list.push(ModPath::Item { item: mod_path[1].to_string(), span, }); @@ -288,46 +339,16 @@ fn proccess_macro_path(span: Span, import: &str, import_map: &mut FxHashMap<Stri let name = mod_path.remove(mod_path.len() - 1); let nested = ModPath::Nested { - names: mod_path.into_iter().map(ToString::to_string).collect(), + segments: mod_path.into_iter().map(ToString::to_string).collect(), item: name.to_string(), span, }; - import_map.entry(first.to_string()) - .or_insert(vec![]) - .push(nested); + // CLIPPY NOTE: this told me to use `or_insert_with(vec![])` + // import_map.entry(first.to_string()).or_insert(vec![]).push(nested); + // which failed as `vec!` is not a closure then told me to add `||` which failed + // with the redundant_closure lint so I finally gave up and used this. + import_map.entry(first.to_string()).or_insert_with(Vec::new).push(nested); } else { unreachable!("test to see if code path hit TODO REMOVE") } } - -fn recursive_path_push(module: ModPath, comma: &str, rest: &[ModPath], mut path: String) -> String { - match &module { - ModPath::Item { item, .. } => { - path.push_str(&format!("{}{}", item, comma)); - } - ModPath::Nested { names, item, span } => { - let nested = rest.iter() - // filter "self" out - .filter(|other_m| other_m != &&module) - // this matches the first path segment and filters non ModPath::Nested items - .filter(|other_m| other_m.matches(0, &module)) - .collect::<Vec<_>>(); - - println!("{:#?}", nested); - - if nested.is_empty() { - path.push_str(&format!("{}::{}{}", names.join("::").to_string(), item, comma)) - } else { - // use mod_a::{mod_b::{one, two}, mod_c::item, item1, item2} - let mod_path = if names.len() - 1 > 0 { - ModPath::Nested { names: names.clone(), item: item.to_string(), span: *span, } - } else { - ModPath::Item { item: names[0].to_string(), span: *span, } - }; - let names = recursive_path_push(mod_path, comma, rest, path.to_string()); - // path.push_str(&format!("{}{}", item, comma)); - } - } - } - path -} diff --git a/tests/ui/auxiliary/macro_use_helper.rs b/tests/ui/auxiliary/macro_use_helper.rs index 7cc4e1d736a..ecb55d8cb48 100644 --- a/tests/ui/auxiliary/macro_use_helper.rs +++ b/tests/ui/auxiliary/macro_use_helper.rs @@ -13,8 +13,13 @@ pub mod inner { // RE-EXPORT // this will stick in `inner` module + pub use macro_rules::foofoo; pub use macro_rules::try_err; + pub mod nested { + pub use macro_rules::string_add; + } + // ITEM #[macro_export] macro_rules! inner_mod_macro { diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index 2d4f71e5d53..52dec0e44b3 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -18,6 +18,8 @@ mod a { use mini_mac; #[macro_use] use mac::inner; + #[macro_use] + use mac::inner::nested; #[derive(ClippyMiniMacroTest)] struct Test; @@ -30,6 +32,8 @@ mod a { let v: ty_macro!() = Vec::default(); inner::try_err!(); + inner::foofoo!(); + nested::string_add!(); } } diff --git a/tests/ui/macro_use_imports.stderr b/tests/ui/macro_use_imports.stderr index 6bcacd0be19..00c76c19ea9 100644 --- a/tests/ui/macro_use_imports.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -1,8 +1,8 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:15:5 + --> $DIR/macro_use_imports.rs:17:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::pub_macro` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use use mini_mac::ClippyMiniMacroTest;` | = note: `-D clippy::macro-use-imports` implied by `-D warnings` @@ -10,37 +10,7 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:15:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner_mod_macro` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro, inner::{foofoo, try_err, nested::string_add}};` -error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:15:5 - | -LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::function_macro` - -error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:15:5 - | -LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::ty_macro` - -error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:15:5 - | -LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::pub_in_private_macro` - -error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:17:5 - | -LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest` - -error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:19:5 - | -LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::try_err` - -error: aborting due to 7 previous errors +error: aborting due to 2 previous errors From 8c5a5a92ec6f298a067ba052a0d5b6150537c1c9 Mon Sep 17 00:00:00 2001 From: Devin R <devin.ragotzy@gmail.com> Date: Tue, 26 May 2020 19:57:36 -0400 Subject: [PATCH 195/526] cleaned up import suggestion formatter, look into code reuse with wildcard impotrs --- clippy_lints/src/macro_use.rs | 222 +++++++----------------------- tests/ui/macro_use_imports.stderr | 18 ++- 2 files changed, 63 insertions(+), 177 deletions(-) diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 1e1f27e9430..089ae79b02c 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -29,6 +29,12 @@ declare_clippy_lint! { const BRACKETS: &[char] = &['<', '>']; +#[derive(Clone, Debug, PartialEq, Eq)] +struct PathAndSpan { + path: String, + span: Span, +} + /// `MacroRefData` includes the name of the macro /// and the path from `SourceMap::span_to_filename`. #[derive(Debug, Clone)] @@ -110,7 +116,8 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { for kid in cx.tcx.item_children(id).iter() { if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { let span = mac_attr.span; - self.imports.push((cx.tcx.def_path_str(mac_id), span)); + let def_path = cx.tcx.def_path_str(mac_id); + self.imports.push((def_path, span)); } } } else { @@ -147,127 +154,69 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { } #[allow(clippy::too_many_lines)] fn check_crate_post(&mut self, cx: &LateContext<'_, '_>, _krate: &hir::Crate<'_>) { - let mut import_map = FxHashMap::default(); + let mut used = FxHashMap::default(); + let mut check_dup = vec![]; for (import, span) in &self.imports { let found_idx = self.mac_refs.iter().position(|mac| import.ends_with(&mac.name)); if let Some(idx) = found_idx { let _ = self.mac_refs.remove(idx); - proccess_macro_path(*span, import, &mut import_map); - } - } - // println!("{:#?}", import_map); - let mut imports = vec![]; - for (root, rest) in import_map { - let mut path = format!("use {}::", root); - let mut attr_span = None; - // when a multiple nested paths are found one may be written to the string - // before it is found in this loop so we make note and skip it when this - // loop finds it - let mut found_nested = vec![]; - let mut count = 1; - let rest_len = rest.len(); + let seg = import.split("::").collect::<Vec<_>>(); - if rest_len > 1 { - path.push_str("{"); - } - - for m in &rest { - if attr_span.is_none() { - attr_span = Some(m.span()); - } - if found_nested.contains(&m) { - continue; - } - let comma = if rest_len == count { "" } else { ", " }; - match m { - ModPath::Item { item, .. } => { - path.push_str(&format!("{}{}", item, comma)); + match seg.as_slice() { + [] => unreachable!("this should never be empty"), + [_] => unreachable!("path must have two segments ?"), + [root, item] => { + if !check_dup.contains(&item.to_string()) { + used.entry((root.to_string(), span)) + .or_insert(vec![]) + .push(item.to_string()); + check_dup.push(item.to_string()); + } }, - ModPath::Nested { segments, item, .. } => { - // do any other Nested paths match the current one - let nested = rest - .iter() - // filter "self" out - .filter(|other_m| other_m != &m) - // filters out Nested we have previously seen - .filter(|other_m| !found_nested.contains(other_m)) - // this matches the first path segment and filters non ModPath::Nested items - .filter(|other_m| other_m.matches(0, m)) - .collect::<Vec<_>>(); - - if nested.is_empty() { - path.push_str(&format!("{}::{}{}", segments.join("::").to_string(), item, comma)) - // use mod_a::{mod_b::{one, two}, mod_c::item} + [root, rest @ ..] => { + if !rest.iter().all(|item| !check_dup.contains(&item.to_string())) { + let mut rest = rest.to_vec(); + rest.sort(); + used.entry((root.to_string(), span)) + .or_insert(vec![]) + .push(rest.join("::")); + check_dup.extend(rest.iter().map(ToString::to_string)); } else { - found_nested.extend(nested.iter()); - found_nested.push(&m); - // we check each segment for matches with other import paths if - // one differs we have to open a new `{}` - for (idx, seg) in segments.iter().enumerate() { - path.push_str(&format!("{}::", seg)); - if nested.iter().all(|other_m| other_m.matches(idx, &m)) { - continue; - } - - path.push_str("{"); - let matched_seg_items = nested - .iter() - .filter(|other_m| !other_m.matches(idx, &m)) - .collect::<Vec<_>>(); - for item in matched_seg_items { - if let ModPath::Nested { item, .. } = item { - path.push_str(&format!( - "{}{}", - item, - if nested.len() == idx + 1 { "" } else { ", " } - )); - } - } - path.push_str("}"); - } - path.push_str(&format!("{{{}{}", item, comma)); - for (i, item) in nested.iter().enumerate() { - if let ModPath::Nested { item, segments: matched_seg, .. } = item { - path.push_str(&format!( - "{}{}{}", - if matched_seg > segments { - format!("{}::", matched_seg[segments.len()..].join("::")) - } else { - String::new() - }, - item, - if nested.len() == i + 1 { "" } else { ", " } - )); - } - } - path.push_str("}"); + let mut filtered = rest + .iter() + .filter(|item| !check_dup.contains(&item.to_string())) + .map(ToString::to_string) + .collect::<Vec<_>>(); + filtered.sort(); + used.entry((root.to_string(), span)) + .or_insert(vec![]) + .push(filtered.join("::")); + check_dup.extend(filtered); } }, } - count += 1; } - if rest_len > 1 { - path.push_str("};"); + } + + let mut suggestions = vec![]; + for ((root, span), path) in used { + if path.len() == 1 { + suggestions.push((span, format!("{}::{}", root, path[0]))) } else { - path.push_str(";"); - } - if let Some(span) = attr_span { - imports.push((span, path)) - } else { - unreachable!("a span must always be attached to a macro_use attribute") + suggestions.push((span, format!("{}::{{{}}}", root, path.join(", ")))) } } // If mac_refs is not empty we have encountered an import we could not handle // such as `std::prelude::v1::foo` or some other macro that expands to an import. if self.mac_refs.is_empty() { - for (span, import) in imports { + for (span, import) in suggestions { let help = format!("use {}", import); span_lint_and_sugg( cx, MACRO_USE_IMPORTS, - span, + *span, "`macro_use` attributes are no longer needed in the Rust 2018 edition", "remove the attribute and import the macro directly, try", help, @@ -277,78 +226,3 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { } } } - -#[derive(Debug, PartialEq)] -enum ModPath { - Item { - item: String, - span: Span, - }, - Nested { - segments: Vec<String>, - item: String, - span: Span, - }, -} - -impl ModPath { - fn span(&self) -> Span { - match self { - Self::Item { span, .. } | Self::Nested { span, .. } => *span, - } - } - - fn item(&self) -> &str { - match self { - Self::Item { item, .. } | Self::Nested { item, .. } => item, - } - } - - fn matches(&self, idx: usize, other: &ModPath) -> bool { - match (self, other) { - (Self::Item { item, .. }, Self::Item { item: other_item, .. }) => item == other_item, - ( - Self::Nested { segments, .. }, - Self::Nested { - segments: other_names, .. - }, - ) => match (segments.get(idx), other_names.get(idx)) { - (Some(seg), Some(other_seg)) => seg == other_seg, - (_, _) => false, - }, - (_, _) => false, - } - } -} - -#[allow(clippy::comparison_chain)] -fn proccess_macro_path(span: Span, import: &str, import_map: &mut FxHashMap<String, Vec<ModPath>>) { - let mut mod_path = import.split("::").collect::<Vec<_>>(); - - if mod_path.len() == 2 { - let item_list = import_map.entry(mod_path[0].to_string()).or_insert_with(Vec::new); - - if !item_list.iter().any(|mods| mods.item() == mod_path[1]) { - item_list.push(ModPath::Item { - item: mod_path[1].to_string(), - span, - }); - } - } else if mod_path.len() > 2 { - let first = mod_path.remove(0); - let name = mod_path.remove(mod_path.len() - 1); - - let nested = ModPath::Nested { - segments: mod_path.into_iter().map(ToString::to_string).collect(), - item: name.to_string(), - span, - }; - // CLIPPY NOTE: this told me to use `or_insert_with(vec![])` - // import_map.entry(first.to_string()).or_insert(vec![]).push(nested); - // which failed as `vec!` is not a closure then told me to add `||` which failed - // with the redundant_closure lint so I finally gave up and used this. - import_map.entry(first.to_string()).or_insert_with(Vec::new).push(nested); - } else { - unreachable!("test to see if code path hit TODO REMOVE") - } -} diff --git a/tests/ui/macro_use_imports.stderr b/tests/ui/macro_use_imports.stderr index 00c76c19ea9..83c8ebe6ab9 100644 --- a/tests/ui/macro_use_imports.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -2,15 +2,27 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:17:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use use mini_mac::ClippyMiniMacroTest;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest` | = note: `-D clippy::macro-use-imports` implied by `-D warnings` +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:21:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add` + +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:19:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{foofoo::inner, inner::try_err}` + error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:15:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro, inner::{foofoo, try_err, nested::string_add}};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro}` -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors From 288df59b25c04f05d08d817727a8ac9c8d0d6648 Mon Sep 17 00:00:00 2001 From: Devin R <devin.ragotzy@gmail.com> Date: Sun, 7 Jun 2020 16:12:35 -0400 Subject: [PATCH 196/526] Fix suggestion output, add run-rustfix to test file, stop sorting import segments duh --- clippy_lints/src/macro_use.rs | 35 +++++++++++++------------- tests/ui/macro_use_imports.fixed | 41 +++++++++++++++++++++++++++++++ tests/ui/macro_use_imports.rs | 1 + tests/ui/macro_use_imports.stderr | 16 ++++++------ 4 files changed, 68 insertions(+), 25 deletions(-) create mode 100644 tests/ui/macro_use_imports.fixed diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 089ae79b02c..7e3ce07254f 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -167,32 +167,33 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { [] => unreachable!("this should never be empty"), [_] => unreachable!("path must have two segments ?"), [root, item] => { - if !check_dup.contains(&item.to_string()) { + if !check_dup.contains(&(*item).to_string()) { used.entry((root.to_string(), span)) - .or_insert(vec![]) + .or_insert_with(|| vec![]) .push(item.to_string()); check_dup.push(item.to_string()); } }, [root, rest @ ..] => { - if !rest.iter().all(|item| !check_dup.contains(&item.to_string())) { - let mut rest = rest.to_vec(); - rest.sort(); - used.entry((root.to_string(), span)) - .or_insert(vec![]) - .push(rest.join("::")); - check_dup.extend(rest.iter().map(ToString::to_string)); - } else { - let mut filtered = rest + if rest.iter().all(|item| !check_dup.contains(&(*item).to_string())) { + let filtered = rest .iter() - .filter(|item| !check_dup.contains(&item.to_string())) - .map(ToString::to_string) + .filter_map(|item| if check_dup.contains(&(*item).to_string()) { + None + } else { + Some(item.to_string()) + }) .collect::<Vec<_>>(); - filtered.sort(); - used.entry((root.to_string(), span)) - .or_insert(vec![]) + used.entry(((*root).to_string(), span)) + .or_insert_with(|| vec![]) .push(filtered.join("::")); check_dup.extend(filtered); + } else { + let rest = rest.to_vec(); + used.entry((root.to_string(), span)) + .or_insert_with(|| vec![]) + .push(rest.join("::")); + check_dup.extend(rest.iter().map(ToString::to_string)); } }, } @@ -212,7 +213,7 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { // such as `std::prelude::v1::foo` or some other macro that expands to an import. if self.mac_refs.is_empty() { for (span, import) in suggestions { - let help = format!("use {}", import); + let help = format!("use {};", import); span_lint_and_sugg( cx, MACRO_USE_IMPORTS, diff --git a/tests/ui/macro_use_imports.fixed b/tests/ui/macro_use_imports.fixed new file mode 100644 index 00000000000..8034c56b59a --- /dev/null +++ b/tests/ui/macro_use_imports.fixed @@ -0,0 +1,41 @@ +// compile-flags: --edition 2018 +// aux-build:macro_rules.rs +// aux-build:macro_use_helper.rs +// run-rustfix + +#![allow(clippy::single_component_path_imports)] +#![warn(clippy::macro_use_imports)] + +#[macro_use] +extern crate macro_use_helper as mac; + +#[macro_use] +extern crate clippy_mini_macro_test as mini_mac; + +mod a { + use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro}; + use mac; + use mini_mac::ClippyMiniMacroTest; + use mini_mac; + use mac::{inner::foofoo, inner::try_err}; + use mac::inner; + use mac::inner::nested::string_add; + use mac::inner::nested; + + #[derive(ClippyMiniMacroTest)] + struct Test; + + fn test() { + pub_macro!(); + inner_mod_macro!(); + pub_in_private_macro!(_var); + function_macro!(); + let v: ty_macro!() = Vec::default(); + + inner::try_err!(); + inner::foofoo!(); + nested::string_add!(); + } +} + +fn main() {} diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index 52dec0e44b3..7d415222d64 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -1,6 +1,7 @@ // compile-flags: --edition 2018 // aux-build:macro_rules.rs // aux-build:macro_use_helper.rs +// run-rustfix #![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] diff --git a/tests/ui/macro_use_imports.stderr b/tests/ui/macro_use_imports.stderr index 83c8ebe6ab9..6feda8a5222 100644 --- a/tests/ui/macro_use_imports.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -1,28 +1,28 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:17:5 + --> $DIR/macro_use_imports.rs:18:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` | = note: `-D clippy::macro-use-imports` implied by `-D warnings` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:21:5 + --> $DIR/macro_use_imports.rs:20:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:19:5 + --> $DIR/macro_use_imports.rs:16:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{foofoo::inner, inner::try_err}` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:15:5 + --> $DIR/macro_use_imports.rs:22:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro}` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` error: aborting due to 4 previous errors From e521a4ed3818c02a1831db570e69d056c351ee05 Mon Sep 17 00:00:00 2001 From: Devin R <devin.ragotzy@gmail.com> Date: Sun, 7 Jun 2020 16:25:21 -0400 Subject: [PATCH 197/526] Add enough attrs to the test file so the fix compiles with no errors, fmt/`clippy` --- clippy_lints/src/macro_use.rs | 29 ++++++++++++++++------------- tests/ui/macro_use_imports.fixed | 2 ++ tests/ui/macro_use_imports.rs | 2 ++ tests/ui/macro_use_imports.stderr | 16 ++++++++-------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 7e3ce07254f..b845b20d2c0 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -164,34 +164,37 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { let seg = import.split("::").collect::<Vec<_>>(); match seg.as_slice() { - [] => unreachable!("this should never be empty"), - [_] => unreachable!("path must have two segments ?"), + // an empty path is impossible + // a path should always consist of 2 or more segments + [] | [_] => return, [root, item] => { if !check_dup.contains(&(*item).to_string()) { - used.entry((root.to_string(), span)) - .or_insert_with(|| vec![]) - .push(item.to_string()); - check_dup.push(item.to_string()); + used.entry(((*root).to_string(), span)) + .or_insert_with(Vec::new) + .push((*item).to_string()); + check_dup.push((*item).to_string()); } }, [root, rest @ ..] => { if rest.iter().all(|item| !check_dup.contains(&(*item).to_string())) { let filtered = rest .iter() - .filter_map(|item| if check_dup.contains(&(*item).to_string()) { - None - } else { - Some(item.to_string()) + .filter_map(|item| { + if check_dup.contains(&(*item).to_string()) { + None + } else { + Some((*item).to_string()) + } }) .collect::<Vec<_>>(); used.entry(((*root).to_string(), span)) - .or_insert_with(|| vec![]) + .or_insert_with(Vec::new) .push(filtered.join("::")); check_dup.extend(filtered); } else { let rest = rest.to_vec(); - used.entry((root.to_string(), span)) - .or_insert_with(|| vec![]) + used.entry(((*root).to_string(), span)) + .or_insert_with(Vec::new) .push(rest.join("::")); check_dup.extend(rest.iter().map(ToString::to_string)); } diff --git a/tests/ui/macro_use_imports.fixed b/tests/ui/macro_use_imports.fixed index 8034c56b59a..91e34c62160 100644 --- a/tests/ui/macro_use_imports.fixed +++ b/tests/ui/macro_use_imports.fixed @@ -2,7 +2,9 @@ // aux-build:macro_rules.rs // aux-build:macro_use_helper.rs // run-rustfix +// ignore-32bit +#![allow(unused_imports, unreachable_code, unused_variables, dead_code)] #![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index 7d415222d64..9c3c50c5d49 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -2,7 +2,9 @@ // aux-build:macro_rules.rs // aux-build:macro_use_helper.rs // run-rustfix +// ignore-32bit +#![allow(unused_imports, unreachable_code, unused_variables, dead_code)] #![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] diff --git a/tests/ui/macro_use_imports.stderr b/tests/ui/macro_use_imports.stderr index 6feda8a5222..f8c86c8d917 100644 --- a/tests/ui/macro_use_imports.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -2,7 +2,7 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:18:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` | = note: `-D clippy::macro-use-imports` implied by `-D warnings` @@ -10,17 +10,17 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:20:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};` - -error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:16:5 - | -LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:22:5 | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};` + +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:24:5 + | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` From a083b84b783a2c9e622c9d618e751da22adaff37 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Tue, 9 Jun 2020 23:49:21 +0200 Subject: [PATCH 198/526] if_same_then_else: don't assume multiplication is always commutative --- clippy_lints/src/utils/hir_utils.rs | 13 +++++-------- tests/ui/if_same_then_else.rs | 12 ++++++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index f8d197c15e8..6846658b6e2 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -309,18 +309,15 @@ fn swap_binop<'a>( rhs: &'a Expr<'a>, ) -> Option<(BinOpKind, &'a Expr<'a>, &'a Expr<'a>)> { match binop { - BinOpKind::Add - | BinOpKind::Mul - | BinOpKind::Eq - | BinOpKind::Ne - | BinOpKind::BitAnd - | BinOpKind::BitXor - | BinOpKind::BitOr => Some((binop, rhs, lhs)), + BinOpKind::Add | BinOpKind::Eq | BinOpKind::Ne | BinOpKind::BitAnd | BinOpKind::BitXor | BinOpKind::BitOr => { + Some((binop, rhs, lhs)) + }, BinOpKind::Lt => Some((BinOpKind::Gt, rhs, lhs)), BinOpKind::Le => Some((BinOpKind::Ge, rhs, lhs)), BinOpKind::Ge => Some((BinOpKind::Le, rhs, lhs)), BinOpKind::Gt => Some((BinOpKind::Lt, rhs, lhs)), - BinOpKind::Shl + BinOpKind::Mul + | BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Rem | BinOpKind::Sub diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index 6bbf79edfcf..9c5fe02f751 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -142,4 +142,16 @@ fn func() { fn f(val: &[u8]) {} +mod issue_5698 { + fn mul_not_always_commutative(x: i32, y: i32) -> i32 { + if x == 42 { + x * y + } else if x == 21 { + y * x + } else { + 0 + } + } +} + fn main() {} From 2f74283fce768a262387fe7f51e1e4ebb9b0e300 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Wed, 10 Jun 2020 00:14:02 +0200 Subject: [PATCH 199/526] Add a comment linking to the issue --- clippy_lints/src/utils/hir_utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 6846658b6e2..9c2c96203c0 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -316,7 +316,7 @@ fn swap_binop<'a>( BinOpKind::Le => Some((BinOpKind::Ge, rhs, lhs)), BinOpKind::Ge => Some((BinOpKind::Le, rhs, lhs)), BinOpKind::Gt => Some((BinOpKind::Lt, rhs, lhs)), - BinOpKind::Mul + BinOpKind::Mul // Not always commutative, e.g. with matrices. See issue #5698 | BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Rem From 56f25e3e62dbdd8f84a9152bbfb73a35055363dd Mon Sep 17 00:00:00 2001 From: David Tolnay <dtolnay@gmail.com> Date: Wed, 10 Jun 2020 19:29:11 -0700 Subject: [PATCH 200/526] Downgrade unnested_or_patterns to pedantic --- clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/unnested_or_patterns.rs | 2 +- src/lintlist/mod.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 021fbe932d8..19e1b00050a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1187,6 +1187,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::OPTION_OPTION), LintId::of(&unicode::NON_ASCII_LITERAL), LintId::of(&unicode::UNICODE_NOT_NFC), + LintId::of(&unnested_or_patterns::UNNESTED_OR_PATTERNS), LintId::of(&unused_self::UNUSED_SELF), LintId::of(&wildcard_imports::ENUM_GLOB_USE), LintId::of(&wildcard_imports::WILDCARD_IMPORTS), @@ -1440,7 +1441,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS), LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS), LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), - LintId::of(&unnested_or_patterns::UNNESTED_OR_PATTERNS), LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), LintId::of(&unwrap::PANICKING_UNWRAP), @@ -1624,7 +1624,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::UNNECESSARY_CAST), LintId::of(&types::VEC_BOX), LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), - LintId::of(&unnested_or_patterns::UNNESTED_OR_PATTERNS), LintId::of(&unwrap::UNNECESSARY_UNWRAP), LintId::of(&useless_conversion::USELESS_CONVERSION), LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO), diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 8c281126c32..4d3682263f1 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -45,7 +45,7 @@ declare_clippy_lint! { /// } /// ``` pub UNNESTED_OR_PATTERNS, - complexity, + pedantic, "unnested or-patterns, e.g., `Foo(Bar) | Foo(Baz) instead of `Foo(Bar | Baz)`" } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index cac3cc6bdb3..edceb755180 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2329,7 +2329,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ }, Lint { name: "unnested_or_patterns", - group: "complexity", + group: "pedantic", desc: "unnested or-patterns, e.g., `Foo(Bar) | Foo(Baz) instead of `Foo(Bar | Baz)`", deprecation: None, module: "unnested_or_patterns", From 840786a93976d5885bfe6c7878cecc99e4a56432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Mon, 1 Jun 2020 00:22:29 +0200 Subject: [PATCH 201/526] clippy-driver: pass all args after "--rustc" to rustc. --- src/driver.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 4453ae5ce44..1956effa827 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -297,12 +297,6 @@ pub fn main() { exit(rustc_driver::catch_with_exit_code(move || { let mut orig_args: Vec<String> = env::args().collect(); - if orig_args.iter().any(|a| a == "--version" || a == "-V") { - let version_info = rustc_tools_util::get_version_info!(); - println!("{}", version_info); - exit(0); - } - // Get the sysroot, looking from most specific to this invocation to the least: // - command line // - runtime environment @@ -348,6 +342,29 @@ pub fn main() { .map(|pb| pb.to_string_lossy().to_string()) .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); + // make "clippy-driver --rustc" work like a subcommand that passes further args to "rustc" + // for example `clippy-driver --rustc --version` will print the rustc version that clippy-driver + // uses + if let Some(pos) = orig_args.iter().position(|arg| arg == "--rustc") { + orig_args.remove(pos); + orig_args[0] = "rustc".to_string(); + + // if we call "rustc", we need to pass --sysroot here as well + let mut args: Vec<String> = orig_args.clone(); + if !have_sys_root_arg { + args.extend(vec!["--sysroot".into(), sys_root]); + }; + + println!("args: {:?}", args); + return rustc_driver::run_compiler(&args, &mut DefaultCallbacks, None, None); + } + + if orig_args.iter().any(|a| a == "--version" || a == "-V") { + let version_info = rustc_tools_util::get_version_info!(); + println!("{}", version_info); + exit(0); + } + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. // We're invoking the compiler programmatically, so we ignore this/ let wrapper_mode = orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref()); From 88ab10400b81338782c729e4193e47cd3ef1cab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 2 Jun 2020 14:50:44 +0200 Subject: [PATCH 202/526] add test and remove debug print --- .github/driver.sh | 5 +++++ src/driver.rs | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/driver.sh b/.github/driver.sh index a2e87f5eb37..c797bdb14db 100644 --- a/.github/driver.sh +++ b/.github/driver.sh @@ -26,4 +26,9 @@ unset CARGO_MANIFEST_DIR sed -e "s,tests/ui,\$DIR," -e "/= help/d" cstring.stderr > normalized.stderr diff normalized.stderr tests/ui/cstring.stderr + +# make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same +SYSROOT=`rustc --print sysroot` +diff <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose) + # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR diff --git a/src/driver.rs b/src/driver.rs index 1956effa827..5ef8d3cf809 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -355,7 +355,6 @@ pub fn main() { args.extend(vec!["--sysroot".into(), sys_root]); }; - println!("args: {:?}", args); return rustc_driver::run_compiler(&args, &mut DefaultCallbacks, None, None); } From f1d5cd5d13bbd59c21e70e2e728c3db9829cf816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Sun, 7 Jun 2020 16:27:41 +0200 Subject: [PATCH 203/526] add test for compiler output when compiling with rustc/clippy-driver --- .github/driver.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/driver.sh b/.github/driver.sh index c797bdb14db..f8139f36369 100644 --- a/.github/driver.sh +++ b/.github/driver.sh @@ -31,4 +31,9 @@ diff normalized.stderr tests/ui/cstring.stderr SYSROOT=`rustc --print sysroot` diff <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose) +# we can't run 2 rustcs on the same file at the same time +CLIPPY=`LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver tests/driver/main.rs` +RUSTC=`rustc tests/driver/main.rs` +diff <($CLIPPY) <($RUSTC) + # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR From 7a62380fc8f8ca39bc49b8f67a4d4929911cb036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 9 Jun 2020 13:18:00 +0200 Subject: [PATCH 204/526] clippy-driver: fix test and add --rustc to --help output --- .github/driver.sh | 6 ++++-- src/driver.rs | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/driver.sh b/.github/driver.sh index f8139f36369..2c17c4203ae 100644 --- a/.github/driver.sh +++ b/.github/driver.sh @@ -31,9 +31,11 @@ diff normalized.stderr tests/ui/cstring.stderr SYSROOT=`rustc --print sysroot` diff <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose) + +echo "fn main() {}" > target/driver_test.rs # we can't run 2 rustcs on the same file at the same time -CLIPPY=`LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver tests/driver/main.rs` -RUSTC=`rustc tests/driver/main.rs` +CLIPPY=`LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver ./target/driver_test.rs --rustc` +RUSTC=`rustc ./target/driver_test.rs` diff <($CLIPPY) <($RUSTC) # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR diff --git a/src/driver.rs b/src/driver.rs index 5ef8d3cf809..6faa5e9fe66 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -207,6 +207,7 @@ Usage: Common options: -h, --help Print this message + --rustc Pass all args to rustc -V, --version Print version info and exit Other options are the same as `cargo check`. From b21ef2b365ef4f5c973327f3f6064b8be42d1dae Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sat, 13 Jun 2020 00:52:32 +0200 Subject: [PATCH 205/526] Fix ICE in consts::binop --- clippy_lints/src/consts.rs | 2 +- tests/ui/crashes/ice-5389.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/ui/crashes/ice-5389.rs diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 81ddc8c0067..e3c6908b76b 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -396,7 +396,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { let l = self.expr(left)?; let r = self.expr(right); match (l, r) { - (Constant::Int(l), Some(Constant::Int(r))) => match self.tables.expr_ty(left).kind { + (Constant::Int(l), Some(Constant::Int(r))) => match self.tables.expr_ty_opt(left)?.kind { ty::Int(ity) => { let l = sext(self.lcx.tcx, l, ity); let r = sext(self.lcx.tcx, r, ity); diff --git a/tests/ui/crashes/ice-5389.rs b/tests/ui/crashes/ice-5389.rs new file mode 100644 index 00000000000..de262199004 --- /dev/null +++ b/tests/ui/crashes/ice-5389.rs @@ -0,0 +1,13 @@ +#![allow(clippy::explicit_counter_loop)] + +fn main() { + let v = vec![1, 2, 3]; + let mut i = 0; + let max_storage_size = [0; 128 * 1024]; + for item in &v { + bar(i, *item); + i += 1; + } +} + +fn bar(_: usize, _: u32) {} From dee794f4503dda6a10891b49a7cb2f8bb92e001b Mon Sep 17 00:00:00 2001 From: Bastian Kauschke <bastian_kauschke@hotmail.de> Date: Sat, 13 Jun 2020 12:42:58 +0200 Subject: [PATCH 206/526] typo --- clippy_lints/src/new_without_default.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index dd236535c18..42200385932 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -33,7 +33,7 @@ declare_clippy_lint! { /// } /// ``` /// - /// To fix the lint, and a `Default` implementation that delegates to `new`: + /// To fix the lint, add a `Default` implementation that delegates to `new`: /// /// ```ignore /// struct Foo(Bar); From f663a21c8f51db58ff73e2e0d9852d03e8916a5e Mon Sep 17 00:00:00 2001 From: Iain Brandram-Adams <ijijnj@gmail.com> Date: Sun, 14 Jun 2020 01:24:36 +1200 Subject: [PATCH 207/526] Remove `bar` from blacklisted names --- clippy_lints/src/utils/conf.rs | 2 +- tests/ui/blacklisted_name.rs | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 9e8e0ff30ec..418c4ded544 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -107,7 +107,7 @@ macro_rules! define_Conf { pub use self::helpers::Conf; define_Conf! { /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about - (blacklisted_names, "blacklisted_names": Vec<String>, ["foo", "bar", "baz", "quux"].iter().map(ToString::to_string).collect()), + (blacklisted_names, "blacklisted_names": Vec<String>, ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()), /// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have (cognitive_complexity_threshold, "cognitive_complexity_threshold": u64, 25), /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. Use the Cognitive Complexity lint instead. diff --git a/tests/ui/blacklisted_name.rs b/tests/ui/blacklisted_name.rs index ca9d8d16b78..3d87eb06181 100644 --- a/tests/ui/blacklisted_name.rs +++ b/tests/ui/blacklisted_name.rs @@ -12,29 +12,32 @@ fn test(foo: ()) {} fn main() { let foo = 42; - let bar = 42; let baz = 42; + let quux = 42; + // Unlike these others, `bar` is considered an acceptable name to use. + // See https://github.com/rust-lang/rust-clippy/issues/5225. - let barb = 42; - let barbaric = 42; + let food = 42; + let foodstuffs = 42; + let bazaar = 42; match (42, Some(1337), Some(0)) { - (foo, Some(bar), baz @ Some(_)) => (), + (foo, Some(baz), quux @ Some(_)) => (), _ => (), } } fn issue_1647(mut foo: u8) { - let mut bar = 0; - if let Some(mut baz) = Some(42) {} + let mut baz = 0; + if let Some(mut quux) = Some(42) {} } fn issue_1647_ref() { - let ref bar = 0; - if let Some(ref baz) = Some(42) {} + let ref baz = 0; + if let Some(ref quux) = Some(42) {} } fn issue_1647_ref_mut() { - let ref mut bar = 0; - if let Some(ref mut baz) = Some(42) {} + let ref mut baz = 0; + if let Some(ref mut quux) = Some(42) {} } From 40ee620e51c86c72e3c2b65df71f5f0a4a79797f Mon Sep 17 00:00:00 2001 From: Teddy_Wang <wangtheo662@gmail.com> Date: Mon, 8 Jun 2020 00:35:10 -0400 Subject: [PATCH 208/526] Added a lint for .map(|x| x) --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 ++ clippy_lints/src/map_identity.rs | 126 +++++++++++++++++++++++++++++++ src/lintlist/mod.rs | 7 ++ tests/ui/map_flatten.fixed | 1 + tests/ui/map_flatten.rs | 1 + tests/ui/map_flatten.stderr | 4 +- tests/ui/map_identity.fixed | 23 ++++++ tests/ui/map_identity.rs | 25 ++++++ tests/ui/map_identity.stderr | 37 +++++++++ 10 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 clippy_lints/src/map_identity.rs create mode 100644 tests/ui/map_identity.fixed create mode 100644 tests/ui/map_identity.rs create mode 100644 tests/ui/map_identity.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index adc945a6944..d6186c319d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1508,6 +1508,7 @@ Released 2018-09-13 [`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone [`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry [`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten +[`map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_identity [`map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or [`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref [`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 021fbe932d8..8b5e0b84eb4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -252,6 +252,7 @@ mod main_recursion; mod manual_async_fn; mod manual_non_exhaustive; mod map_clone; +mod map_identity; mod map_unit_fn; mod match_on_vec_items; mod matches; @@ -631,6 +632,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &manual_async_fn::MANUAL_ASYNC_FN, &manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, &map_clone::MAP_CLONE, + &map_identity::MAP_IDENTITY, &map_unit_fn::OPTION_MAP_UNIT_FN, &map_unit_fn::RESULT_MAP_UNIT_FN, &match_on_vec_items::MATCH_ON_VEC_ITEMS, @@ -1080,6 +1082,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_early_pass(|| box unnested_or_patterns::UnnestedOrPatterns); store.register_late_pass(|| box macro_use::MacroUseImports::default()); + store.register_late_pass(|| box map_identity::MapIdentity); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1295,6 +1298,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&manual_async_fn::MANUAL_ASYNC_FN), LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), LintId::of(&map_clone::MAP_CLONE), + LintId::of(&map_identity::MAP_IDENTITY), LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN), LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN), LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), @@ -1573,6 +1577,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::EXPLICIT_COUNTER_LOOP), LintId::of(&loops::MUT_RANGE_BOUND), LintId::of(&loops::WHILE_LET_LOOP), + LintId::of(&map_identity::MAP_IDENTITY), LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN), LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN), LintId::of(&matches::MATCH_AS_REF), diff --git a/clippy_lints/src/map_identity.rs b/clippy_lints/src/map_identity.rs new file mode 100644 index 00000000000..9bc8f1bec1b --- /dev/null +++ b/clippy_lints/src/map_identity.rs @@ -0,0 +1,126 @@ +use crate::utils::{ + is_adjusted, is_type_diagnostic_item, match_path, match_trait_method, match_var, paths, remove_blocks, + span_lint_and_sugg, +}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Body, Expr, ExprKind, Pat, PatKind, QPath, StmtKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Checks for instances of `map(f)` where `f` is the identity function. + /// + /// **Why is this bad?** It can be written more concisely without the call to `map`. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// let x = [1, 2, 3]; + /// let y: Vec<_> = x.iter().map(|x| x).map(|x| 2*x).collect(); + /// ``` + /// Use instead: + /// ```rust + /// let x = [1, 2, 3]; + /// let y: Vec<_> = x.iter().map(|x| 2*x).collect(); + /// ``` + pub MAP_IDENTITY, + complexity, + "using iterator.map(|x| x)" +} + +declare_lint_pass!(MapIdentity => [MAP_IDENTITY]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapIdentity { + fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + if expr.span.from_expansion() { + return; + } + + if_chain! { + if let Some([caller, func]) = get_map_argument(cx, expr); + if is_expr_identity_function(cx, func); + then { + span_lint_and_sugg( + cx, + MAP_IDENTITY, + expr.span.trim_start(caller.span).unwrap(), + "unnecessary map of the identity function", + "remove the call to `map`", + String::new(), + Applicability::MachineApplicable + ) + } + } + } +} + +/// Returns the arguments passed into map() if the expression is a method call to +/// map(). Otherwise, returns None. +fn get_map_argument<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<&'a [Expr<'a>]> { + if_chain! { + if let ExprKind::MethodCall(ref method, _, ref args) = expr.kind; + if args.len() == 2 && method.ident.as_str() == "map"; + let caller_ty = cx.tables.expr_ty(&args[0]); + if match_trait_method(cx, expr, &paths::ITERATOR) + || is_type_diagnostic_item(cx, caller_ty, sym!(result_type)) + || is_type_diagnostic_item(cx, caller_ty, sym!(option_type)); + then { + Some(args) + } else { + None + } + } +} + +/// Checks if an expression represents the identity function +/// Only examines closures and `std::convert::identity` +fn is_expr_identity_function(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + match expr.kind { + ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)), + ExprKind::Path(QPath::Resolved(_, ref path)) => match_path(path, &paths::STD_CONVERT_IDENTITY), + _ => false, + } +} + +/// Checks if a function's body represents the identity function +/// Looks for bodies of the form `|x| x`, `|x| return x`, `|x| { return x }` or `|x| { +/// return x; }` +fn is_body_identity_function(cx: &LateContext<'_, '_>, func: &Body<'_>) -> bool { + let params = func.params; + let body = remove_blocks(&func.value); + + // if there's less/more than one parameter, then it is not the identity function + if params.len() != 1 { + return false; + } + + match body.kind { + ExprKind::Path(QPath::Resolved(None, _)) => match_expr_param(cx, body, params[0].pat), + ExprKind::Ret(Some(ref ret_val)) => match_expr_param(cx, ret_val, params[0].pat), + ExprKind::Block(ref block, _) => { + if_chain! { + if block.stmts.len() == 1; + if let StmtKind::Semi(ref expr) | StmtKind::Expr(ref expr) = block.stmts[0].kind; + if let ExprKind::Ret(Some(ref ret_val)) = expr.kind; + then { + match_expr_param(cx, ret_val, params[0].pat) + } else { + false + } + } + }, + _ => false, + } +} + +/// Returns true iff an expression returns the same thing as a parameter's pattern +fn match_expr_param(cx: &LateContext<'_, '_>, expr: &Expr<'_>, pat: &Pat<'_>) -> bool { + if let PatKind::Binding(_, _, ident, _) = pat.kind { + match_var(expr, ident.name) && !(cx.tables.hir_owner == Some(expr.hir_id.owner) && is_adjusted(cx, expr)) + } else { + false + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index cac3cc6bdb3..a9cd5469048 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1144,6 +1144,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "methods", }, + Lint { + name: "map_identity", + group: "complexity", + desc: "using iterator.map(|x| x)", + deprecation: None, + module: "map_identity", + }, Lint { name: "map_unwrap_or", group: "pedantic", diff --git a/tests/ui/map_flatten.fixed b/tests/ui/map_flatten.fixed index 7ac368878ab..4171d80f48a 100644 --- a/tests/ui/map_flatten.fixed +++ b/tests/ui/map_flatten.fixed @@ -2,6 +2,7 @@ #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] +#![allow(clippy::map_identity)] fn main() { let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect(); diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index a608601039c..16a0fd090ad 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -2,6 +2,7 @@ #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::missing_docs_in_private_items)] +#![allow(clippy::map_identity)] fn main() { let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); diff --git a/tests/ui/map_flatten.stderr b/tests/ui/map_flatten.stderr index 3cf2abd5b6d..00bc41c15e9 100644 --- a/tests/ui/map_flatten.stderr +++ b/tests/ui/map_flatten.stderr @@ -1,5 +1,5 @@ error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` - --> $DIR/map_flatten.rs:7:21 + --> $DIR/map_flatten.rs:8:21 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)` @@ -7,7 +7,7 @@ LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().colle = note: `-D clippy::map-flatten` implied by `-D warnings` error: called `map(..).flatten()` on an `Option`. This is more succinctly expressed by calling `.and_then(..)` - --> $DIR/map_flatten.rs:8:24 + --> $DIR/map_flatten.rs:9:24 | LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `(Some(Some(1))).and_then(|x| x)` diff --git a/tests/ui/map_identity.fixed b/tests/ui/map_identity.fixed new file mode 100644 index 00000000000..4a1452b25f3 --- /dev/null +++ b/tests/ui/map_identity.fixed @@ -0,0 +1,23 @@ +// run-rustfix +#![warn(clippy::map_identity)] +#![allow(clippy::needless_return)] + +fn main() { + let x: [u16; 3] = [1, 2, 3]; + // should lint + let _: Vec<_> = x.iter().map(not_identity).collect(); + let _: Vec<_> = x.iter().collect(); + let _: Option<u8> = Some(3); + let _: Result<i8, f32> = Ok(-3); + // should not lint + let _: Vec<_> = x.iter().map(|x| 2 * x).collect(); + let _: Vec<_> = x.iter().map(not_identity).map(|x| return x - 4).collect(); + let _: Option<u8> = None.map(|x: u8| x - 1); + let _: Result<i8, f32> = Err(2.3).map(|x: i8| { + return x + 3; + }); +} + +fn not_identity(x: &u16) -> u16 { + *x +} diff --git a/tests/ui/map_identity.rs b/tests/ui/map_identity.rs new file mode 100644 index 00000000000..65c7e6e1ea5 --- /dev/null +++ b/tests/ui/map_identity.rs @@ -0,0 +1,25 @@ +// run-rustfix +#![warn(clippy::map_identity)] +#![allow(clippy::needless_return)] + +fn main() { + let x: [u16; 3] = [1, 2, 3]; + // should lint + let _: Vec<_> = x.iter().map(not_identity).map(|x| return x).collect(); + let _: Vec<_> = x.iter().map(std::convert::identity).map(|y| y).collect(); + let _: Option<u8> = Some(3).map(|x| x); + let _: Result<i8, f32> = Ok(-3).map(|x| { + return x; + }); + // should not lint + let _: Vec<_> = x.iter().map(|x| 2 * x).collect(); + let _: Vec<_> = x.iter().map(not_identity).map(|x| return x - 4).collect(); + let _: Option<u8> = None.map(|x: u8| x - 1); + let _: Result<i8, f32> = Err(2.3).map(|x: i8| { + return x + 3; + }); +} + +fn not_identity(x: &u16) -> u16 { + *x +} diff --git a/tests/ui/map_identity.stderr b/tests/ui/map_identity.stderr new file mode 100644 index 00000000000..e4a0320cbda --- /dev/null +++ b/tests/ui/map_identity.stderr @@ -0,0 +1,37 @@ +error: unnecessary map of the identity function + --> $DIR/map_identity.rs:8:47 + | +LL | let _: Vec<_> = x.iter().map(not_identity).map(|x| return x).collect(); + | ^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + | + = note: `-D clippy::map-identity` implied by `-D warnings` + +error: unnecessary map of the identity function + --> $DIR/map_identity.rs:9:57 + | +LL | let _: Vec<_> = x.iter().map(std::convert::identity).map(|y| y).collect(); + | ^^^^^^^^^^^ help: remove the call to `map` + +error: unnecessary map of the identity function + --> $DIR/map_identity.rs:9:29 + | +LL | let _: Vec<_> = x.iter().map(std::convert::identity).map(|y| y).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + +error: unnecessary map of the identity function + --> $DIR/map_identity.rs:10:32 + | +LL | let _: Option<u8> = Some(3).map(|x| x); + | ^^^^^^^^^^^ help: remove the call to `map` + +error: unnecessary map of the identity function + --> $DIR/map_identity.rs:11:36 + | +LL | let _: Result<i8, f32> = Ok(-3).map(|x| { + | ____________________________________^ +LL | | return x; +LL | | }); + | |______^ help: remove the call to `map` + +error: aborting due to 5 previous errors + From c020e45cd3c1f10d1271de8b47cea9e00b73f500 Mon Sep 17 00:00:00 2001 From: Iain Brandram-Adams <ijijnj@gmail.com> Date: Sun, 14 Jun 2020 12:40:36 +1200 Subject: [PATCH 209/526] Update stderr to match, and reinforce comments --- tests/ui/blacklisted_name.rs | 4 +- tests/ui/blacklisted_name.stderr | 86 ++++++++++++++++---------------- 2 files changed, 46 insertions(+), 44 deletions(-) diff --git a/tests/ui/blacklisted_name.rs b/tests/ui/blacklisted_name.rs index 3d87eb06181..cb15bdd2f1b 100644 --- a/tests/ui/blacklisted_name.rs +++ b/tests/ui/blacklisted_name.rs @@ -14,8 +14,10 @@ fn main() { let foo = 42; let baz = 42; let quux = 42; - // Unlike these others, `bar` is considered an acceptable name to use. + // Unlike these others, `bar` is actually considered an acceptable name. + // Among many other legitimate uses, bar commonly refers to a period of time in music. // See https://github.com/rust-lang/rust-clippy/issues/5225. + let bar = 42; let food = 42; let foodstuffs = 42; diff --git a/tests/ui/blacklisted_name.stderr b/tests/ui/blacklisted_name.stderr index 44123829fb0..70dbdaece8b 100644 --- a/tests/ui/blacklisted_name.stderr +++ b/tests/ui/blacklisted_name.stderr @@ -12,77 +12,77 @@ error: use of a blacklisted/placeholder name `foo` LL | let foo = 42; | ^^^ -error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:15:9 - | -LL | let bar = 42; - | ^^^ - error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:16:9 + --> $DIR/blacklisted_name.rs:15:9 | LL | let baz = 42; | ^^^ -error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:22:10 +error: use of a blacklisted/placeholder name `quux` + --> $DIR/blacklisted_name.rs:16:9 | -LL | (foo, Some(bar), baz @ Some(_)) => (), +LL | let quux = 42; + | ^^^^ + +error: use of a blacklisted/placeholder name `foo` + --> $DIR/blacklisted_name.rs:27:10 + | +LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^ -error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:22:20 +error: use of a blacklisted/placeholder name `baz` + --> $DIR/blacklisted_name.rs:27:20 | -LL | (foo, Some(bar), baz @ Some(_)) => (), +LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^ -error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:22:26 +error: use of a blacklisted/placeholder name `quux` + --> $DIR/blacklisted_name.rs:27:26 | -LL | (foo, Some(bar), baz @ Some(_)) => (), - | ^^^ +LL | (foo, Some(baz), quux @ Some(_)) => (), + | ^^^^ error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:27:19 + --> $DIR/blacklisted_name.rs:32:19 | LL | fn issue_1647(mut foo: u8) { | ^^^ -error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:28:13 - | -LL | let mut bar = 0; - | ^^^ - error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:29:21 - | -LL | if let Some(mut baz) = Some(42) {} - | ^^^ - -error: use of a blacklisted/placeholder name `bar` --> $DIR/blacklisted_name.rs:33:13 | -LL | let ref bar = 0; +LL | let mut baz = 0; | ^^^ -error: use of a blacklisted/placeholder name `baz` +error: use of a blacklisted/placeholder name `quux` --> $DIR/blacklisted_name.rs:34:21 | -LL | if let Some(ref baz) = Some(42) {} - | ^^^ - -error: use of a blacklisted/placeholder name `bar` - --> $DIR/blacklisted_name.rs:38:17 - | -LL | let ref mut bar = 0; - | ^^^ +LL | if let Some(mut quux) = Some(42) {} + | ^^^^ error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:39:25 + --> $DIR/blacklisted_name.rs:38:13 | -LL | if let Some(ref mut baz) = Some(42) {} - | ^^^ +LL | let ref baz = 0; + | ^^^ + +error: use of a blacklisted/placeholder name `quux` + --> $DIR/blacklisted_name.rs:39:21 + | +LL | if let Some(ref quux) = Some(42) {} + | ^^^^ + +error: use of a blacklisted/placeholder name `baz` + --> $DIR/blacklisted_name.rs:43:17 + | +LL | let ref mut baz = 0; + | ^^^ + +error: use of a blacklisted/placeholder name `quux` + --> $DIR/blacklisted_name.rs:44:25 + | +LL | if let Some(ref mut quux) = Some(42) {} + | ^^^^ error: aborting due to 14 previous errors From 454ed47acf462c847956464ac3811546b733bd5b Mon Sep 17 00:00:00 2001 From: Iain Brandram-Adams <ijijnj@gmail.com> Date: Sun, 14 Jun 2020 12:46:56 +1200 Subject: [PATCH 210/526] Update comment in conf.rs --- clippy_lints/src/utils/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 418c4ded544..c41befbf147 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -106,7 +106,7 @@ macro_rules! define_Conf { pub use self::helpers::Conf; define_Conf! { - /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about + /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses (blacklisted_names, "blacklisted_names": Vec<String>, ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()), /// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have (cognitive_complexity_threshold, "cognitive_complexity_threshold": u64, 25), From 8a6f42a9707bbad1dad3f1511f793cd07c723bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Sun, 14 Jun 2020 11:07:44 +0200 Subject: [PATCH 211/526] Fix typo in wildcard_imports --- clippy_lints/src/wildcard_imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index b637253bd02..79f7705e281 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -36,7 +36,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** Checks for wildcard imports `use _::*`. /// - /// **Why is this bad?** wildcard imports can polute the namespace. This is especially bad if + /// **Why is this bad?** wildcard imports can pollute the namespace. This is especially bad if /// you try to import something through a wildcard, that already has been imported by name from /// a different source: /// From 8c1ee063bb67b20ac17603d0f0025b48b958cc08 Mon Sep 17 00:00:00 2001 From: Ericko Samudera <ericko.samudera@gmail.com> Date: Mon, 8 Jun 2020 00:44:14 +0700 Subject: [PATCH 212/526] mem_replace_with_uninit: suggest std::ptr::read --- clippy_lints/src/mem_replace.rs | 82 ++++++++++++++++++++++----------- tests/ui/repl_uninit.rs | 6 +++ tests/ui/repl_uninit.stderr | 19 ++++---- 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index ab6865bf0f3..e2672e02b36 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -135,33 +135,59 @@ fn check_replace_option_with_none(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest } } -fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, expr_span: Span) { - if let ExprKind::Call(ref repl_func, ref repl_args) = src.kind { - if_chain! { - if repl_args.is_empty(); - if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; - if let Some(repl_def_id) = cx.tables.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); - then { - if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) { - span_lint_and_help( - cx, - MEM_REPLACE_WITH_UNINIT, - expr_span, - "replacing with `mem::uninitialized()`", - None, - "consider using the `take_mut` crate instead", - ); - } else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) && - !cx.tables.expr_ty(src).is_primitive() { - span_lint_and_help( - cx, - MEM_REPLACE_WITH_UNINIT, - expr_span, - "replacing with `mem::zeroed()`", - None, - "consider using a default value or the `take_mut` crate instead", - ); - } +fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { + if_chain! { + // check if replacement is mem::MaybeUninit::uninit().assume_init() + if let Some(method_def_id) = cx.tables.type_dependent_def_id(src.hir_id); + if cx.tcx.is_diagnostic_item(sym::assume_init, method_def_id); + then { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + MEM_REPLACE_WITH_UNINIT, + expr_span, + "replacing with `mem::MaybeUninit::uninit().assume_init()`", + "consider using", + format!( + "std::ptr::read({})", + snippet_with_applicability(cx, dest.span, "", &mut applicability) + ), + applicability, + ); + return; + } + } + + if_chain! { + if let ExprKind::Call(ref repl_func, ref repl_args) = src.kind; + if repl_args.is_empty(); + if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; + if let Some(repl_def_id) = cx.tables.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); + then { + if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + MEM_REPLACE_WITH_UNINIT, + expr_span, + "replacing with `mem::uninitialized()`", + "consider using", + format!( + "std::ptr::read({})", + snippet_with_applicability(cx, dest.span, "", &mut applicability) + ), + applicability, + ); + } else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) && + !cx.tables.expr_ty(src).is_primitive() { + span_lint_and_help( + cx, + MEM_REPLACE_WITH_UNINIT, + expr_span, + "replacing with `mem::zeroed()`", + None, + "consider using a default value or the `take_mut` crate instead", + ); } } } @@ -209,7 +235,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace { if let [dest, src] = &**func_args; then { check_replace_option_with_none(cx, src, dest, expr.span); - check_replace_with_uninit(cx, src, expr.span); + check_replace_with_uninit(cx, src, dest, expr.span); check_replace_with_default(cx, src, dest, expr.span); } } diff --git a/tests/ui/repl_uninit.rs b/tests/ui/repl_uninit.rs index 346972b7bb4..ad5b8e4857d 100644 --- a/tests/ui/repl_uninit.rs +++ b/tests/ui/repl_uninit.rs @@ -17,6 +17,12 @@ fn main() { std::mem::forget(mem::replace(&mut v, new_v)); } + unsafe { + let taken_v = mem::replace(&mut v, mem::MaybeUninit::uninit().assume_init()); + let new_v = might_panic(taken_v); + std::mem::forget(mem::replace(&mut v, new_v)); + } + unsafe { let taken_v = mem::replace(&mut v, mem::zeroed()); let new_v = might_panic(taken_v); diff --git a/tests/ui/repl_uninit.stderr b/tests/ui/repl_uninit.stderr index c1f55d7601e..09468eeaea4 100644 --- a/tests/ui/repl_uninit.stderr +++ b/tests/ui/repl_uninit.stderr @@ -2,13 +2,18 @@ error: replacing with `mem::uninitialized()` --> $DIR/repl_uninit.rs:15:23 | LL | let taken_v = mem::replace(&mut v, mem::uninitialized()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::ptr::read(&mut v)` | = note: `-D clippy::mem-replace-with-uninit` implied by `-D warnings` - = help: consider using the `take_mut` crate instead + +error: replacing with `mem::MaybeUninit::uninit().assume_init()` + --> $DIR/repl_uninit.rs:21:23 + | +LL | let taken_v = mem::replace(&mut v, mem::MaybeUninit::uninit().assume_init()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::ptr::read(&mut v)` error: replacing with `mem::zeroed()` - --> $DIR/repl_uninit.rs:21:23 + --> $DIR/repl_uninit.rs:27:23 | LL | let taken_v = mem::replace(&mut v, mem::zeroed()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,12 +21,10 @@ LL | let taken_v = mem::replace(&mut v, mem::zeroed()); = help: consider using a default value or the `take_mut` crate instead error: replacing with `mem::uninitialized()` - --> $DIR/repl_uninit.rs:33:28 + --> $DIR/repl_uninit.rs:39:28 | LL | let taken_u = unsafe { mem::replace(uref, mem::uninitialized()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider using the `take_mut` crate instead + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::ptr::read(uref)` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors From f7acea2683c6124854bfe20e7127e4dfba344d3e Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Fri, 24 Apr 2020 00:14:03 +0200 Subject: [PATCH 213/526] Register redundant_field_names and non_expressive_names as early passes --- clippy_lints/src/lib.rs | 12 ++++++------ src/driver.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b8415fa3af1..9057de99029 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -341,13 +341,8 @@ mod reexport { /// level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass. /// /// Used in `./src/driver.rs`. -pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &Conf) { +pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) { store.register_pre_expansion_pass(|| box write::Write::default()); - store.register_pre_expansion_pass(|| box redundant_field_names::RedundantFieldNames); - let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; - store.register_pre_expansion_pass(move || box non_expressive_names::NonExpressiveNames { - single_char_binding_names_threshold, - }); store.register_pre_expansion_pass(|| box attrs::DeprecatedCfgAttribute); store.register_pre_expansion_pass(|| box dbg_macro::DbgMacro); } @@ -1051,6 +1046,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box unnamed_address::UnnamedAddress); store.register_late_pass(|| box dereference::Dereferencing); store.register_late_pass(|| box future_not_send::FutureNotSend); + store.register_early_pass(|| box redundant_field_names::RedundantFieldNames); + let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; + store.register_early_pass(move || box non_expressive_names::NonExpressiveNames { + single_char_binding_names_threshold, + }); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), diff --git a/src/driver.rs b/src/driver.rs index 2c699998ea9..928497ba5e4 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -79,7 +79,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { let conf = clippy_lints::read_conf(&[], &sess); clippy_lints::register_plugins(&mut lint_store, &sess, &conf); - clippy_lints::register_pre_expansion_lints(&mut lint_store, &conf); + clippy_lints::register_pre_expansion_lints(&mut lint_store); clippy_lints::register_renamed(&mut lint_store); })); From 485229c4a3d6a2fbe40f5a6976a33144a27497c6 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 12 May 2020 16:26:55 +0200 Subject: [PATCH 214/526] Fix fallout in redundant_field_names --- clippy_lints/src/redundant_field_names.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index b12c3c344ef..2a81170e49e 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -2,6 +2,7 @@ use crate::utils::span_lint_and_sugg; use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -36,6 +37,9 @@ declare_lint_pass!(RedundantFieldNames => [REDUNDANT_FIELD_NAMES]); impl EarlyLintPass for RedundantFieldNames { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if in_external_macro(cx.sess, expr.span) { + return; + } if let ExprKind::Struct(_, ref fields, _) = expr.kind { for field in fields { if field.is_shorthand { From efd3dcff97f67f376e354c047133ce9044c52991 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 12 May 2020 16:50:00 +0200 Subject: [PATCH 215/526] Fix fallout in similar_names --- clippy_lints/src/non_expressive_names.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 45809b35986..ef3b1da1b0b 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -5,6 +5,7 @@ use rustc_ast::ast::{ use rustc_ast::attr; use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor}; use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::SymbolStr; @@ -354,12 +355,20 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { impl EarlyLintPass for NonExpressiveNames { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if in_external_macro(cx.sess, item.span) { + return; + } + if let ItemKind::Fn(_, ref sig, _, Some(ref blk)) = item.kind { do_check(self, cx, &item.attrs, &sig.decl, blk); } } fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &AssocItem) { + if in_external_macro(cx.sess, item.span) { + return; + } + if let AssocItemKind::Fn(_, ref sig, _, Some(ref blk)) = item.kind { do_check(self, cx, &item.attrs, &sig.decl, blk); } From bb37a0f948b02e6434dbe3ea615960052d37f784 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Wed, 27 May 2020 00:06:50 +0200 Subject: [PATCH 216/526] Avoid triggering similar names on code from expansion --- clippy_lints/src/new_without_default.rs | 10 +++++----- clippy_lints/src/non_expressive_names.rs | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 19e06ab66c4..1ad631abe91 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -126,8 +126,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { return; } if sig.decl.inputs.is_empty() && name == sym!(new) && cx.access_levels.is_reachable(id) { - let self_did = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent_item(id)); - let self_ty = cx.tcx.type_of(self_did); + let self_def_id = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent_item(id)); + let self_ty = cx.tcx.type_of(self_def_id); if_chain! { if same_tys(cx, self_ty, return_ty(cx, id)); if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); @@ -148,10 +148,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { // generics if_chain! { if let Some(ref impling_types) = self.impling_types; - if let Some(self_def) = cx.tcx.type_of(self_did).ty_adt_def(); - if let Some(self_def_id) = self_def.did.as_local(); + if let Some(self_def) = cx.tcx.type_of(self_def_id).ty_adt_def(); + if let Some(self_local_did) = self_def.did.as_local(); then { - let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_def_id); + let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did); if impling_types.contains(&self_id) { return; } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index ef3b1da1b0b..5331bf26e05 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -132,7 +132,11 @@ struct SimilarNamesNameVisitor<'a, 'tcx, 'b>(&'b mut SimilarNamesLocalVisitor<'a impl<'a, 'tcx, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { fn visit_pat(&mut self, pat: &'tcx Pat) { match pat.kind { - PatKind::Ident(_, ident, _) => self.check_ident(ident), + PatKind::Ident(_, ident, _) => { + if !pat.span.from_expansion() { + self.check_ident(ident); + } + }, PatKind::Struct(_, ref fields, _) => { for field in fields { if !field.is_shorthand { From a7743e9084f9ccd7c966f98a14fa667c694d66ab Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Wed, 17 Jun 2020 00:32:47 +0200 Subject: [PATCH 217/526] redundant_pattern_matching: avoid non-const fn in const context --- .../src/redundant_pattern_matching.rs | 80 ++++++++++++++----- tests/ui/redundant_pattern_matching.fixed | 42 ++++++++++ tests/ui/redundant_pattern_matching.rs | 42 ++++++++++ tests/ui/redundant_pattern_matching.stderr | 56 ++++++------- ...undant_pattern_matching_const_result.fixed | 46 +++++++++++ ...redundant_pattern_matching_const_result.rs | 52 ++++++++++++ ...ndant_pattern_matching_const_result.stderr | 46 +++++++++++ 7 files changed, 318 insertions(+), 46 deletions(-) create mode 100644 tests/ui/redundant_pattern_matching_const_result.fixed create mode 100644 tests/ui/redundant_pattern_matching_const_result.rs create mode 100644 tests/ui/redundant_pattern_matching_const_result.stderr diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index 7ee298e9833..b95b12c4eb5 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -1,10 +1,13 @@ -use crate::utils::{match_qpath, match_trait_method, paths, snippet, span_lint_and_then}; +use crate::utils::{in_constant, match_qpath, match_trait_method, paths, snippet, span_lint_and_then}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::{Arm, Expr, ExprKind, MatchSource, PatKind, QPath}; +use rustc_hir::{Arm, Expr, ExprKind, HirId, MatchSource, PatKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_mir::const_eval::is_const_fn; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Symbol; declare_clippy_lint! { /// **What it does:** Lint for redundant pattern matching over `Result` or @@ -64,26 +67,37 @@ fn find_sugg_for_if_let<'a, 'tcx>( arms: &[Arm<'_>], keyword: &'static str, ) { + fn find_suggestion(cx: &LateContext<'_, '_>, hir_id: HirId, path: &QPath<'_>) -> Option<&'static str> { + if match_qpath(path, &paths::RESULT_OK) && can_suggest(cx, hir_id, sym!(result_type), "is_ok") { + return Some("is_ok()"); + } + if match_qpath(path, &paths::RESULT_ERR) && can_suggest(cx, hir_id, sym!(result_type), "is_err") { + return Some("is_err()"); + } + if match_qpath(path, &paths::OPTION_SOME) && can_suggest(cx, hir_id, sym!(option_type), "is_some") { + return Some("is_some()"); + } + if match_qpath(path, &paths::OPTION_NONE) && can_suggest(cx, hir_id, sym!(option_type), "is_none") { + return Some("is_none()"); + } + None + } + + let hir_id = expr.hir_id; let good_method = match arms[0].pat.kind { PatKind::TupleStruct(ref path, ref patterns, _) if patterns.len() == 1 => { if let PatKind::Wild = patterns[0].kind { - if match_qpath(path, &paths::RESULT_OK) { - "is_ok()" - } else if match_qpath(path, &paths::RESULT_ERR) { - "is_err()" - } else if match_qpath(path, &paths::OPTION_SOME) { - "is_some()" - } else { - return; - } + find_suggestion(cx, hir_id, path) } else { - return; + None } }, - - PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()", - - _ => return, + PatKind::Path(ref path) => find_suggestion(cx, hir_id, path), + _ => None, + }; + let good_method = match good_method { + Some(method) => method, + None => return, }; // check that `while_let_on_iterator` lint does not trigger @@ -128,6 +142,7 @@ fn find_sugg_for_match<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_ if arms.len() == 2 { let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind); + let hir_id = expr.hir_id; let found_good_method = match node_pair { ( PatKind::TupleStruct(ref path_left, ref patterns_left, _), @@ -142,6 +157,8 @@ fn find_sugg_for_match<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_ &paths::RESULT_ERR, "is_ok()", "is_err()", + || can_suggest(cx, hir_id, sym!(result_type), "is_ok"), + || can_suggest(cx, hir_id, sym!(result_type), "is_err"), ) } else { None @@ -160,6 +177,8 @@ fn find_sugg_for_match<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_ &paths::OPTION_NONE, "is_some()", "is_none()", + || can_suggest(cx, hir_id, sym!(option_type), "is_some"), + || can_suggest(cx, hir_id, sym!(option_type), "is_none"), ) } else { None @@ -188,6 +207,7 @@ fn find_sugg_for_match<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_ } } +#[allow(clippy::too_many_arguments)] fn find_good_method_for_match<'a>( arms: &[Arm<'_>], path_left: &QPath<'_>, @@ -196,6 +216,8 @@ fn find_good_method_for_match<'a>( expected_right: &[&str], should_be_left: &'a str, should_be_right: &'a str, + can_suggest_left: impl Fn() -> bool, + can_suggest_right: impl Fn() -> bool, ) -> Option<&'a str> { let body_node_pair = if match_qpath(path_left, expected_left) && match_qpath(path_right, expected_right) { (&(*arms[0].body).kind, &(*arms[1].body).kind) @@ -207,10 +229,32 @@ fn find_good_method_for_match<'a>( match body_node_pair { (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => match (&lit_left.node, &lit_right.node) { - (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left), - (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right), + (LitKind::Bool(true), LitKind::Bool(false)) if can_suggest_left() => Some(should_be_left), + (LitKind::Bool(false), LitKind::Bool(true)) if can_suggest_right() => Some(should_be_right), _ => None, }, _ => None, } } + +fn can_suggest(cx: &LateContext<'_, '_>, hir_id: HirId, diag_item: Symbol, name: &str) -> bool { + if !in_constant(cx, hir_id) { + return true; + } + + // Avoid suggesting calls to non-`const fn`s in const contexts, see #5697. + cx.tcx + .get_diagnostic_item(diag_item) + .and_then(|def_id| { + cx.tcx.inherent_impls(def_id).iter().find_map(|imp| { + cx.tcx + .associated_items(*imp) + .in_definition_order() + .find_map(|item| match item.kind { + ty::AssocKind::Fn if item.ident.name.as_str() == name => Some(item.def_id), + _ => None, + }) + }) + }) + .map_or(false, |def_id| is_const_fn(cx.tcx, def_id)) +} diff --git a/tests/ui/redundant_pattern_matching.fixed b/tests/ui/redundant_pattern_matching.fixed index fc8cb0e747c..6ba5cfb1d71 100644 --- a/tests/ui/redundant_pattern_matching.fixed +++ b/tests/ui/redundant_pattern_matching.fixed @@ -1,5 +1,7 @@ // run-rustfix +#![feature(const_if_match)] +#![feature(const_loop)] #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] #![allow(clippy::unit_arg, unused_must_use, clippy::needless_bool, deprecated)] @@ -67,6 +69,7 @@ fn main() { takes_bool(x); issue5504(); + issue5697(); let _ = if gen_opt().is_some() { 1 @@ -117,3 +120,42 @@ fn issue5504() { if m!().is_some() {} while m!().is_some() {} } + +// None of these should be linted because none of the suggested methods +// are `const fn` without toggling a feature. +const fn issue5697() { + if let Ok(_) = Ok::<i32, i32>(42) {} + + if let Err(_) = Err::<i32, i32>(42) {} + + if let Some(_) = Some(42) {} + + if let None = None::<()> {} + + while let Ok(_) = Ok::<i32, i32>(10) {} + + while let Err(_) = Ok::<i32, i32>(10) {} + + while let Some(_) = Some(42) {} + + while let None = None::<()> {} + + match Ok::<i32, i32>(42) { + Ok(_) => true, + Err(_) => false, + }; + + match Err::<i32, i32>(42) { + Ok(_) => false, + Err(_) => true, + }; + match Some(42) { + Some(_) => true, + None => false, + }; + + match None::<()> { + Some(_) => false, + None => true, + }; +} diff --git a/tests/ui/redundant_pattern_matching.rs b/tests/ui/redundant_pattern_matching.rs index 51912dade03..17de66f9ad0 100644 --- a/tests/ui/redundant_pattern_matching.rs +++ b/tests/ui/redundant_pattern_matching.rs @@ -1,5 +1,7 @@ // run-rustfix +#![feature(const_if_match)] +#![feature(const_loop)] #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] #![allow(clippy::unit_arg, unused_must_use, clippy::needless_bool, deprecated)] @@ -88,6 +90,7 @@ fn main() { takes_bool(x); issue5504(); + issue5697(); let _ = if let Some(_) = gen_opt() { 1 @@ -138,3 +141,42 @@ fn issue5504() { if let Some(_) = m!() {} while let Some(_) = m!() {} } + +// None of these should be linted because none of the suggested methods +// are `const fn` without toggling a feature. +const fn issue5697() { + if let Ok(_) = Ok::<i32, i32>(42) {} + + if let Err(_) = Err::<i32, i32>(42) {} + + if let Some(_) = Some(42) {} + + if let None = None::<()> {} + + while let Ok(_) = Ok::<i32, i32>(10) {} + + while let Err(_) = Ok::<i32, i32>(10) {} + + while let Some(_) = Some(42) {} + + while let None = None::<()> {} + + match Ok::<i32, i32>(42) { + Ok(_) => true, + Err(_) => false, + }; + + match Err::<i32, i32>(42) { + Ok(_) => false, + Err(_) => true, + }; + match Some(42) { + Some(_) => true, + None => false, + }; + + match None::<()> { + Some(_) => false, + None => true, + }; +} diff --git a/tests/ui/redundant_pattern_matching.stderr b/tests/ui/redundant_pattern_matching.stderr index b58deb7954e..1b9a4b40a2f 100644 --- a/tests/ui/redundant_pattern_matching.stderr +++ b/tests/ui/redundant_pattern_matching.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:8:12 + --> $DIR/redundant_pattern_matching.rs:10:12 | LL | if let Ok(_) = Ok::<i32, i32>(42) {} | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()` @@ -7,67 +7,67 @@ LL | if let Ok(_) = Ok::<i32, i32>(42) {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:10:12 + --> $DIR/redundant_pattern_matching.rs:12:12 | LL | if let Err(_) = Err::<i32, i32>(42) {} | -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:12:12 + --> $DIR/redundant_pattern_matching.rs:14:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:14:12 + --> $DIR/redundant_pattern_matching.rs:16:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:16:12 + --> $DIR/redundant_pattern_matching.rs:18:12 | LL | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:22:15 + --> $DIR/redundant_pattern_matching.rs:24:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:24:15 + --> $DIR/redundant_pattern_matching.rs:26:15 | LL | while let None = Some(42) {} | ----------^^^^----------- help: try this: `while Some(42).is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:26:15 + --> $DIR/redundant_pattern_matching.rs:28:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try this: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:28:15 + --> $DIR/redundant_pattern_matching.rs:30:15 | LL | while let Ok(_) = Ok::<i32, i32>(10) {} | ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:30:15 + --> $DIR/redundant_pattern_matching.rs:32:15 | LL | while let Err(_) = Ok::<i32, i32>(10) {} | ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:33:15 + --> $DIR/redundant_pattern_matching.rs:35:15 | LL | while let Some(_) = v.pop() { | ----------^^^^^^^---------- help: try this: `while v.pop().is_some()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:49:5 + --> $DIR/redundant_pattern_matching.rs:51:5 | LL | / match Ok::<i32, i32>(42) { LL | | Ok(_) => true, @@ -76,7 +76,7 @@ LL | | }; | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:54:5 + --> $DIR/redundant_pattern_matching.rs:56:5 | LL | / match Ok::<i32, i32>(42) { LL | | Ok(_) => false, @@ -85,7 +85,7 @@ LL | | }; | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:59:5 + --> $DIR/redundant_pattern_matching.rs:61:5 | LL | / match Err::<i32, i32>(42) { LL | | Ok(_) => false, @@ -94,7 +94,7 @@ LL | | }; | |_____^ help: try this: `Err::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:64:5 + --> $DIR/redundant_pattern_matching.rs:66:5 | LL | / match Err::<i32, i32>(42) { LL | | Ok(_) => true, @@ -103,7 +103,7 @@ LL | | }; | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:69:5 + --> $DIR/redundant_pattern_matching.rs:71:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -112,7 +112,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:74:5 + --> $DIR/redundant_pattern_matching.rs:76:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -121,7 +121,7 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:79:13 + --> $DIR/redundant_pattern_matching.rs:81:13 | LL | let _ = match None::<()> { | _____________^ @@ -131,61 +131,61 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:84:20 + --> $DIR/redundant_pattern_matching.rs:86:20 | LL | let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false }; | -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:87:20 + --> $DIR/redundant_pattern_matching.rs:89:20 | LL | let x = if let Some(_) = opt { true } else { false }; | -------^^^^^^^------ help: try this: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:92:20 + --> $DIR/redundant_pattern_matching.rs:95:20 | LL | let _ = if let Some(_) = gen_opt() { | -------^^^^^^^------------ help: try this: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:94:19 + --> $DIR/redundant_pattern_matching.rs:97:19 | LL | } else if let None = gen_opt() { | -------^^^^------------ help: try this: `if gen_opt().is_none()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:96:19 + --> $DIR/redundant_pattern_matching.rs:99:19 | LL | } else if let Ok(_) = gen_res() { | -------^^^^^------------ help: try this: `if gen_res().is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:98:19 + --> $DIR/redundant_pattern_matching.rs:101:19 | LL | } else if let Err(_) = gen_res() { | -------^^^^^^------------ help: try this: `if gen_res().is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:131:19 + --> $DIR/redundant_pattern_matching.rs:134:19 | LL | while let Some(_) = r#try!(result_opt()) {} | ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:132:16 + --> $DIR/redundant_pattern_matching.rs:135:16 | LL | if let Some(_) = r#try!(result_opt()) {} | -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:138:12 + --> $DIR/redundant_pattern_matching.rs:141:12 | LL | if let Some(_) = m!() {} | -------^^^^^^^------- help: try this: `if m!().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:139:15 + --> $DIR/redundant_pattern_matching.rs:142:15 | LL | while let Some(_) = m!() {} | ----------^^^^^^^------- help: try this: `while m!().is_some()` diff --git a/tests/ui/redundant_pattern_matching_const_result.fixed b/tests/ui/redundant_pattern_matching_const_result.fixed new file mode 100644 index 00000000000..c8bc5458067 --- /dev/null +++ b/tests/ui/redundant_pattern_matching_const_result.fixed @@ -0,0 +1,46 @@ +// run-rustfix + +#![feature(const_if_match)] +#![feature(const_loop)] +#![feature(const_result)] +#![warn(clippy::redundant_pattern_matching)] +#![allow(unused)] + +// Test that results are linted with the feature enabled. + +const fn issue_5697() { + if Ok::<i32, i32>(42).is_ok() {} + + if Err::<i32, i32>(42).is_err() {} + + while Ok::<i32, i32>(10).is_ok() {} + + while Ok::<i32, i32>(10).is_err() {} + + Ok::<i32, i32>(42).is_ok(); + + Err::<i32, i32>(42).is_err(); + + // These should not be linted until `const_option` is implemented. + // See https://github.com/rust-lang/rust/issues/67441 + + if let Some(_) = Some(42) {} + + if let None = None::<()> {} + + while let Some(_) = Some(42) {} + + while let None = None::<()> {} + + match Some(42) { + Some(_) => true, + None => false, + }; + + match None::<()> { + Some(_) => false, + None => true, + }; +} + +fn main() {} diff --git a/tests/ui/redundant_pattern_matching_const_result.rs b/tests/ui/redundant_pattern_matching_const_result.rs new file mode 100644 index 00000000000..75f37ec15c6 --- /dev/null +++ b/tests/ui/redundant_pattern_matching_const_result.rs @@ -0,0 +1,52 @@ +// run-rustfix + +#![feature(const_if_match)] +#![feature(const_loop)] +#![feature(const_result)] +#![warn(clippy::redundant_pattern_matching)] +#![allow(unused)] + +// Test that results are linted with the feature enabled. + +const fn issue_5697() { + if let Ok(_) = Ok::<i32, i32>(42) {} + + if let Err(_) = Err::<i32, i32>(42) {} + + while let Ok(_) = Ok::<i32, i32>(10) {} + + while let Err(_) = Ok::<i32, i32>(10) {} + + match Ok::<i32, i32>(42) { + Ok(_) => true, + Err(_) => false, + }; + + match Err::<i32, i32>(42) { + Ok(_) => false, + Err(_) => true, + }; + + // These should not be linted until `const_option` is implemented. + // See https://github.com/rust-lang/rust/issues/67441 + + if let Some(_) = Some(42) {} + + if let None = None::<()> {} + + while let Some(_) = Some(42) {} + + while let None = None::<()> {} + + match Some(42) { + Some(_) => true, + None => false, + }; + + match None::<()> { + Some(_) => false, + None => true, + }; +} + +fn main() {} diff --git a/tests/ui/redundant_pattern_matching_const_result.stderr b/tests/ui/redundant_pattern_matching_const_result.stderr new file mode 100644 index 00000000000..c32292f0eee --- /dev/null +++ b/tests/ui/redundant_pattern_matching_const_result.stderr @@ -0,0 +1,46 @@ +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_const_result.rs:12:12 + | +LL | if let Ok(_) = Ok::<i32, i32>(42) {} + | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()` + | + = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_const_result.rs:14:12 + | +LL | if let Err(_) = Err::<i32, i32>(42) {} + | -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_const_result.rs:16:15 + | +LL | while let Ok(_) = Ok::<i32, i32>(10) {} + | ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_const_result.rs:18:15 + | +LL | while let Err(_) = Ok::<i32, i32>(10) {} + | ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_const_result.rs:20:5 + | +LL | / match Ok::<i32, i32>(42) { +LL | | Ok(_) => true, +LL | | Err(_) => false, +LL | | }; + | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_const_result.rs:25:5 + | +LL | / match Err::<i32, i32>(42) { +LL | | Ok(_) => false, +LL | | Err(_) => true, +LL | | }; + | |_____^ help: try this: `Err::<i32, i32>(42).is_err()` + +error: aborting due to 6 previous errors + From f3a40f5eb1cedebd374ebcd52341dfec60f3ea10 Mon Sep 17 00:00:00 2001 From: sozysozbot <sozysozbot@gmail.com> Date: Thu, 18 Jun 2020 06:50:04 +0900 Subject: [PATCH 218/526] Fix typo extending it's lifetime -> extending its lifetime --- clippy_lints/src/let_underscore.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs index 710dec8d33f..acd628bbaca 100644 --- a/clippy_lints/src/let_underscore.rs +++ b/clippy_lints/src/let_underscore.rs @@ -35,7 +35,7 @@ declare_clippy_lint! { /// **What it does:** Checks for `let _ = sync_lock` /// /// **Why is this bad?** This statement immediately drops the lock instead of - /// extending it's lifetime to the end of the scope, which is often not intended. + /// extending its lifetime to the end of the scope, which is often not intended. /// To extend lock lifetime to the end of the scope, use an underscore-prefixed /// name instead (i.e. _lock). If you want to explicitly drop the lock, /// `std::mem::drop` conveys your intention better and is less error-prone. From 51592f8587bd5dac9cb3f34fbd5896218a814677 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 23 Jun 2020 02:18:38 +0200 Subject: [PATCH 219/526] Fix sync fallout --- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/len_zero.rs | 3 +- clippy_lints/src/loops.rs | 6 +-- clippy_lints/src/types.rs | 58 +++++-------------------- clippy_lints/src/unnecessary_sort_by.rs | 5 ++- clippy_lints/src/utils/author.rs | 5 ++- clippy_lints/src/utils/usage.rs | 2 +- 7 files changed, 27 insertions(+), 54 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 59af475af17..77e90eeac49 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_target::abi::LayoutOf; -use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceWithHirId, PlaceBase}; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use crate::utils::span_lint; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 13e85fda8ff..7838e8e8ab7 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -211,7 +211,8 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item<'_>, impl_items: &[Imp } fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) { - if let (&ExprKind::MethodCall(ref method_path, _, ref args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) { + if let (&ExprKind::MethodCall(ref method_path, _, ref args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) + { // check if we are in an is_empty() method if let Some(name) = get_item_name(cx, method) { if name.as_str() == "is_empty" { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 83093ec51bd..ae1aa66be5c 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -28,7 +28,7 @@ use rustc_middle::ty::{self, Ty, TyS}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; -use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceWithHirId, PlaceBase}; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use std::iter::{once, Iterator}; use std::mem; @@ -1580,13 +1580,13 @@ fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr<'_>) -> Option<Hi None } -fn check_for_mutation<'a, 'tcx> ( +fn check_for_mutation<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, body: &Expr<'_>, bound_ids: &[Option<HirId>], ) -> (Option<Span>, Option<Span>) { let mut delegate = MutatePairDelegate { - cx: cx, + cx, hir_id_low: bound_ids[0], hir_id_high: bound_ids[1], span_low: None, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index d59a2f1bae0..98de08f79f3 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1945,16 +1945,12 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_ let which = match (&ty.kind, cv) { (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => Minimum, - (&ty::Int(ity), Constant::Int(i)) - if i == unsext(cx.tcx, i128::MIN >> (128 - int_bits(cx.tcx, ity)), ity) => - { + (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MIN >> (128 - int_bits(cx.tcx, ity)), ity) => { Minimum }, (&ty::Bool, Constant::Bool(true)) => Maximum, - (&ty::Int(ity), Constant::Int(i)) - if i == unsext(cx.tcx, i128::MAX >> (128 - int_bits(cx.tcx, ity)), ity) => - { + (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MAX >> (128 - int_bits(cx.tcx, ity)), ity) => { Maximum }, (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::MAX, uty) == i => Maximum, @@ -2083,50 +2079,20 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'_>) } match pre_cast_ty.kind { ty::Int(int_ty) => Some(match int_ty { - IntTy::I8 => ( - FullInt::S(i128::from(i8::MIN)), - FullInt::S(i128::from(i8::MAX)), - ), - IntTy::I16 => ( - FullInt::S(i128::from(i16::MIN)), - FullInt::S(i128::from(i16::MAX)), - ), - IntTy::I32 => ( - FullInt::S(i128::from(i32::MIN)), - FullInt::S(i128::from(i32::MAX)), - ), - IntTy::I64 => ( - FullInt::S(i128::from(i64::MIN)), - FullInt::S(i128::from(i64::MAX)), - ), + IntTy::I8 => (FullInt::S(i128::from(i8::MIN)), FullInt::S(i128::from(i8::MAX))), + IntTy::I16 => (FullInt::S(i128::from(i16::MIN)), FullInt::S(i128::from(i16::MAX))), + IntTy::I32 => (FullInt::S(i128::from(i32::MIN)), FullInt::S(i128::from(i32::MAX))), + IntTy::I64 => (FullInt::S(i128::from(i64::MIN)), FullInt::S(i128::from(i64::MAX))), IntTy::I128 => (FullInt::S(i128::MIN), FullInt::S(i128::MAX)), - IntTy::Isize => ( - FullInt::S(isize::MIN as i128), - FullInt::S(isize::MAX as i128), - ), + IntTy::Isize => (FullInt::S(isize::MIN as i128), FullInt::S(isize::MAX as i128)), }), ty::Uint(uint_ty) => Some(match uint_ty { - UintTy::U8 => ( - FullInt::U(u128::from(u8::MIN)), - FullInt::U(u128::from(u8::MAX)), - ), - UintTy::U16 => ( - FullInt::U(u128::from(u16::MIN)), - FullInt::U(u128::from(u16::MAX)), - ), - UintTy::U32 => ( - FullInt::U(u128::from(u32::MIN)), - FullInt::U(u128::from(u32::MAX)), - ), - UintTy::U64 => ( - FullInt::U(u128::from(u64::MIN)), - FullInt::U(u128::from(u64::MAX)), - ), + UintTy::U8 => (FullInt::U(u128::from(u8::MIN)), FullInt::U(u128::from(u8::MAX))), + UintTy::U16 => (FullInt::U(u128::from(u16::MIN)), FullInt::U(u128::from(u16::MAX))), + UintTy::U32 => (FullInt::U(u128::from(u32::MIN)), FullInt::U(u128::from(u32::MAX))), + UintTy::U64 => (FullInt::U(u128::from(u64::MIN)), FullInt::U(u128::from(u64::MAX))), UintTy::U128 => (FullInt::U(u128::MIN), FullInt::U(u128::MAX)), - UintTy::Usize => ( - FullInt::U(usize::MIN as u128), - FullInt::U(usize::MAX as u128), - ), + UintTy::Usize => (FullInt::U(usize::MIN as u128), FullInt::U(usize::MAX as u128)), }), _ => None, } diff --git a/clippy_lints/src/unnecessary_sort_by.rs b/clippy_lints/src/unnecessary_sort_by.rs index e94eebb88e4..6ac6a12529c 100644 --- a/clippy_lints/src/unnecessary_sort_by.rs +++ b/clippy_lints/src/unnecessary_sort_by.rs @@ -95,7 +95,10 @@ fn mirrored_exprs( // The two exprs are method calls. // Check to see that the function is the same and the arguments are mirrored // This is enough because the receiver of the method is listed in the arguments - (ExprKind::MethodCall(left_segment, _, left_args, _), ExprKind::MethodCall(right_segment, _, right_args, _)) => { + ( + ExprKind::MethodCall(left_segment, _, left_args, _), + ExprKind::MethodCall(right_segment, _, right_args, _), + ) => { left_segment.ident == right_segment.ident && left_args .iter() diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 8b58bbb5e65..910b665ccb7 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -251,7 +251,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } }, ExprKind::MethodCall(ref _method_name, ref _generics, ref _args, ref _fn_span) => { - println!("MethodCall(ref method_name, ref generics, ref args, ref fn_span) = {};", current); + println!( + "MethodCall(ref method_name, ref generics, ref args, ref fn_span) = {};", + current + ); println!(" // unimplemented: `ExprKind::MethodCall` is not further destructured at the moment"); }, ExprKind::Tup(ref elements) => { diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 6a7a1f1ceaa..0492878fc27 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -8,7 +8,7 @@ use rustc_lint::LateContext; use rustc_middle::hir::map::Map; use rustc_middle::ty; use rustc_span::symbol::{Ident, Symbol}; -use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceWithHirId, PlaceBase}; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined. pub fn mutated_variables<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &'a LateContext<'a, 'tcx>) -> Option<FxHashSet<HirId>> { From 52c486475774b7416e691323322ef1ea2db790de Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Thu, 11 Jun 2020 20:25:14 +0200 Subject: [PATCH 220/526] Improve end of expression check in for loop lints The code should to check that the current expression _is_ the end expression; not that it's equal to it. The equality check seems very wasteful in terms of performance. --- clippy_lints/src/loops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index ae1aa66be5c..3874b040b13 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2042,7 +2042,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { if self.state == VarState::DontWarn { return; } - if SpanlessEq::new(self.cx).eq_expr(&expr, self.end_expr) { + if expr.hir_id == self.end_expr.hir_id { self.past_loop = true; return; } From 51c3b42ef33f14cb40aa440d2d432e4c70e028b0 Mon Sep 17 00:00:00 2001 From: Lzu Tao <taolzu@gmail.com> Date: Tue, 23 Jun 2020 14:27:11 +0700 Subject: [PATCH 221/526] Add more specific GitHub issue templates Apply suggestions from code review Co-authored-by: Philipp Krones <hello@philkrones.com> --- .github/ISSUE_TEMPLATE.md | 8 ---- .github/ISSUE_TEMPLATE/blank_issue.md | 4 ++ .github/ISSUE_TEMPLATE/bug_report.md | 47 ++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 5 +++ .github/ISSUE_TEMPLATE/ice.md | 53 +++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/new_lint.md | 35 ++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 1 + 7 files changed, 145 insertions(+), 8 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/ISSUE_TEMPLATE/blank_issue.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/ice.md create mode 100644 .github/ISSUE_TEMPLATE/new_lint.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 15006a07b44..00000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,8 +0,0 @@ -<!-- -Hi there! Whether you've come to make a suggestion for a new lint, an improvement to an existing lint or to report a bug or a false positive in Clippy, you've come to the right place. - -For bug reports and false positives, please include the output of `cargo clippy -V` in the report. - -Thank you for using Clippy! - -Write your comment below this line: --> diff --git a/.github/ISSUE_TEMPLATE/blank_issue.md b/.github/ISSUE_TEMPLATE/blank_issue.md new file mode 100644 index 00000000000..9aef3ebe637 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/blank_issue.md @@ -0,0 +1,4 @@ +--- +name: Blank Issue +about: Create a blank issue. +--- diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000..d8f0c44148c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,47 @@ +--- +name: Bug Report +about: Create a bug report for Clippy +labels: L-bug +--- +<!-- +Thank you for filing a bug report! 🐛 Please provide a short summary of the bug, +along with any information you feel relevant to replicating the bug. +--> + +I tried this code: + +```rust +<code> +``` + +I expected to see this happen: *explanation* + +Instead, this happened: *explanation* + +### Meta + +- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20) +- `rustc -Vv`: + ``` + rustc 1.46.0-nightly (f455e46ea 2020-06-20) + binary: rustc + commit-hash: f455e46eae1a227d735091091144601b467e1565 + commit-date: 2020-06-20 + host: x86_64-unknown-linux-gnu + release: 1.46.0-nightly + LLVM version: 10.0 + ``` + +<!-- +Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your +environment. E.g. `RUST_BACKTRACE=1 cargo clippy`. +--> +<details><summary>Backtrace</summary> + <p> + + ``` + <backtrace> + ``` + + </p> +</details> diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000000..bd7dc0ac95c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: Rust Programming Language Forum + url: https://users.rust-lang.org + about: Please ask and answer questions about Rust here. diff --git a/.github/ISSUE_TEMPLATE/ice.md b/.github/ISSUE_TEMPLATE/ice.md new file mode 100644 index 00000000000..3abe76bf2c4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/ice.md @@ -0,0 +1,53 @@ +--- +name: Internal Compiler Error +about: Create a report for an internal compiler error in Clippy. +labels: L-bug, L-crash +--- +<!-- +Thank you for finding an Internal Compiler Error! 🧊 If possible, try to provide +a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for +how to create smaller examples. + +http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/ + +--> + +### Code + +```rust +<code> +``` + +### Meta + +- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20) +- `rustc -Vv`: + ``` + rustc 1.46.0-nightly (f455e46ea 2020-06-20) + binary: rustc + commit-hash: f455e46eae1a227d735091091144601b467e1565 + commit-date: 2020-06-20 + host: x86_64-unknown-linux-gnu + release: 1.46.0-nightly + LLVM version: 10.0 + ``` + +### Error output + +``` +<output> +``` + +<!-- +Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your +environment. E.g. `RUST_BACKTRACE=1 cargo clippy`. +--> +<details><summary>Backtrace</summary> + <p> + + ``` + <backtrace> + ``` + + </p> +</details> diff --git a/.github/ISSUE_TEMPLATE/new_lint.md b/.github/ISSUE_TEMPLATE/new_lint.md new file mode 100644 index 00000000000..70445d7ef25 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new_lint.md @@ -0,0 +1,35 @@ +--- +name: New lint suggestion +about: Suggest a new Clippy lint. +labels: L-lint +--- + +### What it does + +*What does this lint do?* + +### Categories (optional) + +- Kind: *See <https://github.com/rust-lang/rust-clippy/blob/master/README.md#clippy> for list of lint kinds* + +*What benefit of this lint over old code?* + +For example: +- Remove bounce checking inserted by ... +- Remove the need to duplicating/storing/typo ... + +### Drawbacks + +None. + +### Example + +```rust +<code> +``` + +Could be written as: + +```rust +<code> +``` diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 97aa220afea..137a7363094 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -28,4 +28,5 @@ Delete this line and everything above before opening your PR. --- +*Please keep the line below* changelog: none From ed083cc95987ef37b7ed897f632b4a7a1baaff60 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sat, 13 Jun 2020 18:22:38 +0200 Subject: [PATCH 222/526] Use lints in Clippy that are enabled in rustc bootstrap --- clippy_lints/src/lib.rs | 17 ++++++++++------- src/driver.rs | 6 +++++- src/main.rs | 2 ++ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 021fbe932d8..25c1c2d73b6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,19 +1,22 @@ // error-pattern:cargo-clippy #![feature(bindings_after_at)] -#![feature(box_syntax)] #![feature(box_patterns)] +#![feature(box_syntax)] +#![feature(concat_idents)] +#![feature(crate_visibility_modifier)] +#![feature(drain_filter)] #![feature(or_patterns)] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] -#![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)] #![recursion_limit = "512"] -#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] -#![deny(rustc::internal)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] -#![feature(crate_visibility_modifier)] -#![feature(concat_idents)] -#![feature(drain_filter)] +#![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)] +#![warn(trivial_casts, trivial_numeric_casts)] +// warn on lints, that are included in `rust-lang/rust`s bootstrap +#![warn(rust_2018_idioms, unused_lifetimes)] +// warn on rustc internal lints +#![deny(rustc::internal)] // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) diff --git a/src/driver.rs b/src/driver.rs index 4453ae5ce44..10f56fb2070 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -1,5 +1,9 @@ -#![cfg_attr(feature = "deny-warnings", deny(warnings))] #![feature(rustc_private)] +#![cfg_attr(feature = "deny-warnings", deny(warnings))] +// warn on lints, that are included in `rust-lang/rust`s bootstrap +#![warn(rust_2018_idioms, unused_lifetimes)] +// warn on rustc internal lints +#![deny(rustc::internal)] // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) diff --git a/src/main.rs b/src/main.rs index bc43a34ed5d..6739a4cf224 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,6 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] +// warn on lints, that are included in `rust-lang/rust`s bootstrap +#![warn(rust_2018_idioms, unused_lifetimes)] use rustc_tools_util::VersionInfo; use std::env; From b886c06c1a52a57890b318cc7304f7384e696ec8 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sat, 13 Jun 2020 18:22:49 +0200 Subject: [PATCH 223/526] Fix fallout --- clippy_lints/src/loops.rs | 6 +++--- clippy_lints/src/suspicious_trait_impl.rs | 2 +- clippy_lints/src/trivially_copy_pass_by_ref.rs | 2 +- clippy_lints/src/utils/sugg.rs | 4 ++-- src/driver.rs | 6 ++++-- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index ae1aa66be5c..9020b47a146 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1497,7 +1497,7 @@ struct MutatePairDelegate<'a, 'tcx> { span_high: Option<Span>, } -impl<'a, 'tcx> Delegate<'tcx> for MutatePairDelegate<'a, 'tcx> { +impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: ConsumeMode) {} fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { @@ -1525,7 +1525,7 @@ impl<'a, 'tcx> Delegate<'tcx> for MutatePairDelegate<'a, 'tcx> { } } -impl<'a, 'tcx> MutatePairDelegate<'a, 'tcx> { +impl MutatePairDelegate<'_, '_> { fn mutation_span(&self) -> (Option<Span>, Option<Span>) { (self.span_low, self.span_high) } @@ -2292,7 +2292,7 @@ struct HasBreakOrReturnVisitor { has_break_or_return: bool, } -impl<'a, 'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor { +impl<'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor { type Map = Map<'tcx>; fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index a9e6fa329c0..cf71c3144a2 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -184,7 +184,7 @@ struct BinaryExprVisitor { in_binary_expr: bool, } -impl<'a, 'tcx> Visitor<'tcx> for BinaryExprVisitor { +impl<'tcx> Visitor<'tcx> for BinaryExprVisitor { type Map = Map<'tcx>; fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 8e0cb94317a..146ac4b09d5 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -58,7 +58,7 @@ pub struct TriviallyCopyPassByRef { limit: u64, } -impl<'a, 'tcx> TriviallyCopyPassByRef { +impl<'tcx> TriviallyCopyPassByRef { pub fn new(limit: Option<u64>, target: &SessionConfig) -> Self { let limit = limit.unwrap_or_else(|| { let bit_width = u64::from(target.ptr_width); diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 73758b7eeb7..e919b1522d8 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -509,7 +509,7 @@ fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> { } /// Convenience extension trait for `DiagnosticBuilder`. -pub trait DiagnosticBuilderExt<'a, T: LintContext> { +pub trait DiagnosticBuilderExt<T: LintContext> { /// Suggests to add an attribute to an item. /// /// Correctly handles indentation of the attribute and item. @@ -556,7 +556,7 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext> { fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability); } -impl<'a, 'b, 'c, T: LintContext> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> { +impl<T: LintContext> DiagnosticBuilderExt<T> for rustc_errors::DiagnosticBuilder<'_> { fn suggest_item_with_attr<D: Display + ?Sized>( &mut self, cx: &T, diff --git a/src/driver.rs b/src/driver.rs index 10f56fb2070..3d12436e9af 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -8,6 +8,8 @@ // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) #[allow(unused_extern_crates)] +extern crate rustc_data_structures; +#[allow(unused_extern_crates)] extern crate rustc_driver; #[allow(unused_extern_crates)] extern crate rustc_errors; @@ -97,7 +99,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { #[allow(clippy::find_map, clippy::filter_map)] fn describe_lints() { use lintlist::{Level, Lint, ALL_LINTS, LINT_LEVELS}; - use std::collections::HashSet; + use rustc_data_structures::fx::FxHashSet; println!( " @@ -141,7 +143,7 @@ Available lint options: let scoped = |x: &str| format!("clippy::{}", x); - let lint_groups: HashSet<_> = lints.iter().map(|lint| lint.group).collect(); + let lint_groups: FxHashSet<_> = lints.iter().map(|lint| lint.group).collect(); println!("Lint checks provided by clippy:\n"); println!(" {} {:7.7} meaning", padded("name"), "default"); From 7374185b36d8dee6c91970a4c016d714a6e1bd39 Mon Sep 17 00:00:00 2001 From: Lzu Tao <taolzu@gmail.com> Date: Tue, 23 Jun 2020 20:59:35 +0700 Subject: [PATCH 224/526] Remove unused allowed unused attributes --- clippy_lints/src/lib.rs | 32 +++----------------------------- src/driver.rs | 5 ----- 2 files changed, 3 insertions(+), 34 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 19ad7d92c2b..501220f28e5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -20,47 +20,25 @@ // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) -#[allow(unused_extern_crates)] extern crate rustc_ast; -#[allow(unused_extern_crates)] extern crate rustc_ast_pretty; -#[allow(unused_extern_crates)] extern crate rustc_attr; -#[allow(unused_extern_crates)] extern crate rustc_data_structures; -#[allow(unused_extern_crates)] -extern crate rustc_driver; -#[allow(unused_extern_crates)] extern crate rustc_errors; -#[allow(unused_extern_crates)] extern crate rustc_hir; -#[allow(unused_extern_crates)] extern crate rustc_hir_pretty; -#[allow(unused_extern_crates)] extern crate rustc_index; -#[allow(unused_extern_crates)] extern crate rustc_infer; -#[allow(unused_extern_crates)] extern crate rustc_lexer; -#[allow(unused_extern_crates)] extern crate rustc_lint; -#[allow(unused_extern_crates)] extern crate rustc_middle; -#[allow(unused_extern_crates)] extern crate rustc_mir; -#[allow(unused_extern_crates)] extern crate rustc_parse; -#[allow(unused_extern_crates)] extern crate rustc_parse_format; -#[allow(unused_extern_crates)] extern crate rustc_session; -#[allow(unused_extern_crates)] extern crate rustc_span; -#[allow(unused_extern_crates)] extern crate rustc_target; -#[allow(unused_extern_crates)] extern crate rustc_trait_selection; -#[allow(unused_extern_crates)] extern crate rustc_typeck; use rustc_data_structures::fx::FxHashSet; @@ -85,14 +63,10 @@ use rustc_session::Session; /// # Example /// /// ``` -/// # #![feature(rustc_private)] -/// # #[allow(unused_extern_crates)] -/// # extern crate rustc_middle; -/// # #[allow(unused_extern_crates)] -/// # extern crate rustc_session; -/// # #[macro_use] -/// # use clippy_lints::declare_clippy_lint; +/// #![feature(rustc_private)] +/// extern crate rustc_session; /// use rustc_session::declare_tool_lint; +/// use clippy_lints::declare_clippy_lint; /// /// declare_clippy_lint! { /// /// **What it does:** Checks for ... (describe what the lint matches). diff --git a/src/driver.rs b/src/driver.rs index 3fca66a5792..decd3a79cce 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -7,15 +7,10 @@ // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) -#[allow(unused_extern_crates)] extern crate rustc_data_structures; -#[allow(unused_extern_crates)] extern crate rustc_driver; -#[allow(unused_extern_crates)] extern crate rustc_errors; -#[allow(unused_extern_crates)] extern crate rustc_interface; -#[allow(unused_extern_crates)] extern crate rustc_middle; use rustc_interface::interface; From fb4f9a0ad7a4656beb01c85b02b3e6ef15d914ec Mon Sep 17 00:00:00 2001 From: Teddy_Wang <wangtheo662@gmail.com> Date: Tue, 23 Jun 2020 11:40:38 -0400 Subject: [PATCH 225/526] Fix pattern match of ExprKind::MethodCall --- clippy_lints/src/map_identity.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/map_identity.rs b/clippy_lints/src/map_identity.rs index 9bc8f1bec1b..6607a26b130 100644 --- a/clippy_lints/src/map_identity.rs +++ b/clippy_lints/src/map_identity.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapIdentity { /// map(). Otherwise, returns None. fn get_map_argument<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<&'a [Expr<'a>]> { if_chain! { - if let ExprKind::MethodCall(ref method, _, ref args) = expr.kind; + if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind; if args.len() == 2 && method.ident.as_str() == "map"; let caller_ty = cx.tables.expr_ty(&args[0]); if match_trait_method(cx, expr, &paths::ITERATOR) From 5987c7d4041ce5d72c8412d2ad73fe3b63308b51 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Tue, 9 Jun 2020 22:40:43 +0200 Subject: [PATCH 226/526] cmp_owned: avoid FP when PartialEq is not implemented symmetrically --- clippy_lints/src/misc.rs | 35 ++++++++++++---------- tests/ui/cmp_owned/issue_4874.rs | 51 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 15 deletions(-) create mode 100644 tests/ui/cmp_owned/issue_4874.rs diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index a0947608e60..1b65a01690d 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -3,11 +3,11 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - def, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, Stmt, StmtKind, Ty, - TyKind, UnOp, + self as hir, def, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, Stmt, + StmtKind, TyKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{ExpnKind, Span}; @@ -571,6 +571,15 @@ fn is_array(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { } fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { + fn symmetric_partial_eq<'tcx>(cx: &LateContext<'_, 'tcx>, lhs: Ty<'tcx>, rhs: Ty<'tcx>) -> bool { + if let Some(trait_def_id) = cx.tcx.lang_items().eq_trait() { + return implements_trait(cx, lhs, trait_def_id, &[rhs.into()]) + && implements_trait(cx, rhs, trait_def_id, &[lhs.into()]); + } + + false + } + let (arg_ty, snip) = match expr.kind { ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => { if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) { @@ -594,18 +603,14 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { }; let other_ty = cx.tables.expr_ty_adjusted(other); - let partial_eq_trait_id = match cx.tcx.lang_items().eq_trait() { - Some(id) => id, - None => return, - }; - let deref_arg_impl_partial_eq_other = arg_ty.builtin_deref(true).map_or(false, |tam| { - implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty.into()]) - }); - let arg_impl_partial_eq_deref_other = other_ty.builtin_deref(true).map_or(false, |tam| { - implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty.into()]) - }); - let arg_impl_partial_eq_other = implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty.into()]); + let deref_arg_impl_partial_eq_other = arg_ty + .builtin_deref(true) + .map_or(false, |tam| symmetric_partial_eq(cx, tam.ty, other_ty)); + let arg_impl_partial_eq_deref_other = other_ty + .builtin_deref(true) + .map_or(false, |tam| symmetric_partial_eq(cx, arg_ty, tam.ty)); + let arg_impl_partial_eq_other = symmetric_partial_eq(cx, arg_ty, other_ty); if !deref_arg_impl_partial_eq_other && !arg_impl_partial_eq_deref_other && !arg_impl_partial_eq_other { return; @@ -694,7 +699,7 @@ fn non_macro_local(cx: &LateContext<'_, '_>, res: def::Res) -> bool { } } -fn check_cast(cx: &LateContext<'_, '_>, span: Span, e: &Expr<'_>, ty: &Ty<'_>) { +fn check_cast(cx: &LateContext<'_, '_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) { if_chain! { if let TyKind::Ptr(ref mut_ty) = ty.kind; if let ExprKind::Lit(ref lit) = e.kind; diff --git a/tests/ui/cmp_owned/issue_4874.rs b/tests/ui/cmp_owned/issue_4874.rs new file mode 100644 index 00000000000..b29c555eb1e --- /dev/null +++ b/tests/ui/cmp_owned/issue_4874.rs @@ -0,0 +1,51 @@ +#![allow(clippy::redundant_clone)] // See #5700 + +#[derive(PartialEq)] +struct Foo; + +struct Bar; + +impl std::fmt::Display for Bar { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "bar") + } +} + +// NOTE: PartialEq<Bar> for T can't be implemented due to the orphan rules +impl<T> PartialEq<T> for Bar +where + T: AsRef<str> + ?Sized, +{ + fn eq(&self, _: &T) -> bool { + true + } +} + +// NOTE: PartialEq<Bar> for Foo is not implemented +impl PartialEq<Foo> for Bar { + fn eq(&self, _: &Foo) -> bool { + true + } +} + +impl ToOwned for Bar { + type Owned = Foo; + fn to_owned(&self) -> Foo { + Foo + } +} + +impl std::borrow::Borrow<Bar> for Foo { + fn borrow(&self) -> &Bar { + static BAR: Bar = Bar; + &BAR + } +} + +fn main() { + let b = Bar {}; + if "Hi" == b.to_string() {} + + let f = Foo {}; + if f == b.to_owned() {} +} From b498e1d71537a79e7aff5378da625aca8b4eef96 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sat, 13 Jun 2020 00:03:19 +0200 Subject: [PATCH 227/526] cmp_owned: reverse operands if necessary --- clippy_lints/src/misc.rs | 81 ++++++++++------ .../ui/cmp_owned/asymmetric_partial_eq.fixed | 93 +++++++++++++++++++ tests/ui/cmp_owned/asymmetric_partial_eq.rs | 93 +++++++++++++++++++ .../ui/cmp_owned/asymmetric_partial_eq.stderr | 46 +++++++++ tests/ui/cmp_owned/issue_4874.rs | 51 ---------- 5 files changed, 283 insertions(+), 81 deletions(-) create mode 100644 tests/ui/cmp_owned/asymmetric_partial_eq.fixed create mode 100644 tests/ui/cmp_owned/asymmetric_partial_eq.rs create mode 100644 tests/ui/cmp_owned/asymmetric_partial_eq.stderr delete mode 100644 tests/ui/cmp_owned/issue_4874.rs diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 1b65a01690d..76ffe6f6a1c 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -371,8 +371,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints { if op.is_comparison() { check_nan(cx, left, expr); check_nan(cx, right, expr); - check_to_owned(cx, left, right); - check_to_owned(cx, right, left); + check_to_owned(cx, left, right, true); + check_to_owned(cx, right, left, false); } if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) { if is_allowed(cx, left) || is_allowed(cx, right) { @@ -570,20 +570,30 @@ fn is_array(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { matches!(&walk_ptrs_ty(cx.tables.expr_ty(expr)).kind, ty::Array(_, _)) } -fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { - fn symmetric_partial_eq<'tcx>(cx: &LateContext<'_, 'tcx>, lhs: Ty<'tcx>, rhs: Ty<'tcx>) -> bool { - if let Some(trait_def_id) = cx.tcx.lang_items().eq_trait() { - return implements_trait(cx, lhs, trait_def_id, &[rhs.into()]) - && implements_trait(cx, rhs, trait_def_id, &[lhs.into()]); - } +fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) { + #[derive(Default)] + struct EqImpl { + ty_eq_other: bool, + other_eq_ty: bool, + } - false + impl EqImpl { + fn is_implemented(&self) -> bool { + self.ty_eq_other || self.other_eq_ty + } + } + + fn symmetric_partial_eq<'tcx>(cx: &LateContext<'_, 'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>) -> Option<EqImpl> { + cx.tcx.lang_items().eq_trait().map(|def_id| EqImpl { + ty_eq_other: implements_trait(cx, ty, def_id, &[other.into()]), + other_eq_ty: implements_trait(cx, other, def_id, &[ty.into()]), + }) } let (arg_ty, snip) = match expr.kind { ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => { if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) { - (cx.tables.expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, "..")) + (cx.tables.expr_ty(&args[0]), snippet(cx, args[0].span, "..")) } else { return; } @@ -591,7 +601,7 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { ExprKind::Call(ref path, ref v) if v.len() == 1 => { if let ExprKind::Path(ref path) = path.kind { if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) { - (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, "..")) + (cx.tables.expr_ty(&v[0]), snippet(cx, v[0].span, "..")) } else { return; } @@ -602,24 +612,19 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { _ => return, }; - let other_ty = cx.tables.expr_ty_adjusted(other); + let other_ty = cx.tables.expr_ty(other); - let deref_arg_impl_partial_eq_other = arg_ty + let without_deref = symmetric_partial_eq(cx, arg_ty, other_ty).unwrap_or_default(); + let with_deref = arg_ty .builtin_deref(true) - .map_or(false, |tam| symmetric_partial_eq(cx, tam.ty, other_ty)); - let arg_impl_partial_eq_deref_other = other_ty - .builtin_deref(true) - .map_or(false, |tam| symmetric_partial_eq(cx, arg_ty, tam.ty)); - let arg_impl_partial_eq_other = symmetric_partial_eq(cx, arg_ty, other_ty); + .and_then(|tam| symmetric_partial_eq(cx, tam.ty, other_ty)) + .unwrap_or_default(); - if !deref_arg_impl_partial_eq_other && !arg_impl_partial_eq_deref_other && !arg_impl_partial_eq_other { + if !with_deref.is_implemented() && !without_deref.is_implemented() { return; } - let other_gets_derefed = match other.kind { - ExprKind::Unary(UnOp::UnDeref, _) => true, - _ => false, - }; + let other_gets_derefed = matches!(other.kind, ExprKind::Unary(UnOp::UnDeref, _)); let lint_span = if other_gets_derefed { expr.span.to(other.span) @@ -639,18 +644,34 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { return; } - let try_hint = if deref_arg_impl_partial_eq_other { - // suggest deref on the left - format!("*{}", snip) + let expr_snip; + let eq_impl; + if with_deref.is_implemented() { + expr_snip = format!("*{}", snip); + eq_impl = with_deref; } else { - // suggest dropping the to_owned on the left - snip.to_string() + expr_snip = snip.to_string(); + eq_impl = without_deref; }; + let span; + let hint; + if (eq_impl.ty_eq_other && left) || (eq_impl.other_eq_ty && !left) { + span = expr.span; + hint = expr_snip; + } else { + span = expr.span.to(other.span); + if eq_impl.ty_eq_other { + hint = format!("{} == {}", expr_snip, snippet(cx, other.span, "..")); + } else { + hint = format!("{} == {}", snippet(cx, other.span, ".."), expr_snip); + } + } + diag.span_suggestion( - lint_span, + span, "try", - try_hint, + hint, Applicability::MachineApplicable, // snippet ); }, diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.fixed b/tests/ui/cmp_owned/asymmetric_partial_eq.fixed new file mode 100644 index 00000000000..3305ac9bf8b --- /dev/null +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.fixed @@ -0,0 +1,93 @@ +// run-rustfix +#![allow(unused, clippy::redundant_clone)] // See #5700 + +// Define the types in each module to avoid trait impls leaking between modules. +macro_rules! impl_types { + () => { + #[derive(PartialEq)] + pub struct Owned; + + pub struct Borrowed; + + impl ToOwned for Borrowed { + type Owned = Owned; + fn to_owned(&self) -> Owned { + Owned {} + } + } + + impl std::borrow::Borrow<Borrowed> for Owned { + fn borrow(&self) -> &Borrowed { + static VALUE: Borrowed = Borrowed {}; + &VALUE + } + } + }; +} + +// Only Borrowed == Owned is implemented +mod borrowed_eq_owned { + impl_types!(); + + impl PartialEq<Owned> for Borrowed { + fn eq(&self, _: &Owned) -> bool { + true + } + } + + pub fn compare() { + let owned = Owned {}; + let borrowed = Borrowed {}; + + if borrowed == owned {} + if borrowed == owned {} + } +} + +// Only Owned == Borrowed is implemented +mod owned_eq_borrowed { + impl_types!(); + + impl PartialEq<Borrowed> for Owned { + fn eq(&self, _: &Borrowed) -> bool { + true + } + } + + fn compare() { + let owned = Owned {}; + let borrowed = Borrowed {}; + + if owned == borrowed {} + if owned == borrowed {} + } +} + +mod issue_4874 { + impl_types!(); + + // NOTE: PartialEq<Borrowed> for T can't be implemented due to the orphan rules + impl<T> PartialEq<T> for Borrowed + where + T: AsRef<str> + ?Sized, + { + fn eq(&self, _: &T) -> bool { + true + } + } + + impl std::fmt::Display for Borrowed { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "borrowed") + } + } + + fn compare() { + let borrowed = Borrowed {}; + + if borrowed == "Hi" {} + if borrowed == "Hi" {} + } +} + +fn main() {} diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.rs b/tests/ui/cmp_owned/asymmetric_partial_eq.rs new file mode 100644 index 00000000000..88bc2f51dd6 --- /dev/null +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.rs @@ -0,0 +1,93 @@ +// run-rustfix +#![allow(unused, clippy::redundant_clone)] // See #5700 + +// Define the types in each module to avoid trait impls leaking between modules. +macro_rules! impl_types { + () => { + #[derive(PartialEq)] + pub struct Owned; + + pub struct Borrowed; + + impl ToOwned for Borrowed { + type Owned = Owned; + fn to_owned(&self) -> Owned { + Owned {} + } + } + + impl std::borrow::Borrow<Borrowed> for Owned { + fn borrow(&self) -> &Borrowed { + static VALUE: Borrowed = Borrowed {}; + &VALUE + } + } + }; +} + +// Only Borrowed == Owned is implemented +mod borrowed_eq_owned { + impl_types!(); + + impl PartialEq<Owned> for Borrowed { + fn eq(&self, _: &Owned) -> bool { + true + } + } + + pub fn compare() { + let owned = Owned {}; + let borrowed = Borrowed {}; + + if borrowed.to_owned() == owned {} + if owned == borrowed.to_owned() {} + } +} + +// Only Owned == Borrowed is implemented +mod owned_eq_borrowed { + impl_types!(); + + impl PartialEq<Borrowed> for Owned { + fn eq(&self, _: &Borrowed) -> bool { + true + } + } + + fn compare() { + let owned = Owned {}; + let borrowed = Borrowed {}; + + if owned == borrowed.to_owned() {} + if borrowed.to_owned() == owned {} + } +} + +mod issue_4874 { + impl_types!(); + + // NOTE: PartialEq<Borrowed> for T can't be implemented due to the orphan rules + impl<T> PartialEq<T> for Borrowed + where + T: AsRef<str> + ?Sized, + { + fn eq(&self, _: &T) -> bool { + true + } + } + + impl std::fmt::Display for Borrowed { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "borrowed") + } + } + + fn compare() { + let borrowed = Borrowed {}; + + if "Hi" == borrowed.to_string() {} + if borrowed.to_string() == "Hi" {} + } +} + +fn main() {} diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.stderr b/tests/ui/cmp_owned/asymmetric_partial_eq.stderr new file mode 100644 index 00000000000..43bf8851fc6 --- /dev/null +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.stderr @@ -0,0 +1,46 @@ +error: this creates an owned instance just for comparison + --> $DIR/asymmetric_partial_eq.rs:42:12 + | +LL | if borrowed.to_owned() == owned {} + | ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` + | + = note: `-D clippy::cmp-owned` implied by `-D warnings` + +error: this creates an owned instance just for comparison + --> $DIR/asymmetric_partial_eq.rs:43:21 + | +LL | if owned == borrowed.to_owned() {} + | ---------^^^^^^^^^^^^^^^^^^^ + | | + | help: try: `borrowed == owned` + +error: this creates an owned instance just for comparison + --> $DIR/asymmetric_partial_eq.rs:61:21 + | +LL | if owned == borrowed.to_owned() {} + | ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` + +error: this creates an owned instance just for comparison + --> $DIR/asymmetric_partial_eq.rs:62:12 + | +LL | if borrowed.to_owned() == owned {} + | ^^^^^^^^^^^^^^^^^^^--------- + | | + | help: try: `owned == borrowed` + +error: this creates an owned instance just for comparison + --> $DIR/asymmetric_partial_eq.rs:88:20 + | +LL | if "Hi" == borrowed.to_string() {} + | --------^^^^^^^^^^^^^^^^^^^^ + | | + | help: try: `borrowed == "Hi"` + +error: this creates an owned instance just for comparison + --> $DIR/asymmetric_partial_eq.rs:89:12 + | +LL | if borrowed.to_string() == "Hi" {} + | ^^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/cmp_owned/issue_4874.rs b/tests/ui/cmp_owned/issue_4874.rs deleted file mode 100644 index b29c555eb1e..00000000000 --- a/tests/ui/cmp_owned/issue_4874.rs +++ /dev/null @@ -1,51 +0,0 @@ -#![allow(clippy::redundant_clone)] // See #5700 - -#[derive(PartialEq)] -struct Foo; - -struct Bar; - -impl std::fmt::Display for Bar { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "bar") - } -} - -// NOTE: PartialEq<Bar> for T can't be implemented due to the orphan rules -impl<T> PartialEq<T> for Bar -where - T: AsRef<str> + ?Sized, -{ - fn eq(&self, _: &T) -> bool { - true - } -} - -// NOTE: PartialEq<Bar> for Foo is not implemented -impl PartialEq<Foo> for Bar { - fn eq(&self, _: &Foo) -> bool { - true - } -} - -impl ToOwned for Bar { - type Owned = Foo; - fn to_owned(&self) -> Foo { - Foo - } -} - -impl std::borrow::Borrow<Bar> for Foo { - fn borrow(&self) -> &Bar { - static BAR: Bar = Bar; - &BAR - } -} - -fn main() { - let b = Bar {}; - if "Hi" == b.to_string() {} - - let f = Foo {}; - if f == b.to_owned() {} -} From 6bf5434e19ce6d2a501589d1fcbc0d1748c531a6 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Wed, 24 Jun 2020 01:01:23 +0200 Subject: [PATCH 228/526] copy_on_clone - add machine applicability --- clippy_lints/src/methods/mod.rs | 2 +- tests/ui/clone_on_copy.fixed | 40 +++++++++++++++++++++ tests/ui/clone_on_copy.rs | 40 +++++++++++++++++++++ tests/ui/clone_on_copy.stderr | 34 ++++++++++++++++++ tests/ui/unnecessary_clone.rs | 25 ------------- tests/ui/unnecessary_clone.stderr | 58 ++++++++----------------------- 6 files changed, 129 insertions(+), 70 deletions(-) create mode 100644 tests/ui/clone_on_copy.fixed create mode 100644 tests/ui/clone_on_copy.rs create mode 100644 tests/ui/clone_on_copy.stderr diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 214cf0c130f..74fefa65612 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2041,7 +2041,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir: } span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |diag| { if let Some((text, snip)) = snip { - diag.span_suggestion(expr.span, text, snip, Applicability::Unspecified); + diag.span_suggestion(expr.span, text, snip, Applicability::MachineApplicable); } }); } diff --git a/tests/ui/clone_on_copy.fixed b/tests/ui/clone_on_copy.fixed new file mode 100644 index 00000000000..1f0ca101757 --- /dev/null +++ b/tests/ui/clone_on_copy.fixed @@ -0,0 +1,40 @@ +// run-rustfix + +#![allow( + unused, + clippy::redundant_clone, + clippy::deref_addrof, + clippy::no_effect, + clippy::unnecessary_operation +)] + +use std::cell::RefCell; +use std::rc::{self, Rc}; +use std::sync::{self, Arc}; + +fn main() {} + +fn is_ascii(ch: char) -> bool { + ch.is_ascii() +} + +fn clone_on_copy() { + 42; + + vec![1].clone(); // ok, not a Copy type + Some(vec![1]).clone(); // ok, not a Copy type + *(&42); + + let rc = RefCell::new(0); + *rc.borrow(); + + // Issue #4348 + let mut x = 43; + let _ = &x.clone(); // ok, getting a ref + 'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate + is_ascii('z'); + + // Issue #5436 + let mut vec = Vec::new(); + vec.push(42); +} diff --git a/tests/ui/clone_on_copy.rs b/tests/ui/clone_on_copy.rs new file mode 100644 index 00000000000..ca39a654b4f --- /dev/null +++ b/tests/ui/clone_on_copy.rs @@ -0,0 +1,40 @@ +// run-rustfix + +#![allow( + unused, + clippy::redundant_clone, + clippy::deref_addrof, + clippy::no_effect, + clippy::unnecessary_operation +)] + +use std::cell::RefCell; +use std::rc::{self, Rc}; +use std::sync::{self, Arc}; + +fn main() {} + +fn is_ascii(ch: char) -> bool { + ch.is_ascii() +} + +fn clone_on_copy() { + 42.clone(); + + vec![1].clone(); // ok, not a Copy type + Some(vec![1]).clone(); // ok, not a Copy type + (&42).clone(); + + let rc = RefCell::new(0); + rc.borrow().clone(); + + // Issue #4348 + let mut x = 43; + let _ = &x.clone(); // ok, getting a ref + 'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate + is_ascii('z'.clone()); + + // Issue #5436 + let mut vec = Vec::new(); + vec.push(42.clone()); +} diff --git a/tests/ui/clone_on_copy.stderr b/tests/ui/clone_on_copy.stderr new file mode 100644 index 00000000000..ec2faf4ab40 --- /dev/null +++ b/tests/ui/clone_on_copy.stderr @@ -0,0 +1,34 @@ +error: using `clone` on a `Copy` type + --> $DIR/clone_on_copy.rs:22:5 + | +LL | 42.clone(); + | ^^^^^^^^^^ help: try removing the `clone` call: `42` + | + = note: `-D clippy::clone-on-copy` implied by `-D warnings` + +error: using `clone` on a `Copy` type + --> $DIR/clone_on_copy.rs:26:5 + | +LL | (&42).clone(); + | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` + +error: using `clone` on a `Copy` type + --> $DIR/clone_on_copy.rs:29:5 + | +LL | rc.borrow().clone(); + | ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()` + +error: using `clone` on a `Copy` type + --> $DIR/clone_on_copy.rs:35:14 + | +LL | is_ascii('z'.clone()); + | ^^^^^^^^^^^ help: try removing the `clone` call: `'z'` + +error: using `clone` on a `Copy` type + --> $DIR/clone_on_copy.rs:39:14 + | +LL | vec.push(42.clone()); + | ^^^^^^^^^^ help: try removing the `clone` call: `42` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index f1cc5b564c1..2c9d4d39e6c 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -13,31 +13,6 @@ impl SomeTrait for SomeImpl {} fn main() {} -fn is_ascii(ch: char) -> bool { - ch.is_ascii() -} - -fn clone_on_copy() { - 42.clone(); - - vec![1].clone(); // ok, not a Copy type - Some(vec![1]).clone(); // ok, not a Copy type - (&42).clone(); - - let rc = RefCell::new(0); - rc.borrow().clone(); - - // Issue #4348 - let mut x = 43; - let _ = &x.clone(); // ok, getting a ref - 'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate - is_ascii('z'.clone()); - - // Issue #5436 - let mut vec = Vec::new(); - vec.push(42.clone()); -} - fn clone_on_ref_ptr() { let rc = Rc::new(true); let arc = Arc::new(true); diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 6176a2bc464..113fab69009 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -1,37 +1,5 @@ -error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:21:5 - | -LL | 42.clone(); - | ^^^^^^^^^^ help: try removing the `clone` call: `42` - | - = note: `-D clippy::clone-on-copy` implied by `-D warnings` - -error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:25:5 - | -LL | (&42).clone(); - | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` - -error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:28:5 - | -LL | rc.borrow().clone(); - | ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()` - -error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:34:14 - | -LL | is_ascii('z'.clone()); - | ^^^^^^^^^^^ help: try removing the `clone` call: `'z'` - -error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:38:14 - | -LL | vec.push(42.clone()); - | ^^^^^^^^^^ help: try removing the `clone` call: `42` - error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:48:5 + --> $DIR/unnecessary_clone.rs:23:5 | LL | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::<bool>::clone(&rc)` @@ -39,43 +7,45 @@ LL | rc.clone(); = note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings` error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:51:5 + --> $DIR/unnecessary_clone.rs:26:5 | LL | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::<bool>::clone(&arc)` error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:54:5 + --> $DIR/unnecessary_clone.rs:29:5 | LL | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&rcweak)` error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:57:5 + --> $DIR/unnecessary_clone.rs:32:5 | LL | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&arc_weak)` error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:61:33 + --> $DIR/unnecessary_clone.rs:36:33 | LL | let _: Arc<dyn SomeTrait> = x.clone(); | ^^^^^^^^^ help: try this: `Arc::<SomeImpl>::clone(&x)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:65:5 + --> $DIR/unnecessary_clone.rs:40:5 | LL | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` + | + = note: `-D clippy::clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:67:5 + --> $DIR/unnecessary_clone.rs:42:5 | LL | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:73:22 + --> $DIR/unnecessary_clone.rs:48:22 | LL | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ @@ -91,13 +61,13 @@ LL | let z: &Vec<_> = <&std::vec::Vec<i32>>::clone(y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:109:20 + --> $DIR/unnecessary_clone.rs:84:20 | LL | let _: E = a.clone(); | ^^^^^^^^^ help: try dereferencing it: `*****a` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:114:22 + --> $DIR/unnecessary_clone.rs:89:22 | LL | let _ = &mut encoded.clone(); | ^^^^^^^^^^^^^^^ @@ -112,7 +82,7 @@ LL | let _ = &mut <&[u8]>::clone(encoded); | ^^^^^^^^^^^^^^^^^^^^^^^ error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:115:18 + --> $DIR/unnecessary_clone.rs:90:18 | LL | let _ = &encoded.clone(); | ^^^^^^^^^^^^^^^ @@ -126,5 +96,5 @@ help: or try being explicit if you are sure, that you want to clone a reference LL | let _ = &<&[u8]>::clone(encoded); | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 16 previous errors +error: aborting due to 11 previous errors From fa0f1d3e5353df04e3d2e68e65810ca1a231c220 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Thu, 25 Jun 2020 11:25:21 -0400 Subject: [PATCH 229/526] Change a noun to a verb to make the sentence complete --- clippy_lints/src/await_holding_lock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/await_holding_lock.rs b/clippy_lints/src/await_holding_lock.rs index a88f922d8e0..8f7e06b32ff 100644 --- a/clippy_lints/src/await_holding_lock.rs +++ b/clippy_lints/src/await_holding_lock.rs @@ -11,7 +11,7 @@ declare_clippy_lint! { /// non-async-aware MutexGuard. /// /// **Why is this bad?** The Mutex types found in syd::sync and parking_lot - /// are not designed to operator in an async context across await points. + /// are not designed to operate in an async context across await points. /// /// There are two potential solutions. One is to use an asynx-aware Mutex /// type. Many asynchronous foundation crates provide such a Mutex type. The From ab649c920e18929c8f2b3399178bcfd1ecdcdd3e Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 30 Jun 2020 16:19:42 +0200 Subject: [PATCH 230/526] Disable chrono integration test --- .github/workflows/clippy_bors.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 0c80394f03e..fd0cd7a1890 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -240,7 +240,8 @@ jobs: - 'Geal/nom' - 'rust-lang/stdarch' - 'serde-rs/serde' - - 'chronotope/chrono' + # FIXME: chrono currently cannot be compiled with `--all-targets` + # - 'chronotope/chrono' - 'hyperium/hyper' - 'rust-random/rand' - 'rust-lang/futures-rs' From 814349f9418b3d247e2e3cc952877e510f824fdd Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Fri, 26 Jun 2020 10:52:14 +0200 Subject: [PATCH 231/526] Lint enabling the whole restriction group --- CHANGELOG.md | 1 + clippy_lints/src/attrs.rs | 95 +++++++++++++++++++++++++++------------ clippy_lints/src/lib.rs | 3 ++ src/lintlist/mod.rs | 7 +++ tests/ui/attrs.rs | 6 +++ tests/ui/attrs.stderr | 33 ++++++++++++-- 6 files changed, 113 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6186c319d0..b88044d6ce8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1352,6 +1352,7 @@ Released 2018-09-13 [`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask [`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map [`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name +[`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints [`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_if_conditions [`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison [`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 41f125d4839..dd4dffda0f9 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -2,8 +2,8 @@ use crate::reexport::Name; use crate::utils::{ - first_line_of_span, is_present_in_source, match_def_path, paths, snippet_opt, span_lint, span_lint_and_sugg, - span_lint_and_then, without_block_comments, + first_line_of_span, is_present_in_source, match_def_path, paths, snippet_opt, span_lint, span_lint_and_help, + span_lint_and_sugg, span_lint_and_then, without_block_comments, }; use if_chain::if_chain; use rustc_ast::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; @@ -17,7 +17,7 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{Symbol, SymbolStr}; use semver::Version; static UNIX_SYSTEMS: &[&str] = &[ @@ -182,6 +182,29 @@ declare_clippy_lint! { "unknown_lints for scoped Clippy lints" } +declare_clippy_lint! { + /// **What it does:** Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category. + /// + /// **Why is this bad?** Restriction lints sometimes are in contrast with other lints or even go against idiomatic rust. + /// These lints should only be enabled on a lint-by-lint basis and with careful consideration. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// Bad: + /// ```rust + /// #![deny(clippy::restriction)] + /// ``` + /// + /// Good: + /// ```rust + /// #![deny(clippy::as_conversions)] + /// ``` + pub BLANKET_CLIPPY_RESTRICTION_LINTS, + correctness, + "enabling the complete restriction group" +} + declare_clippy_lint! { /// **What it does:** Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it /// with `#[rustfmt::skip]`. @@ -249,15 +272,17 @@ declare_lint_pass!(Attributes => [ DEPRECATED_SEMVER, USELESS_ATTRIBUTE, UNKNOWN_CLIPPY_LINTS, + BLANKET_CLIPPY_RESTRICTION_LINTS, ]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes { fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) { if let Some(items) = &attr.meta_item_list() { if let Some(ident) = attr.ident() { - match &*ident.as_str() { + let ident = &*ident.as_str(); + match ident { "allow" | "warn" | "deny" | "forbid" => { - check_clippy_lint_names(cx, items); + check_clippy_lint_names(cx, ident, items); }, _ => {}, } @@ -363,38 +388,43 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes { } } -#[allow(clippy::single_match_else)] -fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { - let lint_store = cx.lints(); - for lint in items { +fn check_clippy_lint_names(cx: &LateContext<'_, '_>, ident: &str, items: &[NestedMetaItem]) { + fn extract_name(lint: &NestedMetaItem) -> Option<SymbolStr> { if_chain! { if let Some(meta_item) = lint.meta_item(); if meta_item.path.segments.len() > 1; if let tool_name = meta_item.path.segments[0].ident; if tool_name.as_str() == "clippy"; - let name = meta_item.path.segments.last().unwrap().ident.name; - if let CheckLintNameResult::Tool(Err((None, _))) = lint_store.check_lint_name( - &name.as_str(), - Some(tool_name.name), - ); + let lint_name = meta_item.path.segments.last().unwrap().ident.name; then { + return Some(lint_name.as_str()); + } + } + None + } + + let lint_store = cx.lints(); + for lint in items { + if let Some(lint_name) = extract_name(lint) { + if let CheckLintNameResult::Tool(Err((None, _))) = + lint_store.check_lint_name(&lint_name, Some(sym!(clippy))) + { span_lint_and_then( cx, UNKNOWN_CLIPPY_LINTS, lint.span(), - &format!("unknown clippy lint: clippy::{}", name), + &format!("unknown clippy lint: clippy::{}", lint_name), |diag| { - let name_lower = name.as_str().to_lowercase(); - let symbols = lint_store.get_lints().iter().map( - |l| Symbol::intern(&l.name_lower()) - ).collect::<Vec<_>>(); - let sugg = find_best_match_for_name( - symbols.iter(), - &format!("clippy::{}", name_lower), - None, - ); - if name.as_str().chars().any(char::is_uppercase) - && lint_store.find_lints(&format!("clippy::{}", name_lower)).is_ok() { + let name_lower = lint_name.to_lowercase(); + let symbols = lint_store + .get_lints() + .iter() + .map(|l| Symbol::intern(&l.name_lower())) + .collect::<Vec<_>>(); + let sugg = find_best_match_for_name(symbols.iter(), &format!("clippy::{}", name_lower), None); + if lint_name.chars().any(char::is_uppercase) + && lint_store.find_lints(&format!("clippy::{}", name_lower)).is_ok() + { diag.span_suggestion( lint.span(), "lowercase the lint name", @@ -409,10 +439,19 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { Applicability::MachineApplicable, ); } - } + }, + ); + } else if lint_name == "restriction" && ident != "allow" { + span_lint_and_help( + cx, + BLANKET_CLIPPY_RESTRICTION_LINTS, + lint.span(), + "restriction lints are not meant to be all enabled", + None, + "try enabling only the lints you really need", ); } - }; + } } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 756b6b9a8a4..24eb492ee72 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -474,6 +474,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &assign_ops::ASSIGN_OP_PATTERN, &assign_ops::MISREFACTORED_ASSIGN_OP, &atomic_ordering::INVALID_ATOMIC_ORDERING, + &attrs::BLANKET_CLIPPY_RESTRICTION_LINTS, &attrs::DEPRECATED_CFG_ATTR, &attrs::DEPRECATED_SEMVER, &attrs::EMPTY_LINE_AFTER_OUTER_ATTR, @@ -1189,6 +1190,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&assign_ops::ASSIGN_OP_PATTERN), LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP), LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING), + LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), LintId::of(&attrs::DEPRECATED_CFG_ATTR), LintId::of(&attrs::DEPRECATED_SEMVER), LintId::of(&attrs::MISMATCHED_TARGET_OS), @@ -1614,6 +1616,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![ LintId::of(&approx_const::APPROX_CONSTANT), LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING), + LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), LintId::of(&attrs::DEPRECATED_SEMVER), LintId::of(&attrs::MISMATCHED_TARGET_OS), LintId::of(&attrs::USELESS_ATTRIBUTE), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 5a43a1a07d2..8d27e6282f1 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -80,6 +80,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "blacklisted_name", }, + Lint { + name: "blanket_clippy_restriction_lints", + group: "correctness", + desc: "enabling the complete restriction group", + deprecation: None, + module: "attrs", + }, Lint { name: "blocks_in_if_conditions", group: "style", diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index 91b65a43be7..908d063729f 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -1,5 +1,11 @@ #![warn(clippy::inline_always, clippy::deprecated_semver)] #![allow(clippy::assertions_on_constants)] +// Test that the whole restriction group is not enabled +#![warn(clippy::restriction)] +#![deny(clippy::restriction)] +#![forbid(clippy::restriction)] +#![allow(clippy::missing_docs_in_private_items, clippy::panic, clippy::unreachable)] + #[inline(always)] fn test_attr_lint() { assert!(true) diff --git a/tests/ui/attrs.stderr b/tests/ui/attrs.stderr index 39ddf6f226d..adceb4b6369 100644 --- a/tests/ui/attrs.stderr +++ b/tests/ui/attrs.stderr @@ -1,5 +1,5 @@ error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea - --> $DIR/attrs.rs:3:1 + --> $DIR/attrs.rs:9:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[inline(always)] = note: `-D clippy::inline-always` implied by `-D warnings` error: the since field must contain a semver-compliant version - --> $DIR/attrs.rs:23:14 + --> $DIR/attrs.rs:29:14 | LL | #[deprecated(since = "forever")] | ^^^^^^^^^^^^^^^^^ @@ -15,10 +15,35 @@ LL | #[deprecated(since = "forever")] = note: `-D clippy::deprecated-semver` implied by `-D warnings` error: the since field must contain a semver-compliant version - --> $DIR/attrs.rs:26:14 + --> $DIR/attrs.rs:32:14 | LL | #[deprecated(since = "1")] | ^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: restriction lints are not meant to be all enabled + --> $DIR/attrs.rs:4:9 + | +LL | #![warn(clippy::restriction)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(clippy::blanket_clippy_restriction_lints)]` on by default + = help: try enabling only the lints you really need + +error: restriction lints are not meant to be all enabled + --> $DIR/attrs.rs:5:9 + | +LL | #![deny(clippy::restriction)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try enabling only the lints you really need + +error: restriction lints are not meant to be all enabled + --> $DIR/attrs.rs:6:11 + | +LL | #![forbid(clippy::restriction)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try enabling only the lints you really need + +error: aborting due to 6 previous errors From c5d8f530e0625f14c5b4bedebdf0dc53064310c9 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sat, 27 Jun 2020 21:49:34 +0200 Subject: [PATCH 232/526] Move blanket_clippy_restriction_lints to "style" --- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/lib.rs | 2 +- src/lintlist/mod.rs | 2 +- tests/ui/attrs.stderr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index dd4dffda0f9..bb9d8be5dae 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -201,7 +201,7 @@ declare_clippy_lint! { /// #![deny(clippy::as_conversions)] /// ``` pub BLANKET_CLIPPY_RESTRICTION_LINTS, - correctness, + style, "enabling the complete restriction group" } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 24eb492ee72..50116a95612 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1443,6 +1443,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS), LintId::of(&assign_ops::ASSIGN_OP_PATTERN), + LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS), LintId::of(&bit_mask::VERBOSE_BIT_MASK), LintId::of(&blacklisted_name::BLACKLISTED_NAME), @@ -1616,7 +1617,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![ LintId::of(&approx_const::APPROX_CONSTANT), LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING), - LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), LintId::of(&attrs::DEPRECATED_SEMVER), LintId::of(&attrs::MISMATCHED_TARGET_OS), LintId::of(&attrs::USELESS_ATTRIBUTE), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 8d27e6282f1..5119fb40337 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -82,7 +82,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ }, Lint { name: "blanket_clippy_restriction_lints", - group: "correctness", + group: "style", desc: "enabling the complete restriction group", deprecation: None, module: "attrs", diff --git a/tests/ui/attrs.stderr b/tests/ui/attrs.stderr index adceb4b6369..ef4b89eaa6d 100644 --- a/tests/ui/attrs.stderr +++ b/tests/ui/attrs.stderr @@ -26,7 +26,7 @@ error: restriction lints are not meant to be all enabled LL | #![warn(clippy::restriction)] | ^^^^^^^^^^^^^^^^^^^ | - = note: `#[deny(clippy::blanket_clippy_restriction_lints)]` on by default + = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings` = help: try enabling only the lints you really need error: restriction lints are not meant to be all enabled From bff6c435ef597071410af5d136916231f310c64c Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Wed, 1 Jul 2020 00:15:21 +0200 Subject: [PATCH 233/526] Require `or_patterns` to suggest nesting them --- clippy_lints/src/unnested_or_patterns.rs | 4 ++-- tests/ui/unnested_or_patterns3.rs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 tests/ui/unnested_or_patterns3.rs diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 4d3682263f1..169a486d1eb 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -72,8 +72,8 @@ impl EarlyLintPass for UnnestedOrPatterns { } fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) { - if !cx.sess.opts.unstable_features.is_nightly_build() { - // User cannot do `#![feature(or_patterns)]`, so bail. + if !cx.sess.features_untracked().or_patterns { + // Do not suggest nesting the patterns if the feature `or_patterns` is not enabled. return; } diff --git a/tests/ui/unnested_or_patterns3.rs b/tests/ui/unnested_or_patterns3.rs new file mode 100644 index 00000000000..6bd35057bfa --- /dev/null +++ b/tests/ui/unnested_or_patterns3.rs @@ -0,0 +1,6 @@ +#![warn(clippy::unnested_or_patterns)] + +// Test that `unnested_or_patterns` does not trigger without enabling `or_patterns` +fn main() { + if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} +} From 5b9c2ff9ccebbc9ddb646c6f868f9972ccc64f4f Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Wed, 1 Jul 2020 07:30:03 +0200 Subject: [PATCH 234/526] Fix multiple_crate_versions error Fix the versions of packages in the multiple_crate_versions ui test by checking in the Cargo.lock for the test package. `ansi_term 0.11` depends on `winapi ^0.3.4`. This means means that the expected stderr for this test would have to be updated whenever `winapi 0.3` is updated otherwise. --- .../multiple_crate_versions/fail/Cargo.lock | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 tests/ui-cargo/multiple_crate_versions/fail/Cargo.lock diff --git a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.lock b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.lock new file mode 100644 index 00000000000..7e96aa36feb --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.lock @@ -0,0 +1,109 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "ctrlc" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653abc99aa905f693d89df4797fadc08085baee379db92be9f2496cefe8a6f2c" +dependencies = [ + "kernel32-sys", + "nix", + "winapi 0.2.8", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "libc" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" + +[[package]] +name = "multiple_crate_versions" +version = "0.1.0" +dependencies = [ + "ansi_term", + "ctrlc", +] + +[[package]] +name = "nix" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2c5afeb0198ec7be8569d666644b574345aad2e95a53baf3a532da3e0f3fb32" +dependencies = [ + "bitflags", + "cfg-if", + "libc", + "void", +] + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" From d347d0cf59d0a502361db873d900f4587c6e34de Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Wed, 1 Jul 2020 12:36:36 +0200 Subject: [PATCH 235/526] Deprecate regex_macro lint --- clippy_lints/src/deprecated_lints.rs | 10 ++++- clippy_lints/src/lib.rs | 9 +++-- clippy_lints/src/regex.rs | 57 ++-------------------------- clippy_lints/src/utils/paths.rs | 1 - src/lintlist/mod.rs | 7 ---- tests/ui/deprecated.rs | 1 + tests/ui/deprecated.stderr | 8 +++- tests/ui/regex.rs | 2 +- 8 files changed, 26 insertions(+), 69 deletions(-) diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 6e8ca647dd7..818d8188a78 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -153,5 +153,13 @@ declare_deprecated_lint! { /// /// **Deprecation reason:** Associated-constants are now preferred. pub REPLACE_CONSTS, - "associated-constants `MIN`/`MAX` of integers are prefer to `{min,max}_value()` and module constants" + "associated-constants `MIN`/`MAX` of integers are prefered to `{min,max}_value()` and module constants" +} + +declare_deprecated_lint! { + /// **What it does:** Nothing. This lint has been deprecated. + /// + /// **Deprecation reason:** The regex! macro does not exist anymore. + pub REGEX_MACRO, + "the regex! macro has been removed from the regex crate in 2018" } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 50116a95612..d31a597b66a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -460,7 +460,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ); store.register_removed( "clippy::replace_consts", - "associated-constants `MIN`/`MAX` of integers are prefer to `{min,max}_value()` and module constants", + "associated-constants `MIN`/`MAX` of integers are prefered to `{min,max}_value()` and module constants", + ); + store.register_removed( + "clippy::regex_macro", + "the regex! macro has been removed from the regex crate in 2018", ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` @@ -755,7 +759,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &reference::DEREF_ADDROF, &reference::REF_IN_DEREF, ®ex::INVALID_REGEX, - ®ex::REGEX_MACRO, ®ex::TRIVIAL_REGEX, &returns::NEEDLESS_RETURN, &returns::UNUSED_UNIT, @@ -1380,7 +1383,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&reference::DEREF_ADDROF), LintId::of(&reference::REF_IN_DEREF), LintId::of(®ex::INVALID_REGEX), - LintId::of(®ex::REGEX_MACRO), LintId::of(®ex::TRIVIAL_REGEX), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), @@ -1517,7 +1519,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES), LintId::of(&redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING), LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), - LintId::of(®ex::REGEX_MACRO), LintId::of(®ex::TRIVIAL_REGEX), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 9c54c3cbac0..7405edbcd19 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,9 +1,9 @@ use crate::consts::{constant, Constant}; -use crate::utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_lint_and_help}; +use crate::utils::{match_def_path, paths, span_lint, span_lint_and_help}; use if_chain::if_chain; use rustc_ast::ast::{LitKind, StrStyle}; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::{Block, BorrowKind, Crate, Expr, ExprKind, HirId}; +use rustc_hir::{BorrowKind, Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{BytePos, Span}; @@ -46,66 +46,15 @@ declare_clippy_lint! { "trivial regular expressions" } -declare_clippy_lint! { - /// **What it does:** Checks for usage of `regex!(_)` which (as of now) is - /// usually slower than `Regex::new(_)` unless called in a loop (which is a bad - /// idea anyway). - /// - /// **Why is this bad?** Performance, at least for now. The macro version is - /// likely to catch up long-term, but for now the dynamic version is faster. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```ignore - /// regex!("foo|bar") - /// ``` - pub REGEX_MACRO, - style, - "use of `regex!(_)` instead of `Regex::new(_)`" -} - #[derive(Clone, Default)] pub struct Regex { spans: FxHashSet<Span>, last: Option<HirId>, } -impl_lint_pass!(Regex => [INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX]); +impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Regex { - fn check_crate(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx Crate<'_>) { - self.spans.clear(); - } - - fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block<'_>) { - if_chain! { - if self.last.is_none(); - if let Some(ref expr) = block.expr; - if match_type(cx, cx.tables().expr_ty(expr), &paths::REGEX); - if let Some(span) = is_expn_of(expr.span, "regex"); - then { - if !self.spans.contains(&span) { - span_lint( - cx, - REGEX_MACRO, - span, - "`regex!(_)` found. \ - Please use `Regex::new(_)`, which is faster for now." - ); - self.spans.insert(span); - } - self.last = Some(block.hir_id); - } - } - } - - fn check_block_post(&mut self, _: &LateContext<'a, 'tcx>, block: &'tcx Block<'_>) { - if self.last.map_or(false, |id| block.hir_id == id) { - self.last = None; - } - } - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Call(ref fun, ref args) = expr.kind; diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 3b7e9739211..4c3462802e9 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -98,7 +98,6 @@ pub const RANGE_TO_STD: [&str; 3] = ["std", "ops", "RangeTo"]; pub const RC: [&str; 3] = ["alloc", "rc", "Rc"]; pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"]; pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"]; -pub const REGEX: [&str; 3] = ["regex", "re_unicode", "Regex"]; pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"]; pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"]; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 5119fb40337..a2998d74130 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1865,13 +1865,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "reference", }, - Lint { - name: "regex_macro", - group: "style", - desc: "use of `regex!(_)` instead of `Regex::new(_)`", - deprecation: None, - module: "regex", - }, Lint { name: "rest_pat_in_fully_bound_structs", group: "restriction", diff --git a/tests/ui/deprecated.rs b/tests/ui/deprecated.rs index 188a641aa1a..3eefb232780 100644 --- a/tests/ui/deprecated.rs +++ b/tests/ui/deprecated.rs @@ -7,5 +7,6 @@ #[warn(clippy::invalid_ref)] #[warn(clippy::into_iter_on_array)] #[warn(clippy::unused_label)] +#[warn(clippy::regex_macro)] fn main() {} diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index a4efe3d15a9..a80e2bf31fe 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -54,11 +54,17 @@ error: lint `clippy::unused_label` has been removed: `this lint has been uplifte LL | #[warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ +error: lint `clippy::regex_macro` has been removed: `the regex! macro has been removed from the regex crate in 2018` + --> $DIR/deprecated.rs:10:8 + | +LL | #[warn(clippy::regex_macro)] + | ^^^^^^^^^^^^^^^^^^^ + error: lint `clippy::str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` --> $DIR/deprecated.rs:1:8 | LL | #[warn(clippy::str_to_string)] | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index b523fa5b711..9767e5bf76a 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,5 +1,5 @@ #![allow(unused)] -#![warn(clippy::invalid_regex, clippy::trivial_regex, clippy::regex_macro)] +#![warn(clippy::invalid_regex, clippy::trivial_regex)] extern crate regex; From 754bfb1dc89ed9a98b2f1b7d77b035e809b14031 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sun, 28 Jun 2020 12:14:04 +0200 Subject: [PATCH 236/526] Add configurable threshold for `type_repetition_in_bounds` lint --- clippy_lints/src/lib.rs | 5 +++-- clippy_lints/src/trait_bounds.rs | 18 +++++++++++++--- clippy_lints/src/utils/conf.rs | 2 ++ .../toml_unknown_key/conf_unknown_key.stderr | 2 +- tests/ui/type_repetition_in_bounds.rs | 21 ++++++++++++++++++- tests/ui/type_repetition_in_bounds.stderr | 18 +++++++++++----- 6 files changed, 54 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d31a597b66a..38f8d007c72 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -996,7 +996,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box checked_conversions::CheckedConversions); store.register_late_pass(|| box integer_division::IntegerDivision); store.register_late_pass(|| box inherent_to_string::InherentToString); - store.register_late_pass(|| box trait_bounds::TraitBounds); + let max_trait_bounds = conf.max_trait_bounds; + store.register_late_pass(move || box trait_bounds::TraitBounds::new(max_trait_bounds)); store.register_late_pass(|| box comparison_chain::ComparisonChain); store.register_late_pass(|| box mut_key::MutableKeyType); store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic); @@ -1033,7 +1034,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let array_size_threshold = conf.array_size_threshold; store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold)); store.register_late_pass(move || box large_const_arrays::LargeConstArrays::new(array_size_threshold)); - store.register_late_pass(move || box floating_point_arithmetic::FloatingPointArithmetic); + store.register_late_pass(|| box floating_point_arithmetic::FloatingPointArithmetic); store.register_early_pass(|| box as_conversions::AsConversions); store.register_early_pass(|| box utils::internal_lints::ProduceIce); store.register_late_pass(|| box let_underscore::LetUnderscore); diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 9eb2079c3ca..650edbb4b11 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -5,9 +5,6 @@ use rustc_hir::{GenericBound, Generics, WherePredicate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -#[derive(Copy, Clone)] -pub struct TraitBounds; - declare_clippy_lint! { /// **What it does:** This lint warns about unnecessary type repetitions in trait bounds /// @@ -29,6 +26,18 @@ declare_clippy_lint! { "Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`" } +#[derive(Copy, Clone)] +pub struct TraitBounds { + max_trait_bounds: u64, +} + +impl TraitBounds { + #[must_use] + pub fn new(max_trait_bounds: u64) -> Self { + Self { max_trait_bounds } + } +} + impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS]); impl<'tcx> LateLintPass<'tcx> for TraitBounds { @@ -45,6 +54,9 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { let mut applicability = Applicability::MaybeIncorrect; for bound in gen.where_clause.predicates { if let WherePredicate::BoundPredicate(ref p) = bound { + if p.bounds.len() as u64 > self.max_trait_bounds { + return; + } let h = hash(&p.bounded_ty); if let Some(ref v) = map.insert(h, p.bounds.iter().collect::<Vec<_>>()) { let mut hint_string = format!( diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index c41befbf147..de425211e38 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -156,6 +156,8 @@ define_Conf! { (array_size_threshold, "array_size_threshold": u64, 512_000), /// Lint: VEC_BOX. The size of the boxed type in bytes, where boxing in a `Vec` is allowed (vec_box_size_threshold, "vec_box_size_threshold": u64, 4096), + /// Lint: TYPE_REPETITION_IN_BOUNDS. The maximum number of bounds a trait can have to be linted + (max_trait_bounds, "max_trait_bounds": u64, 3), /// Lint: STRUCT_EXCESSIVE_BOOLS. The maximum number of bools a struct can have (max_struct_bools, "max_struct_bools": u64, 3), /// Lint: FN_PARAMS_EXCESSIVE_BOOLS. The maximum number of bools function parameters can have diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 53970af4107..6fbba01416a 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,4 +1,4 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `third-party` at line 5 column 1 +error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `third-party` at line 5 column 1 error: aborting due to previous error diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs index 8b538be762b..60b994548b5 100644 --- a/tests/ui/type_repetition_in_bounds.rs +++ b/tests/ui/type_repetition_in_bounds.rs @@ -1,4 +1,6 @@ -#[deny(clippy::type_repetition_in_bounds)] +#![deny(clippy::type_repetition_in_bounds)] + +use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; pub fn foo<T>(_t: T) where @@ -16,4 +18,21 @@ where unimplemented!(); } +trait LintBounds +where + Self: Clone, + Self: Copy + Default + Ord, + Self: Add<Output = Self> + AddAssign + Sub<Output = Self> + SubAssign, + Self: Mul<Output = Self> + MulAssign + Div<Output = Self> + DivAssign, +{ +} + +trait LotsOfBounds +where + Self: Clone + Copy + Default + Ord, + Self: Add<Output = Self> + AddAssign + Sub<Output = Self> + SubAssign, + Self: Mul<Output = Self> + MulAssign + Div<Output = Self> + DivAssign, +{ +} + fn main() {} diff --git a/tests/ui/type_repetition_in_bounds.stderr b/tests/ui/type_repetition_in_bounds.stderr index 4264e2e10bf..6a1073a23f6 100644 --- a/tests/ui/type_repetition_in_bounds.stderr +++ b/tests/ui/type_repetition_in_bounds.stderr @@ -1,15 +1,23 @@ error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:6:5 + --> $DIR/type_repetition_in_bounds.rs:8:5 | LL | T: Clone, | ^^^^^^^^ | note: the lint level is defined here - --> $DIR/type_repetition_in_bounds.rs:1:8 + --> $DIR/type_repetition_in_bounds.rs:1:9 | -LL | #[deny(clippy::type_repetition_in_bounds)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(clippy::type_repetition_in_bounds)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: consider combining the bounds: `T: Copy + Clone` -error: aborting due to previous error +error: this type has already been used as a bound predicate + --> $DIR/type_repetition_in_bounds.rs:24:5 + | +LL | Self: Copy + Default + Ord, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider combining the bounds: `Self: Clone + Copy + Default + Ord` + +error: aborting due to 2 previous errors From d5a8f03a350e8a392f0aa1c05707b503f549e90b Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Fri, 3 Jul 2020 10:29:14 +0200 Subject: [PATCH 237/526] Take generic args into account for bounded type --- clippy_lints/src/utils/hir_utils.rs | 19 ++++++++++++------- tests/ui/type_repetition_in_bounds.rs | 15 +++++++++++++++ tests/ui/type_repetition_in_bounds.stderr | 2 +- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index ae58f0a1521..34341594c19 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -703,6 +703,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } for segment in path.segments { segment.ident.name.hash(&mut self.s); + self.hash_generic_args(segment.generic_args().args); } }, QPath::TypeRelative(ref ty, ref segment) => { @@ -711,13 +712,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, }, TyKind::OpaqueDef(_, arg_list) => { - for arg in *arg_list { - match arg { - GenericArg::Lifetime(ref l) => self.hash_lifetime(l), - GenericArg::Type(ref ty) => self.hash_ty(&ty), - GenericArg::Const(ref ca) => self.hash_body(ca.value.body), - } - } + self.hash_generic_args(arg_list); }, TyKind::TraitObject(_, lifetime) => { self.hash_lifetime(lifetime); @@ -735,4 +730,14 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(&self.cx.tcx.hir().body(body_id).value); self.maybe_typeck_tables = old_maybe_typeck_tables; } + + fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) { + for arg in arg_list { + match arg { + GenericArg::Lifetime(ref l) => self.hash_lifetime(l), + GenericArg::Type(ref ty) => self.hash_ty(&ty), + GenericArg::Const(ref ca) => self.hash_body(ca.value.body), + } + } + } } diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs index 60b994548b5..9f1700567d1 100644 --- a/tests/ui/type_repetition_in_bounds.rs +++ b/tests/ui/type_repetition_in_bounds.rs @@ -18,6 +18,7 @@ where unimplemented!(); } +// Threshold test (see #4380) trait LintBounds where Self: Clone, @@ -35,4 +36,18 @@ where { } +// Generic distinction (see #4323) +pub struct Foo<A>(A); +pub struct Bar<A, B> { + a: Foo<A>, + b: Foo<B>, +} + +impl<A, B> Unpin for Bar<A, B> +where + Foo<A>: Unpin, + Foo<B>: Unpin, +{ +} + fn main() {} diff --git a/tests/ui/type_repetition_in_bounds.stderr b/tests/ui/type_repetition_in_bounds.stderr index 6a1073a23f6..148c19c7d07 100644 --- a/tests/ui/type_repetition_in_bounds.stderr +++ b/tests/ui/type_repetition_in_bounds.stderr @@ -12,7 +12,7 @@ LL | #![deny(clippy::type_repetition_in_bounds)] = help: consider combining the bounds: `T: Copy + Clone` error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:24:5 + --> $DIR/type_repetition_in_bounds.rs:25:5 | LL | Self: Copy + Default + Ord, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ From 2d5930a3da7048d784489f28b44a769880b6ceff Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Fri, 3 Jul 2020 11:48:28 +0200 Subject: [PATCH 238/526] Don't lint for predicates generated in macros --- clippy_lints/src/trait_bounds.rs | 15 +++++++---- tests/ui/type_repetition_in_bounds.rs | 37 ++++++++++++++++++++------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 650edbb4b11..0ef70311fb1 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,4 +1,5 @@ use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_help, SpanlessHash}; +use if_chain::if_chain; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::{GenericBound, Generics, WherePredicate}; @@ -11,6 +12,8 @@ declare_clippy_lint! { /// **Why is this bad?** Repeating the type for every bound makes the code /// less readable than combining the bounds /// + /// **Known problems:** None. + /// /// **Example:** /// ```rust /// pub fn foo<T>(t: T) where T: Copy, T: Clone {} @@ -53,12 +56,14 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { let mut map = FxHashMap::default(); let mut applicability = Applicability::MaybeIncorrect; for bound in gen.where_clause.predicates { - if let WherePredicate::BoundPredicate(ref p) = bound { - if p.bounds.len() as u64 > self.max_trait_bounds { - return; - } + if_chain! { + if let WherePredicate::BoundPredicate(ref p) = bound; + if p.bounds.len() as u64 <= self.max_trait_bounds; + if !in_macro(p.span); let h = hash(&p.bounded_ty); - if let Some(ref v) = map.insert(h, p.bounds.iter().collect::<Vec<_>>()) { + if let Some(ref v) = map.insert(h, p.bounds.iter().collect::<Vec<_>>()); + + then { let mut hint_string = format!( "consider combining the bounds: `{}:", snippet(cx, p.bounded_ty.span, "_") diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs index 9f1700567d1..766190f2099 100644 --- a/tests/ui/type_repetition_in_bounds.rs +++ b/tests/ui/type_repetition_in_bounds.rs @@ -37,17 +37,36 @@ where } // Generic distinction (see #4323) -pub struct Foo<A>(A); -pub struct Bar<A, B> { - a: Foo<A>, - b: Foo<B>, +mod issue4323 { + pub struct Foo<A>(A); + pub struct Bar<A, B> { + a: Foo<A>, + b: Foo<B>, + } + + impl<A, B> Unpin for Bar<A, B> + where + Foo<A>: Unpin, + Foo<B>: Unpin, + { + } } -impl<A, B> Unpin for Bar<A, B> -where - Foo<A>: Unpin, - Foo<B>: Unpin, -{ +// Extern macros shouldn't lint (see #4326) +extern crate serde; +mod issue4326 { + use serde::{Deserialize, Serialize}; + + trait Foo {} + impl Foo for String {} + + #[derive(Debug, Serialize, Deserialize)] + struct Bar<S> + where + S: Foo, + { + foo: S, + } } fn main() {} From c3c402783f1d12852982f9dc734cc4c07b9fce33 Mon Sep 17 00:00:00 2001 From: Robert Sedlacek <rs@474.at> Date: Mon, 4 Nov 2019 19:39:03 +0100 Subject: [PATCH 239/526] Added restriction lint: pattern-type-mismatch --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 4 + clippy_lints/src/pattern_type_mismatch.rs | 276 ++++++++++++++++++ src/lintlist/mod.rs | 7 + tests/ui/pattern_type_mismatch/mutability.rs | 40 +++ .../pattern_type_mismatch/mutability.stderr | 19 ++ .../pattern_alternatives.rs | 24 ++ .../pattern_alternatives.stderr | 27 ++ .../pattern_type_mismatch/pattern_structs.rs | 45 +++ .../pattern_structs.stderr | 67 +++++ .../pattern_type_mismatch/pattern_tuples.rs | 57 ++++ .../pattern_tuples.stderr | 83 ++++++ tests/ui/pattern_type_mismatch/syntax.rs | 146 +++++++++ tests/ui/pattern_type_mismatch/syntax.stderr | 78 +++++ 14 files changed, 874 insertions(+) create mode 100644 clippy_lints/src/pattern_type_mismatch.rs create mode 100644 tests/ui/pattern_type_mismatch/mutability.rs create mode 100644 tests/ui/pattern_type_mismatch/mutability.stderr create mode 100644 tests/ui/pattern_type_mismatch/pattern_alternatives.rs create mode 100644 tests/ui/pattern_type_mismatch/pattern_alternatives.stderr create mode 100644 tests/ui/pattern_type_mismatch/pattern_structs.rs create mode 100644 tests/ui/pattern_type_mismatch/pattern_structs.stderr create mode 100644 tests/ui/pattern_type_mismatch/pattern_tuples.rs create mode 100644 tests/ui/pattern_type_mismatch/pattern_tuples.stderr create mode 100644 tests/ui/pattern_type_mismatch/syntax.rs create mode 100644 tests/ui/pattern_type_mismatch/syntax.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index b88044d6ce8..ed8f16e65bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1588,6 +1588,7 @@ Released 2018-09-13 [`panicking_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#panicking_unwrap [`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl [`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite +[`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch [`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma [`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence [`print_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_literal diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d31a597b66a..4890349999f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -268,6 +268,7 @@ mod overflow_check_conditional; mod panic_unimplemented; mod partialeq_ne_impl; mod path_buf_push_overwrite; +pub mod pattern_type_mismatch; mod precedence; mod ptr; mod ptr_offset_with_cast; @@ -741,6 +742,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &panic_unimplemented::UNREACHABLE, &partialeq_ne_impl::PARTIALEQ_NE_IMPL, &path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE, + &pattern_type_mismatch::PATTERN_TYPE_MISMATCH, &precedence::PRECEDENCE, &ptr::CMP_NULL, &ptr::MUT_FROM_REF, @@ -1064,6 +1066,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box unnested_or_patterns::UnnestedOrPatterns); store.register_late_pass(|| box macro_use::MacroUseImports::default()); store.register_late_pass(|| box map_identity::MapIdentity); + store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1097,6 +1100,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&panic_unimplemented::TODO), LintId::of(&panic_unimplemented::UNIMPLEMENTED), LintId::of(&panic_unimplemented::UNREACHABLE), + LintId::of(&pattern_type_mismatch::PATTERN_TYPE_MISMATCH), LintId::of(&shadow::SHADOW_REUSE), LintId::of(&shadow::SHADOW_SAME), LintId::of(&strings::STRING_ADD), diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs new file mode 100644 index 00000000000..a07279c92b0 --- /dev/null +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -0,0 +1,276 @@ +use crate::utils::{last_path_segment, span_help_and_lint}; +use rustc::lint::in_external_macro; +use rustc::ty::subst::SubstsRef; +use rustc::ty::{AdtDef, FieldDef, Ty, TyKind, VariantDef}; +use rustc_hir::{ + intravisit, Body, Expr, ExprKind, FieldPat, FnDecl, HirId, LocalSource, MatchSource, Mutability, Pat, PatKind, + QPath, Stmt, StmtKind, +}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Span; + +declare_clippy_lint! { + /// **What it does:** Checks for patterns that aren't exact representations of the types + /// they are applied to. + /// + /// **Why is this bad?** It isn't bad in general. But in some contexts it can be desirable + /// because it increases ownership hints in the code, and will guard against some changes + /// in ownership. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust,ignore + /// // Bad + /// let value = &Some(Box::new(23)); + /// match value { + /// Some(inner) => println!("{}", inner), + /// None => println!("none"), + /// } + /// + /// // Good + /// let value = &Some(Box::new(23)); + /// match *value { + /// Some(ref inner) => println!("{}", inner), + /// None => println!("none"), + /// } + /// ``` + pub PATTERN_TYPE_MISMATCH, + restriction, + "type of pattern does not match the expression type" +} + +declare_lint_pass!(PatternTypeMismatch => [PATTERN_TYPE_MISMATCH]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PatternTypeMismatch { + fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) { + if let StmtKind::Local(ref local) = stmt.kind { + if let Some(init) = &local.init { + if let Some(init_ty) = cx.tables.node_type_opt(init.hir_id) { + let pat = &local.pat; + if in_external_macro(cx.sess(), pat.span) { + return; + } + let deref_possible = match local.source { + LocalSource::Normal => DerefPossible::Possible, + _ => DerefPossible::Impossible, + }; + apply_lint(cx, pat, init_ty, deref_possible); + } + } + } + } + + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + if let ExprKind::Match(ref expr, arms, source) = expr.kind { + match source { + MatchSource::Normal | MatchSource::IfLetDesugar { .. } | MatchSource::WhileLetDesugar => { + if let Some(expr_ty) = cx.tables.node_type_opt(expr.hir_id) { + 'pattern_checks: for arm in arms { + let pat = &arm.pat; + if in_external_macro(cx.sess(), pat.span) { + continue 'pattern_checks; + } + if apply_lint(cx, pat, expr_ty, DerefPossible::Possible) { + break 'pattern_checks; + } + } + } + }, + _ => (), + } + } + } + + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + _: intravisit::FnKind<'tcx>, + _: &'tcx FnDecl<'_>, + body: &'tcx Body<'_>, + _: Span, + hir_id: HirId, + ) { + if let Some(fn_sig) = cx.tables.liberated_fn_sigs().get(hir_id) { + for (param, ty) in body.params.iter().zip(fn_sig.inputs().iter()) { + apply_lint(cx, ¶m.pat, ty, DerefPossible::Impossible); + } + } + } +} + +#[derive(Debug, Clone, Copy)] +enum DerefPossible { + Possible, + Impossible, +} + +fn apply_lint<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + pat: &Pat<'_>, + expr_ty: Ty<'tcx>, + deref_possible: DerefPossible, +) -> bool { + let maybe_mismatch = find_first_mismatch(cx, pat, expr_ty, Level::Top); + if let Some((span, mutability, level)) = maybe_mismatch { + span_help_and_lint( + cx, + PATTERN_TYPE_MISMATCH, + span, + "type of pattern does not match the expression type", + &format!( + "{}explicitly match against a `{}` pattern and adjust the enclosed variable bindings", + match (deref_possible, level) { + (DerefPossible::Possible, Level::Top) => "use `*` to dereference the match expression or ", + _ => "", + }, + match mutability { + Mutability::Mut => "&mut _", + Mutability::Not => "&_", + }, + ), + ); + true + } else { + false + } +} + +#[derive(Debug, Copy, Clone)] +enum Level { + Top, + Lower, +} + +#[allow(rustc::usage_of_ty_tykind)] +fn find_first_mismatch<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + pat: &Pat<'_>, + ty: Ty<'tcx>, + level: Level, +) -> Option<(Span, Mutability, Level)> { + if let PatKind::Ref(ref sub_pat, _) = pat.kind { + if let TyKind::Ref(_, sub_ty, _) = ty.kind { + return find_first_mismatch(cx, sub_pat, sub_ty, Level::Lower); + } + } + + if let TyKind::Ref(_, _, mutability) = ty.kind { + if is_non_ref_pattern(&pat.kind) { + return Some((pat.span, mutability, level)); + } + } + + if let PatKind::Struct(ref qpath, ref field_pats, _) = pat.kind { + if let TyKind::Adt(ref adt_def, ref substs_ref) = ty.kind { + if let Some(variant) = get_variant(adt_def, qpath) { + let field_defs = &variant.fields; + return find_first_mismatch_in_struct(cx, field_pats, field_defs, substs_ref); + } + } + } + + if let PatKind::TupleStruct(ref qpath, ref pats, _) = pat.kind { + if let TyKind::Adt(ref adt_def, ref substs_ref) = ty.kind { + if let Some(variant) = get_variant(adt_def, qpath) { + let field_defs = &variant.fields; + let ty_iter = field_defs.iter().map(|field_def| field_def.ty(cx.tcx, substs_ref)); + return find_first_mismatch_in_tuple(cx, pats, ty_iter); + } + } + } + + if let PatKind::Tuple(ref pats, _) = pat.kind { + if let TyKind::Tuple(..) = ty.kind { + return find_first_mismatch_in_tuple(cx, pats, ty.tuple_fields()); + } + } + + if let PatKind::Or(sub_pats) = pat.kind { + for pat in sub_pats { + let maybe_mismatch = find_first_mismatch(cx, pat, ty, level); + if let Some(mismatch) = maybe_mismatch { + return Some(mismatch); + } + } + } + + None +} + +fn get_variant<'a>(adt_def: &'a AdtDef, qpath: &QPath<'_>) -> Option<&'a VariantDef> { + if adt_def.is_struct() { + if let Some(variant) = adt_def.variants.iter().next() { + return Some(variant); + } + } + + if adt_def.is_enum() { + let pat_ident = last_path_segment(qpath).ident; + for variant in &adt_def.variants { + if variant.ident == pat_ident { + return Some(variant); + } + } + } + + None +} + +fn find_first_mismatch_in_tuple<'a, 'tcx, I>( + cx: &LateContext<'a, 'tcx>, + pats: &[&Pat<'_>], + ty_iter_src: I, +) -> Option<(Span, Mutability, Level)> +where + I: IntoIterator<Item = Ty<'tcx>>, +{ + let mut field_tys = ty_iter_src.into_iter(); + 'fields: for pat in pats { + let field_ty = if let Some(ty) = field_tys.next() { + ty + } else { + break 'fields; + }; + + let maybe_mismatch = find_first_mismatch(cx, pat, field_ty, Level::Lower); + if let Some(mismatch) = maybe_mismatch { + return Some(mismatch); + } + } + + None +} + +fn find_first_mismatch_in_struct<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + field_pats: &[FieldPat<'_>], + field_defs: &[FieldDef], + substs_ref: SubstsRef<'tcx>, +) -> Option<(Span, Mutability, Level)> { + for field_pat in field_pats { + 'definitions: for field_def in field_defs { + if field_pat.ident == field_def.ident { + let field_ty = field_def.ty(cx.tcx, substs_ref); + let pat = &field_pat.pat; + let maybe_mismatch = find_first_mismatch(cx, pat, field_ty, Level::Lower); + if let Some(mismatch) = maybe_mismatch { + return Some(mismatch); + } + break 'definitions; + } + } + } + + None +} + +fn is_non_ref_pattern(pat_kind: &PatKind<'_>) -> bool { + match pat_kind { + PatKind::Struct(..) | PatKind::Tuple(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => true, + PatKind::Or(sub_pats) => sub_pats.iter().any(|pat| is_non_ref_pattern(&pat.kind)), + _ => false, + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index a2998d74130..6402efc2521 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1697,6 +1697,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "path_buf_push_overwrite", }, + Lint { + name: "pattern_type_mismatch", + group: "restriction", + desc: "type of pattern does not match the expression type", + deprecation: None, + module: "pattern_type_mismatch", + }, Lint { name: "possible_missing_comma", group: "correctness", diff --git a/tests/ui/pattern_type_mismatch/mutability.rs b/tests/ui/pattern_type_mismatch/mutability.rs new file mode 100644 index 00000000000..9b4f2f1f579 --- /dev/null +++ b/tests/ui/pattern_type_mismatch/mutability.rs @@ -0,0 +1,40 @@ +#![allow(clippy::all)] +#![warn(clippy::pattern_type_mismatch)] + +fn main() {} + +fn should_lint() { + let value = &Some(23); + match value { + Some(_) => (), + _ => (), + } + + let value = &mut Some(23); + match value { + Some(_) => (), + _ => (), + } +} + +fn should_not_lint() { + let value = &Some(23); + match value { + &Some(_) => (), + _ => (), + } + match *value { + Some(_) => (), + _ => (), + } + + let value = &mut Some(23); + match value { + &mut Some(_) => (), + _ => (), + } + match *value { + Some(_) => (), + _ => (), + } +} diff --git a/tests/ui/pattern_type_mismatch/mutability.stderr b/tests/ui/pattern_type_mismatch/mutability.stderr new file mode 100644 index 00000000000..3421d568365 --- /dev/null +++ b/tests/ui/pattern_type_mismatch/mutability.stderr @@ -0,0 +1,19 @@ +error: type of pattern does not match the expression type + --> $DIR/mutability.rs:9:9 + | +LL | Some(_) => (), + | ^^^^^^^ + | + = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings` + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/mutability.rs:15:9 + | +LL | Some(_) => (), + | ^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&mut _` pattern and adjust the enclosed variable bindings + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pattern_type_mismatch/pattern_alternatives.rs b/tests/ui/pattern_type_mismatch/pattern_alternatives.rs new file mode 100644 index 00000000000..065ea9fb9b5 --- /dev/null +++ b/tests/ui/pattern_type_mismatch/pattern_alternatives.rs @@ -0,0 +1,24 @@ +#![allow(clippy::all)] +#![warn(clippy::pattern_type_mismatch)] + +fn main() {} + +fn alternatives() { + enum Value<'a> { + Unused, + A(&'a Option<i32>), + B, + } + let ref_value = &Value::A(&Some(23)); + + // not ok + if let Value::B | Value::A(_) = ref_value {} + if let &Value::B | &Value::A(Some(_)) = ref_value {} + if let Value::B | Value::A(Some(_)) = *ref_value {} + + // ok + if let &Value::B | &Value::A(_) = ref_value {} + if let Value::B | Value::A(_) = *ref_value {} + if let &Value::B | &Value::A(&Some(_)) = ref_value {} + if let Value::B | Value::A(&Some(_)) = *ref_value {} +} diff --git a/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr b/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr new file mode 100644 index 00000000000..d285c93782c --- /dev/null +++ b/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr @@ -0,0 +1,27 @@ +error: type of pattern does not match the expression type + --> $DIR/pattern_alternatives.rs:15:12 + | +LL | if let Value::B | Value::A(_) = ref_value {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings` + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_alternatives.rs:16:34 + | +LL | if let &Value::B | &Value::A(Some(_)) = ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_alternatives.rs:17:32 + | +LL | if let Value::B | Value::A(Some(_)) = *ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pattern_type_mismatch/pattern_structs.rs b/tests/ui/pattern_type_mismatch/pattern_structs.rs new file mode 100644 index 00000000000..417b1c107c5 --- /dev/null +++ b/tests/ui/pattern_type_mismatch/pattern_structs.rs @@ -0,0 +1,45 @@ +#![allow(clippy::all)] +#![warn(clippy::pattern_type_mismatch)] + +fn main() {} + +fn struct_types() { + struct Struct<'a> { + ref_inner: &'a Option<i32>, + } + let ref_value = &Struct { ref_inner: &Some(42) }; + + // not ok + let Struct { .. } = ref_value; + if let &Struct { ref_inner: Some(_) } = ref_value {} + if let Struct { ref_inner: Some(_) } = *ref_value {} + + // ok + let &Struct { .. } = ref_value; + let Struct { .. } = *ref_value; + if let &Struct { ref_inner: &Some(_) } = ref_value {} + if let Struct { ref_inner: &Some(_) } = *ref_value {} +} + +fn struct_enum_variants() { + enum StructEnum<'a> { + Empty, + Var { inner_ref: &'a Option<i32> }, + } + let ref_value = &StructEnum::Var { inner_ref: &Some(42) }; + + // not ok + if let StructEnum::Var { .. } = ref_value {} + if let StructEnum::Var { inner_ref: Some(_) } = ref_value {} + if let &StructEnum::Var { inner_ref: Some(_) } = ref_value {} + if let StructEnum::Var { inner_ref: Some(_) } = *ref_value {} + if let StructEnum::Empty = ref_value {} + + // ok + if let &StructEnum::Var { .. } = ref_value {} + if let StructEnum::Var { .. } = *ref_value {} + if let &StructEnum::Var { inner_ref: &Some(_) } = ref_value {} + if let StructEnum::Var { inner_ref: &Some(_) } = *ref_value {} + if let &StructEnum::Empty = ref_value {} + if let StructEnum::Empty = *ref_value {} +} diff --git a/tests/ui/pattern_type_mismatch/pattern_structs.stderr b/tests/ui/pattern_type_mismatch/pattern_structs.stderr new file mode 100644 index 00000000000..d428e85b0c9 --- /dev/null +++ b/tests/ui/pattern_type_mismatch/pattern_structs.stderr @@ -0,0 +1,67 @@ +error: type of pattern does not match the expression type + --> $DIR/pattern_structs.rs:13:9 + | +LL | let Struct { .. } = ref_value; + | ^^^^^^^^^^^^^ + | + = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings` + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_structs.rs:14:33 + | +LL | if let &Struct { ref_inner: Some(_) } = ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_structs.rs:15:32 + | +LL | if let Struct { ref_inner: Some(_) } = *ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_structs.rs:32:12 + | +LL | if let StructEnum::Var { .. } = ref_value {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_structs.rs:33:12 + | +LL | if let StructEnum::Var { inner_ref: Some(_) } = ref_value {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_structs.rs:34:42 + | +LL | if let &StructEnum::Var { inner_ref: Some(_) } = ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_structs.rs:35:41 + | +LL | if let StructEnum::Var { inner_ref: Some(_) } = *ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_structs.rs:36:12 + | +LL | if let StructEnum::Empty = ref_value {} + | ^^^^^^^^^^^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: aborting due to 8 previous errors + diff --git a/tests/ui/pattern_type_mismatch/pattern_tuples.rs b/tests/ui/pattern_type_mismatch/pattern_tuples.rs new file mode 100644 index 00000000000..19504a051d8 --- /dev/null +++ b/tests/ui/pattern_type_mismatch/pattern_tuples.rs @@ -0,0 +1,57 @@ +#![allow(clippy::all)] +#![warn(clippy::pattern_type_mismatch)] + +fn main() {} + +fn tuple_types() { + struct TupleStruct<'a>(&'a Option<i32>); + let ref_value = &TupleStruct(&Some(42)); + + // not ok + let TupleStruct(_) = ref_value; + if let &TupleStruct(Some(_)) = ref_value {} + if let TupleStruct(Some(_)) = *ref_value {} + + // ok + let &TupleStruct(_) = ref_value; + let TupleStruct(_) = *ref_value; + if let &TupleStruct(&Some(_)) = ref_value {} + if let TupleStruct(&Some(_)) = *ref_value {} +} + +fn tuple_enum_variants() { + enum TupleEnum<'a> { + Empty, + Var(&'a Option<i32>), + } + let ref_value = &TupleEnum::Var(&Some(42)); + + // not ok + if let TupleEnum::Var(_) = ref_value {} + if let &TupleEnum::Var(Some(_)) = ref_value {} + if let TupleEnum::Var(Some(_)) = *ref_value {} + if let TupleEnum::Empty = ref_value {} + + // ok + if let &TupleEnum::Var(_) = ref_value {} + if let TupleEnum::Var(_) = *ref_value {} + if let &TupleEnum::Var(&Some(_)) = ref_value {} + if let TupleEnum::Var(&Some(_)) = *ref_value {} + if let &TupleEnum::Empty = ref_value {} + if let TupleEnum::Empty = *ref_value {} +} + +fn plain_tuples() { + let ref_value = &(&Some(23), &Some(42)); + + // not ok + let (_a, _b) = ref_value; + if let &(_a, Some(_)) = ref_value {} + if let (_a, Some(_)) = *ref_value {} + + // ok + let &(_a, _b) = ref_value; + let (_a, _b) = *ref_value; + if let &(_a, &Some(_)) = ref_value {} + if let (_a, &Some(_)) = *ref_value {} +} diff --git a/tests/ui/pattern_type_mismatch/pattern_tuples.stderr b/tests/ui/pattern_type_mismatch/pattern_tuples.stderr new file mode 100644 index 00000000000..edd0074d00d --- /dev/null +++ b/tests/ui/pattern_type_mismatch/pattern_tuples.stderr @@ -0,0 +1,83 @@ +error: type of pattern does not match the expression type + --> $DIR/pattern_tuples.rs:11:9 + | +LL | let TupleStruct(_) = ref_value; + | ^^^^^^^^^^^^^^ + | + = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings` + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_tuples.rs:12:25 + | +LL | if let &TupleStruct(Some(_)) = ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_tuples.rs:13:24 + | +LL | if let TupleStruct(Some(_)) = *ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_tuples.rs:30:12 + | +LL | if let TupleEnum::Var(_) = ref_value {} + | ^^^^^^^^^^^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_tuples.rs:31:28 + | +LL | if let &TupleEnum::Var(Some(_)) = ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_tuples.rs:32:27 + | +LL | if let TupleEnum::Var(Some(_)) = *ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_tuples.rs:33:12 + | +LL | if let TupleEnum::Empty = ref_value {} + | ^^^^^^^^^^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_tuples.rs:48:9 + | +LL | let (_a, _b) = ref_value; + | ^^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_tuples.rs:49:18 + | +LL | if let &(_a, Some(_)) = ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/pattern_tuples.rs:50:17 + | +LL | if let (_a, Some(_)) = *ref_value {} + | ^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: aborting due to 10 previous errors + diff --git a/tests/ui/pattern_type_mismatch/syntax.rs b/tests/ui/pattern_type_mismatch/syntax.rs new file mode 100644 index 00000000000..e89917c41e8 --- /dev/null +++ b/tests/ui/pattern_type_mismatch/syntax.rs @@ -0,0 +1,146 @@ +#![allow(clippy::all)] +#![warn(clippy::pattern_type_mismatch)] + +fn main() {} + +fn syntax_match() { + let ref_value = &Some(&Some(42)); + + // not ok + match ref_value { + Some(_) => (), + None => (), + } + + // ok + match ref_value { + &Some(_) => (), + &None => (), + } + match *ref_value { + Some(_) => (), + None => (), + } +} + +fn syntax_if_let() { + let ref_value = &Some(42); + + // not ok + if let Some(_) = ref_value {} + + // ok + if let &Some(_) = ref_value {} + if let Some(_) = *ref_value {} +} + +fn syntax_while_let() { + let ref_value = &Some(42); + + // not ok + while let Some(_) = ref_value { + break; + } + + // ok + while let &Some(_) = ref_value { + break; + } + while let Some(_) = *ref_value { + break; + } +} + +fn syntax_for() { + let ref_value = &Some(23); + let slice = &[(2, 3), (4, 2)]; + + // not ok + for (_a, _b) in slice.iter() {} + + // ok + for &(_a, _b) in slice.iter() {} +} + +fn syntax_let() { + let ref_value = &(2, 3); + + // not ok + let (_n, _m) = ref_value; + + // ok + let &(_n, _m) = ref_value; + let (_n, _m) = *ref_value; +} + +fn syntax_fn() { + // not ok + fn foo((_a, _b): &(i32, i32)) {} + + // ok + fn foo_ok_1(&(_a, _b): &(i32, i32)) {} +} + +fn syntax_closure() { + fn foo<F>(f: F) + where + F: FnOnce(&(i32, i32)), + { + } + + // not ok + foo(|(_a, _b)| ()); + + // ok + foo(|&(_a, _b)| ()); +} + +fn macro_with_expression() { + macro_rules! matching_macro { + ($e:expr) => { + $e + }; + } + let value = &Some(23); + + // not ok + matching_macro!(match value { + Some(_) => (), + _ => (), + }); + + // ok + matching_macro!(match value { + &Some(_) => (), + _ => (), + }); + matching_macro!(match *value { + Some(_) => (), + _ => (), + }); +} + +fn macro_expansion() { + macro_rules! matching_macro { + ($e:expr) => { + // not ok + match $e { + Some(_) => (), + _ => (), + } + + // ok + match $e { + &Some(_) => (), + _ => (), + } + match *$e { + Some(_) => (), + _ => (), + } + }; + } + + let value = &Some(23); + matching_macro!(value); +} diff --git a/tests/ui/pattern_type_mismatch/syntax.stderr b/tests/ui/pattern_type_mismatch/syntax.stderr new file mode 100644 index 00000000000..110e8421a5e --- /dev/null +++ b/tests/ui/pattern_type_mismatch/syntax.stderr @@ -0,0 +1,78 @@ +error: type of pattern does not match the expression type + --> $DIR/syntax.rs:11:9 + | +LL | Some(_) => (), + | ^^^^^^^ + | + = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings` + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/syntax.rs:30:12 + | +LL | if let Some(_) = ref_value {} + | ^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/syntax.rs:41:15 + | +LL | while let Some(_) = ref_value { + | ^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/syntax.rs:59:9 + | +LL | for (_a, _b) in slice.iter() {} + | ^^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/syntax.rs:69:9 + | +LL | let (_n, _m) = ref_value; + | ^^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/syntax.rs:78:12 + | +LL | fn foo((_a, _b): &(i32, i32)) {} + | ^^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/syntax.rs:92:10 + | +LL | foo(|(_a, _b)| ()); + | ^^^^^^^^ + | + = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/syntax.rs:108:9 + | +LL | Some(_) => (), + | ^^^^^^^ + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: type of pattern does not match the expression type + --> $DIR/syntax.rs:128:17 + | +LL | Some(_) => (), + | ^^^^^^^ +... +LL | matching_macro!(value); + | ----------------------- in this macro invocation + | + = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + +error: aborting due to 9 previous errors + From 55877d7b4a6a2c713412db7b30ef79b2a252956e Mon Sep 17 00:00:00 2001 From: Robert Sedlacek <rs@474.at> Date: Sun, 9 Feb 2020 17:57:35 +0100 Subject: [PATCH 240/526] span_help_and_lint -> span_lint_and_help --- clippy_lints/src/pattern_type_mismatch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs index a07279c92b0..d3f65db1916 100644 --- a/clippy_lints/src/pattern_type_mismatch.rs +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -1,4 +1,4 @@ -use crate::utils::{last_path_segment, span_help_and_lint}; +use crate::utils::{last_path_segment, span_lint_and_help}; use rustc::lint::in_external_macro; use rustc::ty::subst::SubstsRef; use rustc::ty::{AdtDef, FieldDef, Ty, TyKind, VariantDef}; @@ -115,7 +115,7 @@ fn apply_lint<'a, 'tcx>( ) -> bool { let maybe_mismatch = find_first_mismatch(cx, pat, expr_ty, Level::Top); if let Some((span, mutability, level)) = maybe_mismatch { - span_help_and_lint( + span_lint_and_help( cx, PATTERN_TYPE_MISMATCH, span, From 346ee968bbe8925aa7961a3e2c99e7ef84c74623 Mon Sep 17 00:00:00 2001 From: Robert Sedlacek <rs@474.at> Date: Mon, 10 Feb 2020 22:19:19 +0100 Subject: [PATCH 241/526] Adjusted expected STDERR --- tests/ui/pattern_type_mismatch/syntax.stderr | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/pattern_type_mismatch/syntax.stderr b/tests/ui/pattern_type_mismatch/syntax.stderr index 110e8421a5e..5a5186bd4fc 100644 --- a/tests/ui/pattern_type_mismatch/syntax.stderr +++ b/tests/ui/pattern_type_mismatch/syntax.stderr @@ -73,6 +73,7 @@ LL | matching_macro!(value); | ----------------------- in this macro invocation | = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 9 previous errors From 6447507ab150ebd1787ca6af385db49dfdf45978 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 8 Jun 2020 15:10:57 +0200 Subject: [PATCH 242/526] Fix rebase fallout --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/pattern_type_mismatch.rs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4890349999f..3d8ce10aef3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -268,7 +268,7 @@ mod overflow_check_conditional; mod panic_unimplemented; mod partialeq_ne_impl; mod path_buf_push_overwrite; -pub mod pattern_type_mismatch; +mod pattern_type_mismatch; mod precedence; mod ptr; mod ptr_offset_with_cast; diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs index d3f65db1916..a6079a8b5bc 100644 --- a/clippy_lints/src/pattern_type_mismatch.rs +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -1,12 +1,12 @@ use crate::utils::{last_path_segment, span_lint_and_help}; -use rustc::lint::in_external_macro; -use rustc::ty::subst::SubstsRef; -use rustc::ty::{AdtDef, FieldDef, Ty, TyKind, VariantDef}; use rustc_hir::{ intravisit, Body, Expr, ExprKind, FieldPat, FnDecl, HirId, LocalSource, MatchSource, Mutability, Pat, PatKind, QPath, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::{AdtDef, FieldDef, Ty, TyKind, VariantDef}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -120,6 +120,7 @@ fn apply_lint<'a, 'tcx>( PATTERN_TYPE_MISMATCH, span, "type of pattern does not match the expression type", + None, &format!( "{}explicitly match against a `{}` pattern and adjust the enclosed variable bindings", match (deref_possible, level) { From 92ecc53691f3edd67526dca423a2b4083d12a221 Mon Sep 17 00:00:00 2001 From: Robert Sedlacek <rs@474.at> Date: Wed, 1 Jul 2020 15:49:06 +0200 Subject: [PATCH 243/526] Catching up with rustc changes --- clippy_lints/src/pattern_type_mismatch.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs index a6079a8b5bc..fcc9b16068f 100644 --- a/clippy_lints/src/pattern_type_mismatch.rs +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -48,7 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PatternTypeMismatch { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) { if let StmtKind::Local(ref local) = stmt.kind { if let Some(init) = &local.init { - if let Some(init_ty) = cx.tables.node_type_opt(init.hir_id) { + if let Some(init_ty) = cx.tables().node_type_opt(init.hir_id) { let pat = &local.pat; if in_external_macro(cx.sess(), pat.span) { return; @@ -67,7 +67,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PatternTypeMismatch { if let ExprKind::Match(ref expr, arms, source) = expr.kind { match source { MatchSource::Normal | MatchSource::IfLetDesugar { .. } | MatchSource::WhileLetDesugar => { - if let Some(expr_ty) = cx.tables.node_type_opt(expr.hir_id) { + if let Some(expr_ty) = cx.tables().node_type_opt(expr.hir_id) { 'pattern_checks: for arm in arms { let pat = &arm.pat; if in_external_macro(cx.sess(), pat.span) { @@ -93,7 +93,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PatternTypeMismatch { _: Span, hir_id: HirId, ) { - if let Some(fn_sig) = cx.tables.liberated_fn_sigs().get(hir_id) { + if let Some(fn_sig) = cx.tables().liberated_fn_sigs().get(hir_id) { for (param, ty) in body.params.iter().zip(fn_sig.inputs().iter()) { apply_lint(cx, ¶m.pat, ty, DerefPossible::Impossible); } From d617551a6a3830a5324898f2046b97aad8c6067a Mon Sep 17 00:00:00 2001 From: Robert Sedlacek <rs@474.at> Date: Wed, 1 Jul 2020 15:49:46 +0200 Subject: [PATCH 244/526] Expanded lint documentation --- clippy_lints/src/pattern_type_mismatch.rs | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs index fcc9b16068f..9fa5860ba30 100644 --- a/clippy_lints/src/pattern_type_mismatch.rs +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -14,6 +14,22 @@ declare_clippy_lint! { /// **What it does:** Checks for patterns that aren't exact representations of the types /// they are applied to. /// + /// To satisfy this lint, you will have to adjust either the expression that is matched + /// against or the pattern itself, as well as the bindings that are introduced by the + /// adjusted patterns. For matching you will have to either dereference the expression + /// with the `*` operator, or amend the patterns to explicitly match against `&<pattern>` + /// or `&mut <pattern>` depending on the reference mutability. For the bindings you need + /// to use the inverse. You can leave them as plain bindings if you wish for the value + /// to be copied, but you must use `ref mut <variable>` or `ref <variable>` to construct + /// a reference into the matched structure. + /// + /// If you are looking for a way to learn about ownership semantics in more detail, it + /// is recommended to look at IDE options available to you to highlight types, lifetimes + /// and reference semantics in your code. The available tooling would expose these things + /// in a general way even outside of the various pattern matching mechanics. Of course + /// this lint can still be used to highlight areas of interest and ensure a good understanding + /// of ownership semantics. + /// /// **Why is this bad?** It isn't bad in general. But in some contexts it can be desirable /// because it increases ownership hints in the code, and will guard against some changes /// in ownership. @@ -22,6 +38,10 @@ declare_clippy_lint! { /// /// **Example:** /// + /// This example shows the basic adjustments necessary to satisfy the lint. Note how + /// the matched expression is explicitly dereferenced with `*` and the `inner` variable + /// is bound to a shared borrow via `ref inner`. + /// /// ```rust,ignore /// // Bad /// let value = &Some(Box::new(23)); @@ -37,6 +57,25 @@ declare_clippy_lint! { /// None => println!("none"), /// } /// ``` + /// + /// The following example demonstrates one of the advantages of the more verbose style. + /// Note how the second version uses `ref mut a` to explicitly declare `a` a shared mutable + /// borrow, while `b` is simply taken by value. This ensures that the loop body cannot + /// accidentally modify the wrong part of the structure. + /// + /// ```rust,ignore + /// // Bad + /// let mut values = vec![(2, 3), (3, 4)]; + /// for (a, b) in &mut values { + /// *a += *b; + /// } + /// + /// // Good + /// let mut values = vec![(2, 3), (3, 4)]; + /// for &mut (ref mut a, b) in &mut values { + /// *a += b; + /// } + /// ``` pub PATTERN_TYPE_MISMATCH, restriction, "type of pattern does not match the expression type" From aa4bee228f23b3e1a1d91ed3a4606af3c6b60895 Mon Sep 17 00:00:00 2001 From: Robert Sedlacek <rs@474.at> Date: Fri, 3 Jul 2020 18:20:19 +0200 Subject: [PATCH 245/526] LateContext has only one lifetime parameter now --- clippy_lints/src/pattern_type_mismatch.rs | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs index 9fa5860ba30..8587a79e821 100644 --- a/clippy_lints/src/pattern_type_mismatch.rs +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -83,8 +83,8 @@ declare_clippy_lint! { declare_lint_pass!(PatternTypeMismatch => [PATTERN_TYPE_MISMATCH]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PatternTypeMismatch { - fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) { +impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if let StmtKind::Local(ref local) = stmt.kind { if let Some(init) = &local.init { if let Some(init_ty) = cx.tables().node_type_opt(init.hir_id) { @@ -102,7 +102,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PatternTypeMismatch { } } - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Match(ref expr, arms, source) = expr.kind { match source { MatchSource::Normal | MatchSource::IfLetDesugar { .. } | MatchSource::WhileLetDesugar => { @@ -125,7 +125,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PatternTypeMismatch { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, _: intravisit::FnKind<'tcx>, _: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, @@ -146,8 +146,8 @@ enum DerefPossible { Impossible, } -fn apply_lint<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn apply_lint<'tcx>( + cx: &LateContext<'tcx>, pat: &Pat<'_>, expr_ty: Ty<'tcx>, deref_possible: DerefPossible, @@ -185,8 +185,8 @@ enum Level { } #[allow(rustc::usage_of_ty_tykind)] -fn find_first_mismatch<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn find_first_mismatch<'tcx>( + cx: &LateContext<'tcx>, pat: &Pat<'_>, ty: Ty<'tcx>, level: Level, @@ -259,8 +259,8 @@ fn get_variant<'a>(adt_def: &'a AdtDef, qpath: &QPath<'_>) -> Option<&'a Variant None } -fn find_first_mismatch_in_tuple<'a, 'tcx, I>( - cx: &LateContext<'a, 'tcx>, +fn find_first_mismatch_in_tuple<'tcx, I>( + cx: &LateContext<'tcx>, pats: &[&Pat<'_>], ty_iter_src: I, ) -> Option<(Span, Mutability, Level)> @@ -284,8 +284,8 @@ where None } -fn find_first_mismatch_in_struct<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn find_first_mismatch_in_struct<'tcx>( + cx: &LateContext<'tcx>, field_pats: &[FieldPat<'_>], field_defs: &[FieldDef], substs_ref: SubstsRef<'tcx>, From c0fd452840c7cc53b3396268f62ed2a0a2e8fef7 Mon Sep 17 00:00:00 2001 From: Robert Sedlacek <rs@474.at> Date: Fri, 3 Jul 2020 18:23:36 +0200 Subject: [PATCH 246/526] fmt fix --- clippy_lints/src/pattern_type_mismatch.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs index 8587a79e821..a49dc87c0b4 100644 --- a/clippy_lints/src/pattern_type_mismatch.rs +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -146,12 +146,7 @@ enum DerefPossible { Impossible, } -fn apply_lint<'tcx>( - cx: &LateContext<'tcx>, - pat: &Pat<'_>, - expr_ty: Ty<'tcx>, - deref_possible: DerefPossible, -) -> bool { +fn apply_lint<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>, expr_ty: Ty<'tcx>, deref_possible: DerefPossible) -> bool { let maybe_mismatch = find_first_mismatch(cx, pat, expr_ty, Level::Top); if let Some((span, mutability, level)) = maybe_mismatch { span_lint_and_help( From bf48a2d50d82cccac58d7c4c73700eaf66926aee Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 5 Mar 2020 10:35:05 -0800 Subject: [PATCH 247/526] Lint for if let Some(x) = ... instead of Option::map_or --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 + clippy_lints/src/option_if_let_else.rs | 202 +++++++++++++++++++++++++ src/lintlist/mod.rs | 7 + tests/ui/option_if_let_else.fixed | 48 ++++++ tests/ui/option_if_let_else.rs | 56 +++++++ tests/ui/option_if_let_else.stderr | 62 ++++++++ 7 files changed, 381 insertions(+) create mode 100644 clippy_lints/src/option_if_let_else.rs create mode 100644 tests/ui/option_if_let_else.fixed create mode 100644 tests/ui/option_if_let_else.rs create mode 100644 tests/ui/option_if_let_else.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index ed8f16e65bb..1a081bb85fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1577,6 +1577,7 @@ Released 2018-09-13 [`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref [`option_as_ref_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref [`option_env_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_env_unwrap +[`option_if_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_if_let_else [`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn [`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1d5be893ffb..cd91e7ceb32 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -264,6 +264,7 @@ mod non_copy_const; mod non_expressive_names; mod open_options; mod option_env_unwrap; +mod option_if_let_else; mod overflow_check_conditional; mod panic_unimplemented; mod partialeq_ne_impl; @@ -734,6 +735,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &non_expressive_names::SIMILAR_NAMES, &open_options::NONSENSICAL_OPEN_OPTIONS, &option_env_unwrap::OPTION_ENV_UNWRAP, + &option_if_let_else::OPTION_IF_LET_ELSE, &overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, &panic_unimplemented::PANIC, &panic_unimplemented::PANIC_PARAMS, @@ -1052,6 +1054,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default()); store.register_late_pass(|| box unnamed_address::UnnamedAddress); store.register_late_pass(|| box dereference::Dereferencing); + store.register_late_pass(|| box option_if_let_else::OptionIfLetElse); store.register_late_pass(|| box future_not_send::FutureNotSend); store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls); store.register_late_pass(|| box if_let_mutex::IfLetMutex); @@ -1369,6 +1372,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES), LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS), LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP), + LintId::of(&option_if_let_else::OPTION_IF_LET_ELSE), LintId::of(&overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), LintId::of(&panic_unimplemented::PANIC_PARAMS), LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL), @@ -1517,6 +1521,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES), + LintId::of(&option_if_let_else::OPTION_IF_LET_ELSE), LintId::of(&panic_unimplemented::PANIC_PARAMS), LintId::of(&ptr::CMP_NULL), LintId::of(&ptr::PTR_ARG), diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs new file mode 100644 index 00000000000..f092f1297c1 --- /dev/null +++ b/clippy_lints/src/option_if_let_else.rs @@ -0,0 +1,202 @@ +use crate::utils::sugg::Sugg; +use crate::utils::{match_type, paths, span_lint_and_sugg}; +use if_chain::if_chain; + +use rustc_errors::Applicability; +use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; +use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +use std::marker::PhantomData; + +declare_clippy_lint! { + /// **What it does:** + /// Lints usage of `if let Some(v) = ... { y } else { x }` which is more + /// idiomatically done with `Option::map_or` (if the else bit is a simple + /// expression) or `Option::map_or_else` (if the else bit is a longer + /// block). + /// + /// **Why is this bad?** + /// Using the dedicated functions of the Option type is clearer and + /// more concise than an if let expression. + /// + /// **Known problems:** + /// This lint uses whether the block is just an expression or if it has + /// more statements to decide whether to use `Option::map_or` or + /// `Option::map_or_else`. If you have a single expression which calls + /// an expensive function, then it would be more efficient to use + /// `Option::map_or_else`, but this lint would suggest `Option::map_or`. + /// + /// Also, this lint uses a deliberately conservative metric for checking + /// if the inside of either body contains breaks or continues which will + /// cause it to not suggest a fix if either block contains a loop with + /// continues or breaks contained within the loop. + /// + /// **Example:** + /// + /// ```rust + /// # let optional: Option<u32> = Some(0); + /// let _ = if let Some(foo) = optional { + /// foo + /// } else { + /// 5 + /// }; + /// let _ = if let Some(foo) = optional { + /// foo + /// } else { + /// let y = do_complicated_function(); + /// y*y + /// }; + /// ``` + /// + /// should be + /// + /// ```rust + /// # let optional: Option<u32> = Some(0); + /// let _ = optional.map_or(5, |foo| foo); + /// let _ = optional.map_or_else(||{ + /// let y = do_complicated_function; + /// y*y + /// }, |foo| foo); + /// ``` + pub OPTION_IF_LET_ELSE, + style, + "reimplementation of Option::map_or" +} + +declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]); + +/// Returns true iff the given expression is the result of calling Result::ok +fn is_result_ok(cx: &LateContext<'_, '_>, expr: &'_ Expr<'_>) -> bool { + if_chain! { + if let ExprKind::MethodCall(ref path, _, &[ref receiver]) = &expr.kind; + if path.ident.name.to_ident_string() == "ok"; + if match_type(cx, &cx.tables.expr_ty(&receiver), &paths::RESULT); + then { + true + } else { + false + } + } +} + +/// A struct containing information about occurences of the +/// `if let Some(..) = .. else` construct that this lint detects. +struct OptionIfLetElseOccurence { + option: String, + method_sugg: String, + some_expr: String, + none_expr: String, +} + +struct ReturnBreakContinueVisitor<'tcx> { + seen_return_break_continue: bool, + phantom_data: PhantomData<&'tcx bool>, +} +impl<'tcx> ReturnBreakContinueVisitor<'tcx> { + fn new() -> ReturnBreakContinueVisitor<'tcx> { + ReturnBreakContinueVisitor { + seen_return_break_continue: false, + phantom_data: PhantomData, + } + } +} +impl<'tcx> Visitor<'tcx> for ReturnBreakContinueVisitor<'tcx> { + type Map = Map<'tcx>; + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } + + fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { + if self.seen_return_break_continue { + // No need to look farther if we've already seen one of them + return; + } + match &ex.kind { + ExprKind::Ret(..) | ExprKind::Break(..) | ExprKind::Continue(..) => { + self.seen_return_break_continue = true; + }, + // Something special could be done here to handle while or for loop + // desugaring, as this will detect a break if there's a while loop + // or a for loop inside the expression. + _ => { + rustc_hir::intravisit::walk_expr(self, ex); + }, + } + } +} + +fn contains_return_break_continue<'tcx>(expression: &'tcx Expr<'tcx>) -> bool { + let mut recursive_visitor: ReturnBreakContinueVisitor<'tcx> = ReturnBreakContinueVisitor::new(); + recursive_visitor.visit_expr(expression); + recursive_visitor.seen_return_break_continue +} + +/// If this expression is the option if let/else construct we're detecting, then +/// this function returns an OptionIfLetElseOccurence struct with details if +/// this construct is found, or None if this construct is not found. +fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -> Option<OptionIfLetElseOccurence> { + //(String, String, String, String)> { + if_chain! { + if let ExprKind::Match(let_body, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind; + if arms.len() == 2; + if match_type(cx, &cx.tables.expr_ty(let_body), &paths::OPTION); + if !is_result_ok(cx, let_body); // Don't lint on Result::ok because a different lint does it already + if let PatKind::TupleStruct(_, &[inner_pat], _) = &arms[0].pat.kind; + if let PatKind::Binding(_, _, id, _) = &inner_pat.kind; + if !contains_return_break_continue(arms[0].body); + if !contains_return_break_continue(arms[1].body); + then { + let some_body = if let ExprKind::Block(Block { stmts: statements, expr: Some(expr), .. }, _) + = &arms[0].body.kind { + if let &[] = &statements { + expr + } else { + &arms[0].body + } + } else { + return None; + }; + let (none_body, method_sugg) = if let ExprKind::Block(Block { stmts: statements, expr: Some(expr), .. }, _) + = &arms[1].body.kind { + if let &[] = &statements { + (expr, "map_or") + } else { + (&arms[1].body, "map_or_else") + } + } else { + return None; + }; + let capture_name = id.name.to_ident_string(); + Some(OptionIfLetElseOccurence { + option: format!("{}", Sugg::hir(cx, let_body, "..")), + method_sugg: format!("{}", method_sugg), + some_expr: format!("|{}| {}", capture_name, Sugg::hir(cx, some_body, "..")), + none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")) + }) + } else { + None + } + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + if let Some(detection) = detect_option_if_let_else(cx, expr) { + span_lint_and_sugg( + cx, + OPTION_IF_LET_ELSE, + expr.span, + format!("use Option::{} instead of an if let/else", detection.method_sugg).as_str(), + "try", + format!( + "{}.{}({}, {})", + detection.option, detection.method_sugg, detection.none_expr, detection.some_expr + ), + Applicability::MachineApplicable, + ); + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 6402efc2521..b499d565fa7 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1620,6 +1620,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "option_env_unwrap", }, + Lint { + name: "option_if_let_else", + group: "style", + desc: "reimplementation of Option::map_or", + deprecation: None, + module: "option_if_let_else", + }, Lint { name: "option_map_or_none", group: "style", diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed new file mode 100644 index 00000000000..3aa895120d1 --- /dev/null +++ b/tests/ui/option_if_let_else.fixed @@ -0,0 +1,48 @@ +// run-rustfix +#![warn(clippy::option_if_let_else)] + +fn bad1(string: Option<&str>) -> (bool, &str) { + string.map_or((false, "hello"), |x| (true, x)) +} + +fn longer_body(arg: Option<u32>) -> u32 { + arg.map_or(13, |x| { + let y = x * x; + y * y + }) +} + +fn test_map_or_else(arg: Option<u32>) { + let _ = arg.map_or_else(|| { + let mut y = 1; + y = (y + 2 / y) / 2; + y = (y + 2 / y) / 2; + y + }, |x| x * x * x * x); +} + +fn negative_tests(arg: Option<u32>) -> u32 { + let _ = if let Some(13) = arg { "unlucky" } else { "lucky" }; + for _ in 0..10 { + let _ = if let Some(x) = arg { + x + } else { + continue; + }; + } + let _ = if let Some(x) = arg { + return x; + } else { + 5 + }; + 7 +} + +fn main() { + let optional = Some(5); + let _ = optional.map_or(5, |x| x + 2); + let _ = bad1(None); + let _ = longer_body(None); + test_map_or_else(None); + let _ = negative_tests(None); +} diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs new file mode 100644 index 00000000000..7d029b0bcf4 --- /dev/null +++ b/tests/ui/option_if_let_else.rs @@ -0,0 +1,56 @@ +// run-rustfix +#![warn(clippy::option_if_let_else)] + +fn bad1(string: Option<&str>) -> (bool, &str) { + if let Some(x) = string { + (true, x) + } else { + (false, "hello") + } +} + +fn longer_body(arg: Option<u32>) -> u32 { + if let Some(x) = arg { + let y = x * x; + y * y + } else { + 13 + } +} + +fn test_map_or_else(arg: Option<u32>) { + let _ = if let Some(x) = arg { + x * x * x * x + } else { + let mut y = 1; + y = (y + 2 / y) / 2; + y = (y + 2 / y) / 2; + y + }; +} + +fn negative_tests(arg: Option<u32>) -> u32 { + let _ = if let Some(13) = arg { "unlucky" } else { "lucky" }; + for _ in 0..10 { + let _ = if let Some(x) = arg { + x + } else { + continue; + }; + } + let _ = if let Some(x) = arg { + return x; + } else { + 5 + }; + 7 +} + +fn main() { + let optional = Some(5); + let _ = if let Some(x) = optional { x + 2 } else { 5 }; + let _ = bad1(None); + let _ = longer_body(None); + test_map_or_else(None); + let _ = negative_tests(None); +} diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr new file mode 100644 index 00000000000..d6cf0836733 --- /dev/null +++ b/tests/ui/option_if_let_else.stderr @@ -0,0 +1,62 @@ +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:5:5 + | +LL | / if let Some(x) = string { +LL | | (true, x) +LL | | } else { +LL | | (false, "hello") +LL | | } + | |_____^ help: try: `string.map_or((false, "hello"), |x| (true, x))` + | + = note: `-D clippy::option-if-let-else` implied by `-D warnings` + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:13:5 + | +LL | / if let Some(x) = arg { +LL | | let y = x * x; +LL | | y * y +LL | | } else { +LL | | 13 +LL | | } + | |_____^ + | +help: try + | +LL | arg.map_or(13, |x| { +LL | let y = x * x; +LL | y * y +LL | }) + | + +error: use Option::map_or_else instead of an if let/else + --> $DIR/option_if_let_else.rs:22:13 + | +LL | let _ = if let Some(x) = arg { + | _____________^ +LL | | x * x * x * x +LL | | } else { +LL | | let mut y = 1; +... | +LL | | y +LL | | }; + | |_____^ + | +help: try + | +LL | let _ = arg.map_or_else(|| { +LL | let mut y = 1; +LL | y = (y + 2 / y) / 2; +LL | y = (y + 2 / y) / 2; +LL | y +LL | }, |x| x * x * x * x); + | + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:51:13 + | +LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` + +error: aborting due to 4 previous errors + From 82f8d4d6f1645dd08b107c3ead9155412637739b Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sat, 25 Apr 2020 08:32:33 -0700 Subject: [PATCH 248/526] Stop linting on macros and correctly use braces for constructs --- clippy_lints/src/option_if_let_else.rs | 23 ++++++++++++++++++++--- tests/ui/option_if_let_else.fixed | 7 +++++++ tests/ui/option_if_let_else.rs | 11 +++++++++++ tests/ui/option_if_let_else.stderr | 19 +++++++++++++++---- 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index f092f1297c1..1edec1cad6e 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -1,3 +1,4 @@ +use crate::utils; use crate::utils::sugg::Sugg; use crate::utils::{match_type, paths, span_lint_and_sugg}; use if_chain::if_chain; @@ -89,6 +90,7 @@ struct OptionIfLetElseOccurence { method_sugg: String, some_expr: String, none_expr: String, + wrap_braces: bool, } struct ReturnBreakContinueVisitor<'tcx> { @@ -140,6 +142,7 @@ fn contains_return_break_continue<'tcx>(expression: &'tcx Expr<'tcx>) -> bool { fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -> Option<OptionIfLetElseOccurence> { //(String, String, String, String)> { if_chain! { + // if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly if let ExprKind::Match(let_body, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind; if arms.len() == 2; if match_type(cx, &cx.tables.expr_ty(let_body), &paths::OPTION); @@ -170,11 +173,23 @@ fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) - return None; }; let capture_name = id.name.to_ident_string(); + let wrap_braces = utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| { + if_chain! { + if let Some(Expr { kind: ExprKind::Match(condition, arms, MatchSource::IfDesugar{contains_else_clause: true}|MatchSource::IfLetDesugar{contains_else_clause: true}), .. } ) = parent.expr; + if expr.hir_id == arms[1].body.hir_id; + then { + true + } else { + false + } + } + }); Some(OptionIfLetElseOccurence { option: format!("{}", Sugg::hir(cx, let_body, "..")), method_sugg: format!("{}", method_sugg), some_expr: format!("|{}| {}", capture_name, Sugg::hir(cx, some_body, "..")), - none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")) + none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")), + wrap_braces, }) } else { None @@ -192,8 +207,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse { format!("use Option::{} instead of an if let/else", detection.method_sugg).as_str(), "try", format!( - "{}.{}({}, {})", - detection.option, detection.method_sugg, detection.none_expr, detection.some_expr + "{}{}.{}({}, {}){}", + if detection.wrap_braces { "{ " } else { "" }, + detection.option, detection.method_sugg, detection.none_expr, detection.some_expr, + if detection.wrap_braces { " }" } else { "" }, ), Applicability::MachineApplicable, ); diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index 3aa895120d1..343e099b2b7 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -5,6 +5,12 @@ fn bad1(string: Option<&str>) -> (bool, &str) { string.map_or((false, "hello"), |x| (true, x)) } +fn bad2(string: Option<&str>) -> Option<(bool, &str)> { + if string.is_none() { + None + } else { string.map_or(Some((false, "")), |x| Some((true, x))) } +} + fn longer_body(arg: Option<u32>) -> u32 { arg.map_or(13, |x| { let y = x * x; @@ -42,6 +48,7 @@ fn main() { let optional = Some(5); let _ = optional.map_or(5, |x| x + 2); let _ = bad1(None); + let _ = bad2(None); let _ = longer_body(None); test_map_or_else(None); let _ = negative_tests(None); diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 7d029b0bcf4..b0c203f0637 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -9,6 +9,16 @@ fn bad1(string: Option<&str>) -> (bool, &str) { } } +fn bad2(string: Option<&str>) -> Option<(bool, &str)> { + if string.is_none() { + None + } else if let Some(x) = string { + Some((true, x)) + } else { + Some((false, "")) + } +} + fn longer_body(arg: Option<u32>) -> u32 { if let Some(x) = arg { let y = x * x; @@ -50,6 +60,7 @@ fn main() { let optional = Some(5); let _ = if let Some(x) = optional { x + 2 } else { 5 }; let _ = bad1(None); + let _ = bad2(None); let _ = longer_body(None); test_map_or_else(None); let _ = negative_tests(None); diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index d6cf0836733..656cfb2f62a 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -11,7 +11,18 @@ LL | | } = note: `-D clippy::option-if-let-else` implied by `-D warnings` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:13:5 + --> $DIR/option_if_let_else.rs:15:12 + | +LL | } else if let Some(x) = string { + | ____________^ +LL | | Some((true, x)) +LL | | } else { +LL | | Some((false, "")) +LL | | } + | |_____^ help: try: `{ string.map_or(Some((false, "")), |x| Some((true, x))) }` + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:23:5 | LL | / if let Some(x) = arg { LL | | let y = x * x; @@ -30,7 +41,7 @@ LL | }) | error: use Option::map_or_else instead of an if let/else - --> $DIR/option_if_let_else.rs:22:13 + --> $DIR/option_if_let_else.rs:32:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -53,10 +64,10 @@ LL | }, |x| x * x * x * x); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:51:13 + --> $DIR/option_if_let_else.rs:61:13 | LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors From b85796fe3613e20a4af21933783a3d993bb8d7ad Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sat, 25 Apr 2020 09:08:23 -0700 Subject: [PATCH 249/526] Properly parenthesize to avoid operator precedence errors --- clippy_lints/src/option_if_let_else.rs | 25 ++++++++++++++++++++++--- tests/ui/option_if_let_else.fixed | 9 +++++++-- tests/ui/option_if_let_else.rs | 13 +++++++++++-- tests/ui/option_if_let_else.stderr | 16 +++++++++++++--- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 1edec1cad6e..66971ee0262 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -175,7 +175,12 @@ fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) - let capture_name = id.name.to_ident_string(); let wrap_braces = utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| { if_chain! { - if let Some(Expr { kind: ExprKind::Match(condition, arms, MatchSource::IfDesugar{contains_else_clause: true}|MatchSource::IfLetDesugar{contains_else_clause: true}), .. } ) = parent.expr; + if let Some(Expr { kind: ExprKind::Match( + _, + arms, + MatchSource::IfDesugar{contains_else_clause: true} + | MatchSource::IfLetDesugar{contains_else_clause: true}), + .. } ) = parent.expr; if expr.hir_id == arms[1].body.hir_id; then { true @@ -184,8 +189,19 @@ fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) - } } }); + let parens_around_option = match &let_body.kind { + ExprKind::Call(..) + | ExprKind::MethodCall(..) + | ExprKind::Loop(..) + | ExprKind::Match(..) + | ExprKind::Block(..) + | ExprKind::Field(..) + | ExprKind::Path(_) + => false, + _ => true, + }; Some(OptionIfLetElseOccurence { - option: format!("{}", Sugg::hir(cx, let_body, "..")), + option: format!("{}{}{}", if parens_around_option { "(" } else { "" }, Sugg::hir(cx, let_body, ".."), if parens_around_option { ")" } else { "" }), method_sugg: format!("{}", method_sugg), some_expr: format!("|{}| {}", capture_name, Sugg::hir(cx, some_body, "..")), none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")), @@ -209,7 +225,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse { format!( "{}{}.{}({}, {}){}", if detection.wrap_braces { "{ " } else { "" }, - detection.option, detection.method_sugg, detection.none_expr, detection.some_expr, + detection.option, + detection.method_sugg, + detection.none_expr, + detection.some_expr, if detection.wrap_braces { " }" } else { "" }, ), Applicability::MachineApplicable, diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index 343e099b2b7..80b162714ac 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -5,12 +5,16 @@ fn bad1(string: Option<&str>) -> (bool, &str) { string.map_or((false, "hello"), |x| (true, x)) } -fn bad2(string: Option<&str>) -> Option<(bool, &str)> { +fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> { if string.is_none() { None } else { string.map_or(Some((false, "")), |x| Some((true, x))) } } +fn unop_bad(string: &Option<&str>) -> usize { + (*string).map_or(0, |s| s.len()) +} + fn longer_body(arg: Option<u32>) -> u32 { arg.map_or(13, |x| { let y = x * x; @@ -48,7 +52,8 @@ fn main() { let optional = Some(5); let _ = optional.map_or(5, |x| x + 2); let _ = bad1(None); - let _ = bad2(None); + let _ = else_if_option(None); + let _ = unop_bad(&None); let _ = longer_body(None); test_map_or_else(None); let _ = negative_tests(None); diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index b0c203f0637..7c43fbea373 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -9,7 +9,7 @@ fn bad1(string: Option<&str>) -> (bool, &str) { } } -fn bad2(string: Option<&str>) -> Option<(bool, &str)> { +fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> { if string.is_none() { None } else if let Some(x) = string { @@ -19,6 +19,14 @@ fn bad2(string: Option<&str>) -> Option<(bool, &str)> { } } +fn unop_bad(string: &Option<&str>) -> usize { + if let Some(s) = *string { + s.len() + } else { + 0 + } +} + fn longer_body(arg: Option<u32>) -> u32 { if let Some(x) = arg { let y = x * x; @@ -60,7 +68,8 @@ fn main() { let optional = Some(5); let _ = if let Some(x) = optional { x + 2 } else { 5 }; let _ = bad1(None); - let _ = bad2(None); + let _ = else_if_option(None); + let _ = unop_bad(&None); let _ = longer_body(None); test_map_or_else(None); let _ = negative_tests(None); diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index 656cfb2f62a..b932fe59759 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -24,6 +24,16 @@ LL | | } error: use Option::map_or instead of an if let/else --> $DIR/option_if_let_else.rs:23:5 | +LL | / if let Some(s) = *string { +LL | | s.len() +LL | | } else { +LL | | 0 +LL | | } + | |_____^ help: try: `(*string).map_or(0, |s| s.len())` + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:31:5 + | LL | / if let Some(x) = arg { LL | | let y = x * x; LL | | y * y @@ -41,7 +51,7 @@ LL | }) | error: use Option::map_or_else instead of an if let/else - --> $DIR/option_if_let_else.rs:32:13 + --> $DIR/option_if_let_else.rs:40:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -64,10 +74,10 @@ LL | }, |x| x * x * x * x); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:61:13 + --> $DIR/option_if_let_else.rs:69:13 | LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors From 88c8afdddff07adeff4c87431cbe8bc630a36d68 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sat, 9 May 2020 20:20:57 -0700 Subject: [PATCH 250/526] Handle ref, mut, &, and &mut on the option --- clippy_lints/src/option_if_let_else.rs | 28 +++++--- tests/ui/option_if_let_else.fixed | 20 +++++- tests/ui/option_if_let_else.rs | 36 ++++++++-- tests/ui/option_if_let_else.stderr | 99 +++++++++++++++++++++++--- 4 files changed, 158 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 66971ee0262..4e501f4ca02 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -140,18 +140,24 @@ fn contains_return_break_continue<'tcx>(expression: &'tcx Expr<'tcx>) -> bool { /// this function returns an OptionIfLetElseOccurence struct with details if /// this construct is found, or None if this construct is not found. fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -> Option<OptionIfLetElseOccurence> { - //(String, String, String, String)> { if_chain! { - // if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly + if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly if let ExprKind::Match(let_body, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind; if arms.len() == 2; - if match_type(cx, &cx.tables.expr_ty(let_body), &paths::OPTION); + // if type_is_option(cx, &cx.tables.expr_ty(let_body).kind); if !is_result_ok(cx, let_body); // Don't lint on Result::ok because a different lint does it already - if let PatKind::TupleStruct(_, &[inner_pat], _) = &arms[0].pat.kind; - if let PatKind::Binding(_, _, id, _) = &inner_pat.kind; + if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind; + if utils::match_qpath(struct_qpath, &paths::OPTION_SOME); + if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind; if !contains_return_break_continue(arms[0].body); if !contains_return_break_continue(arms[1].body); then { + let (capture_mut, capture_ref, capture_ref_mut) = match bind_annotation { + BindingAnnotation::Unannotated => (false, false, false), + BindingAnnotation::Mutable => (true, false, false), + BindingAnnotation::Ref => (false, true, false), + BindingAnnotation::RefMut => (false, false, true), + }; let some_body = if let ExprKind::Block(Block { stmts: statements, expr: Some(expr), .. }, _) = &arms[0].body.kind { if let &[] = &statements { @@ -189,7 +195,7 @@ fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) - } } }); - let parens_around_option = match &let_body.kind { + let (parens_around_option, as_ref, as_mut, let_body) = match &let_body.kind { ExprKind::Call(..) | ExprKind::MethodCall(..) | ExprKind::Loop(..) @@ -197,13 +203,15 @@ fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) - | ExprKind::Block(..) | ExprKind::Field(..) | ExprKind::Path(_) - => false, - _ => true, + => (false, capture_ref, capture_ref_mut, let_body), + ExprKind::Unary(UnOp::UnDeref, expr) => (false, capture_ref, capture_ref_mut, expr), + ExprKind::AddrOf(_, mutability, expr) => (false, mutability == &Mutability::Not, mutability == &Mutability::Mut, expr), + _ => (true, capture_ref, capture_ref_mut, let_body), }; Some(OptionIfLetElseOccurence { - option: format!("{}{}{}", if parens_around_option { "(" } else { "" }, Sugg::hir(cx, let_body, ".."), if parens_around_option { ")" } else { "" }), + option: format!("{}{}{}{}", if parens_around_option { "(" } else { "" }, Sugg::hir(cx, let_body, ".."), if parens_around_option { ")" } else { "" }, if as_mut { ".as_mut()" } else if as_ref { ".as_ref()" } else { "" }), method_sugg: format!("{}", method_sugg), - some_expr: format!("|{}| {}", capture_name, Sugg::hir(cx, some_body, "..")), + some_expr: format!("|{}{}{}| {}", if false { "ref " } else { "" }, if capture_mut { "mut " } else { "" }, capture_name, Sugg::hir(cx, some_body, "..")), none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")), wrap_braces, }) diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index 80b162714ac..695a460cc4e 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -11,8 +11,22 @@ fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> { } else { string.map_or(Some((false, "")), |x| Some((true, x))) } } -fn unop_bad(string: &Option<&str>) -> usize { - (*string).map_or(0, |s| s.len()) +fn unop_bad(string: &Option<&str>, mut num: Option<i32>) { + let _ = string.map_or(0, |s| s.len()); + let _ = num.as_ref().map_or(&0, |s| s); + let _ = num.as_mut().map_or(&mut 0, |s| { + *s += 1; + s + }); + let _ = num.as_ref().map_or(&0, |s| s); + let _ = num.map_or(0, |mut s| { + s += 1; + s + }); + let _ = num.as_mut().map_or(&mut 0, |s| { + *s += 1; + s + }); } fn longer_body(arg: Option<u32>) -> u32 { @@ -53,7 +67,7 @@ fn main() { let _ = optional.map_or(5, |x| x + 2); let _ = bad1(None); let _ = else_if_option(None); - let _ = unop_bad(&None); + unop_bad(&None, None); let _ = longer_body(None); test_map_or_else(None); let _ = negative_tests(None); diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 7c43fbea373..6f9d506d347 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -19,12 +19,40 @@ fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> { } } -fn unop_bad(string: &Option<&str>) -> usize { - if let Some(s) = *string { +fn unop_bad(string: &Option<&str>, mut num: Option<i32>) { + let _ = if let Some(s) = *string { s.len() } else { 0 - } + }; + let _ = if let Some(s) = &num { + s + } else { + &0 + }; + let _ = if let Some(s) = &mut num { + *s += 1; + s + } else { + &mut 0 + }; + let _ = if let Some(ref s) = num { + s + } else { + &0 + }; + let _ = if let Some(mut s) = num { + s += 1; + s + } else { + 0 + }; + let _ = if let Some(ref mut s) = num { + *s += 1; + s + } else { + &mut 0 + }; } fn longer_body(arg: Option<u32>) -> u32 { @@ -69,7 +97,7 @@ fn main() { let _ = if let Some(x) = optional { x + 2 } else { 5 }; let _ = bad1(None); let _ = else_if_option(None); - let _ = unop_bad(&None); + unop_bad(&None, None); let _ = longer_body(None); test_map_or_else(None); let _ = negative_tests(None); diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index b932fe59759..9240d3edb27 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -22,17 +22,100 @@ LL | | } | |_____^ help: try: `{ string.map_or(Some((false, "")), |x| Some((true, x))) }` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:23:5 + --> $DIR/option_if_let_else.rs:23:13 | -LL | / if let Some(s) = *string { +LL | let _ = if let Some(s) = *string { + | _____________^ LL | | s.len() LL | | } else { LL | | 0 -LL | | } - | |_____^ help: try: `(*string).map_or(0, |s| s.len())` +LL | | }; + | |_____^ help: try: `string.map_or(0, |s| s.len())` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:31:5 + --> $DIR/option_if_let_else.rs:28:13 + | +LL | let _ = if let Some(s) = &num { + | _____________^ +LL | | s +LL | | } else { +LL | | &0 +LL | | }; + | |_____^ help: try: `num.as_ref().map_or(&0, |s| s)` + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:33:13 + | +LL | let _ = if let Some(s) = &mut num { + | _____________^ +LL | | *s += 1; +LL | | s +LL | | } else { +LL | | &mut 0 +LL | | }; + | |_____^ + | +help: try + | +LL | let _ = num.as_mut().map_or(&mut 0, |s| { +LL | *s += 1; +LL | s +LL | }); + | + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:39:13 + | +LL | let _ = if let Some(ref s) = num { + | _____________^ +LL | | s +LL | | } else { +LL | | &0 +LL | | }; + | |_____^ help: try: `num.as_ref().map_or(&0, |s| s)` + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:44:13 + | +LL | let _ = if let Some(mut s) = num { + | _____________^ +LL | | s += 1; +LL | | s +LL | | } else { +LL | | 0 +LL | | }; + | |_____^ + | +help: try + | +LL | let _ = num.map_or(0, |mut s| { +LL | s += 1; +LL | s +LL | }); + | + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:50:13 + | +LL | let _ = if let Some(ref mut s) = num { + | _____________^ +LL | | *s += 1; +LL | | s +LL | | } else { +LL | | &mut 0 +LL | | }; + | |_____^ + | +help: try + | +LL | let _ = num.as_mut().map_or(&mut 0, |s| { +LL | *s += 1; +LL | s +LL | }); + | + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:59:5 | LL | / if let Some(x) = arg { LL | | let y = x * x; @@ -51,7 +134,7 @@ LL | }) | error: use Option::map_or_else instead of an if let/else - --> $DIR/option_if_let_else.rs:40:13 + --> $DIR/option_if_let_else.rs:68:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -74,10 +157,10 @@ LL | }, |x| x * x * x * x); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:69:13 + --> $DIR/option_if_let_else.rs:97:13 | LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` -error: aborting due to 6 previous errors +error: aborting due to 11 previous errors From f73b455b99694fbc5ddec38317f705f546729db2 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sat, 9 May 2020 20:44:56 -0700 Subject: [PATCH 251/526] Refactoring --- clippy_lints/src/option_if_let_else.rs | 170 +++++++++++++++---------- tests/ui/option_if_let_else.rs | 18 +-- tests/ui/option_if_let_else.stderr | 43 ++----- 3 files changed, 123 insertions(+), 108 deletions(-) diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 4e501f4ca02..208aa550765 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -5,7 +5,7 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, PatKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -69,17 +69,12 @@ declare_clippy_lint! { declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]); -/// Returns true iff the given expression is the result of calling Result::ok +/// Returns true iff the given expression is the result of calling `Result::ok` fn is_result_ok(cx: &LateContext<'_, '_>, expr: &'_ Expr<'_>) -> bool { - if_chain! { - if let ExprKind::MethodCall(ref path, _, &[ref receiver]) = &expr.kind; - if path.ident.name.to_ident_string() == "ok"; - if match_type(cx, &cx.tables.expr_ty(&receiver), &paths::RESULT); - then { - true - } else { - false - } + if let ExprKind::MethodCall(ref path, _, &[ref receiver]) = &expr.kind { + path.ident.name.to_ident_string() == "ok" && match_type(cx, &cx.tables.expr_ty(&receiver), &paths::RESULT) + } else { + false } } @@ -136,66 +131,108 @@ fn contains_return_break_continue<'tcx>(expression: &'tcx Expr<'tcx>) -> bool { recursive_visitor.seen_return_break_continue } +/// Extracts the body of a given arm. If the arm contains only an expression, +/// then it returns the expression. Otherwise, it returns the entire block +fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> { + if let ExprKind::Block( + Block { + stmts: statements, + expr: Some(expr), + .. + }, + _, + ) = &arm.body.kind + { + if let [] = statements { + Some(&expr) + } else { + Some(&arm.body) + } + } else { + None + } +} + +/// If this is the else body of an if/else expression, then we need to wrap +/// it in curcly braces. Otherwise, we don't. +fn should_wrap_in_braces(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| { + if let Some(Expr { + kind: + ExprKind::Match( + _, + arms, + MatchSource::IfDesugar { + contains_else_clause: true, + } + | MatchSource::IfLetDesugar { + contains_else_clause: true, + }, + ), + .. + }) = parent.expr + { + expr.hir_id == arms[1].body.hir_id + } else { + false + } + }) +} + +fn format_option_in_sugg( + cx: &LateContext<'_, '_>, + cond_expr: &Expr<'_>, + parens_around_option: bool, + as_ref: bool, + as_mut: bool, +) -> String { + format!( + "{}{}{}{}", + if parens_around_option { "(" } else { "" }, + Sugg::hir(cx, cond_expr, ".."), + if parens_around_option { ")" } else { "" }, + if as_mut { + ".as_mut()" + } else if as_ref { + ".as_ref()" + } else { + "" + } + ) +} + /// If this expression is the option if let/else construct we're detecting, then -/// this function returns an OptionIfLetElseOccurence struct with details if +/// this function returns an `OptionIfLetElseOccurence` struct with details if /// this construct is found, or None if this construct is not found. fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -> Option<OptionIfLetElseOccurence> { if_chain! { if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly - if let ExprKind::Match(let_body, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind; + if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind; if arms.len() == 2; - // if type_is_option(cx, &cx.tables.expr_ty(let_body).kind); - if !is_result_ok(cx, let_body); // Don't lint on Result::ok because a different lint does it already + if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind; if utils::match_qpath(struct_qpath, &paths::OPTION_SOME); if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind; if !contains_return_break_continue(arms[0].body); if !contains_return_break_continue(arms[1].body); then { - let (capture_mut, capture_ref, capture_ref_mut) = match bind_annotation { - BindingAnnotation::Unannotated => (false, false, false), - BindingAnnotation::Mutable => (true, false, false), - BindingAnnotation::Ref => (false, true, false), - BindingAnnotation::RefMut => (false, false, true), - }; - let some_body = if let ExprKind::Block(Block { stmts: statements, expr: Some(expr), .. }, _) - = &arms[0].body.kind { - if let &[] = &statements { - expr - } else { - &arms[0].body - } - } else { - return None; - }; - let (none_body, method_sugg) = if let ExprKind::Block(Block { stmts: statements, expr: Some(expr), .. }, _) - = &arms[1].body.kind { - if let &[] = &statements { - (expr, "map_or") - } else { - (&arms[1].body, "map_or_else") - } - } else { - return None; + let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" }; + let some_body = extract_body_from_arm(&arms[0])?; + let none_body = extract_body_from_arm(&arms[1])?; + let method_sugg = match &none_body.kind { + ExprKind::Block(..) => "map_or_else", + _ => "map_or", }; let capture_name = id.name.to_ident_string(); - let wrap_braces = utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| { - if_chain! { - if let Some(Expr { kind: ExprKind::Match( - _, - arms, - MatchSource::IfDesugar{contains_else_clause: true} - | MatchSource::IfLetDesugar{contains_else_clause: true}), - .. } ) = parent.expr; - if expr.hir_id == arms[1].body.hir_id; - then { - true - } else { - false - } - } - }); - let (parens_around_option, as_ref, as_mut, let_body) = match &let_body.kind { + let wrap_braces = should_wrap_in_braces(cx, expr); + let (as_ref, as_mut) = match &cond_expr.kind { + ExprKind::AddrOf(_, Mutability::Not, _) => (true, false), + ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true), + _ => (bind_annotation == &BindingAnnotation::Ref, bind_annotation == &BindingAnnotation::RefMut), + }; + let parens_around_option = match &cond_expr.kind { + // Put parens around the option expression if not doing so might + // mess up the order of operations. ExprKind::Call(..) | ExprKind::MethodCall(..) | ExprKind::Loop(..) @@ -203,15 +240,20 @@ fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) - | ExprKind::Block(..) | ExprKind::Field(..) | ExprKind::Path(_) - => (false, capture_ref, capture_ref_mut, let_body), - ExprKind::Unary(UnOp::UnDeref, expr) => (false, capture_ref, capture_ref_mut, expr), - ExprKind::AddrOf(_, mutability, expr) => (false, mutability == &Mutability::Not, mutability == &Mutability::Mut, expr), - _ => (true, capture_ref, capture_ref_mut, let_body), + | ExprKind::Unary(UnOp::UnDeref, _) + | ExprKind::AddrOf(..) + => false, + _ => true, + }; + let cond_expr = match &cond_expr.kind { + // Pointer dereferencing happens automatically, so we can omit it in the suggestion + ExprKind::Unary(UnOp::UnDeref, expr)|ExprKind::AddrOf(_, _, expr) => expr, + _ => cond_expr, }; Some(OptionIfLetElseOccurence { - option: format!("{}{}{}{}", if parens_around_option { "(" } else { "" }, Sugg::hir(cx, let_body, ".."), if parens_around_option { ")" } else { "" }, if as_mut { ".as_mut()" } else if as_ref { ".as_ref()" } else { "" }), - method_sugg: format!("{}", method_sugg), - some_expr: format!("|{}{}{}| {}", if false { "ref " } else { "" }, if capture_mut { "mut " } else { "" }, capture_name, Sugg::hir(cx, some_body, "..")), + option: format_option_in_sugg(cx, cond_expr, parens_around_option, as_ref, as_mut), + method_sugg: method_sugg.to_string(), + some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir(cx, some_body, "..")), none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")), wrap_braces, }) diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 6f9d506d347..dee80d26bd9 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -20,27 +20,15 @@ fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> { } fn unop_bad(string: &Option<&str>, mut num: Option<i32>) { - let _ = if let Some(s) = *string { - s.len() - } else { - 0 - }; - let _ = if let Some(s) = &num { - s - } else { - &0 - }; + let _ = if let Some(s) = *string { s.len() } else { 0 }; + let _ = if let Some(s) = &num { s } else { &0 }; let _ = if let Some(s) = &mut num { *s += 1; s } else { &mut 0 }; - let _ = if let Some(ref s) = num { - s - } else { - &0 - }; + let _ = if let Some(ref s) = num { s } else { &0 }; let _ = if let Some(mut s) = num { s += 1; s diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index 9240d3edb27..7005850efaf 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -24,27 +24,17 @@ LL | | } error: use Option::map_or instead of an if let/else --> $DIR/option_if_let_else.rs:23:13 | -LL | let _ = if let Some(s) = *string { - | _____________^ -LL | | s.len() -LL | | } else { -LL | | 0 -LL | | }; - | |_____^ help: try: `string.map_or(0, |s| s.len())` +LL | let _ = if let Some(s) = *string { s.len() } else { 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:28:13 + --> $DIR/option_if_let_else.rs:24:13 | -LL | let _ = if let Some(s) = &num { - | _____________^ -LL | | s -LL | | } else { -LL | | &0 -LL | | }; - | |_____^ help: try: `num.as_ref().map_or(&0, |s| s)` +LL | let _ = if let Some(s) = &num { s } else { &0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:33:13 + --> $DIR/option_if_let_else.rs:25:13 | LL | let _ = if let Some(s) = &mut num { | _____________^ @@ -64,18 +54,13 @@ LL | }); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:39:13 + --> $DIR/option_if_let_else.rs:31:13 | -LL | let _ = if let Some(ref s) = num { - | _____________^ -LL | | s -LL | | } else { -LL | | &0 -LL | | }; - | |_____^ help: try: `num.as_ref().map_or(&0, |s| s)` +LL | let _ = if let Some(ref s) = num { s } else { &0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:44:13 + --> $DIR/option_if_let_else.rs:32:13 | LL | let _ = if let Some(mut s) = num { | _____________^ @@ -95,7 +80,7 @@ LL | }); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:50:13 + --> $DIR/option_if_let_else.rs:38:13 | LL | let _ = if let Some(ref mut s) = num { | _____________^ @@ -115,7 +100,7 @@ LL | }); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:59:5 + --> $DIR/option_if_let_else.rs:47:5 | LL | / if let Some(x) = arg { LL | | let y = x * x; @@ -134,7 +119,7 @@ LL | }) | error: use Option::map_or_else instead of an if let/else - --> $DIR/option_if_let_else.rs:68:13 + --> $DIR/option_if_let_else.rs:56:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -157,7 +142,7 @@ LL | }, |x| x * x * x * x); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:97:13 + --> $DIR/option_if_let_else.rs:85:13 | LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` From 7c4de9d3dee3a7e16118df5c1cd2080af7350d98 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Mon, 11 May 2020 17:52:47 -0700 Subject: [PATCH 252/526] Refactoring pt. 2 --- clippy_lints/src/option_if_let_else.rs | 33 ++++---------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 208aa550765..6e8d7515671 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -179,18 +179,10 @@ fn should_wrap_in_braces(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { }) } -fn format_option_in_sugg( - cx: &LateContext<'_, '_>, - cond_expr: &Expr<'_>, - parens_around_option: bool, - as_ref: bool, - as_mut: bool, -) -> String { +fn format_option_in_sugg(cx: &LateContext<'_, '_>, cond_expr: &Expr<'_>, as_ref: bool, as_mut: bool) -> String { format!( - "{}{}{}{}", - if parens_around_option { "(" } else { "" }, - Sugg::hir(cx, cond_expr, ".."), - if parens_around_option { ")" } else { "" }, + "{}{}", + Sugg::hir(cx, cond_expr, "..").maybe_par(), if as_mut { ".as_mut()" } else if as_ref { @@ -230,28 +222,13 @@ fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) - ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true), _ => (bind_annotation == &BindingAnnotation::Ref, bind_annotation == &BindingAnnotation::RefMut), }; - let parens_around_option = match &cond_expr.kind { - // Put parens around the option expression if not doing so might - // mess up the order of operations. - ExprKind::Call(..) - | ExprKind::MethodCall(..) - | ExprKind::Loop(..) - | ExprKind::Match(..) - | ExprKind::Block(..) - | ExprKind::Field(..) - | ExprKind::Path(_) - | ExprKind::Unary(UnOp::UnDeref, _) - | ExprKind::AddrOf(..) - => false, - _ => true, - }; let cond_expr = match &cond_expr.kind { // Pointer dereferencing happens automatically, so we can omit it in the suggestion - ExprKind::Unary(UnOp::UnDeref, expr)|ExprKind::AddrOf(_, _, expr) => expr, + ExprKind::Unary(UnOp::UnDeref, expr) | ExprKind::AddrOf(_, _, expr) => expr, _ => cond_expr, }; Some(OptionIfLetElseOccurence { - option: format_option_in_sugg(cx, cond_expr, parens_around_option, as_ref, as_mut), + option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut), method_sugg: method_sugg.to_string(), some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir(cx, some_body, "..")), none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")), From 5e20475e47d3db1d32a7649a7c3a107caba32a14 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sun, 31 May 2020 15:34:10 -0700 Subject: [PATCH 253/526] Don't lint if contains a macro --- clippy_lints/src/option_if_let_else.rs | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 6e8d7515671..be0c44cae34 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -10,8 +10,6 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use std::marker::PhantomData; - declare_clippy_lint! { /// **What it does:** /// Lints usage of `if let Some(v) = ... { y } else { x }` which is more @@ -88,19 +86,17 @@ struct OptionIfLetElseOccurence { wrap_braces: bool, } -struct ReturnBreakContinueVisitor<'tcx> { +struct ReturnBreakContinueMacroVisitor { seen_return_break_continue: bool, - phantom_data: PhantomData<&'tcx bool>, } -impl<'tcx> ReturnBreakContinueVisitor<'tcx> { - fn new() -> ReturnBreakContinueVisitor<'tcx> { - ReturnBreakContinueVisitor { +impl ReturnBreakContinueMacroVisitor { + fn new() -> ReturnBreakContinueMacroVisitor { + ReturnBreakContinueMacroVisitor { seen_return_break_continue: false, - phantom_data: PhantomData, } } } -impl<'tcx> Visitor<'tcx> for ReturnBreakContinueVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for ReturnBreakContinueMacroVisitor { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { NestedVisitorMap::None @@ -119,14 +115,18 @@ impl<'tcx> Visitor<'tcx> for ReturnBreakContinueVisitor<'tcx> { // desugaring, as this will detect a break if there's a while loop // or a for loop inside the expression. _ => { - rustc_hir::intravisit::walk_expr(self, ex); + if utils::in_macro(ex.span) { + self.seen_return_break_continue = true; + } else { + rustc_hir::intravisit::walk_expr(self, ex); + } }, } } } -fn contains_return_break_continue<'tcx>(expression: &'tcx Expr<'tcx>) -> bool { - let mut recursive_visitor: ReturnBreakContinueVisitor<'tcx> = ReturnBreakContinueVisitor::new(); +fn contains_return_break_continue_macro(expression: &Expr<'_>) -> bool { + let mut recursive_visitor = ReturnBreakContinueMacroVisitor::new(); recursive_visitor.visit_expr(expression); recursive_visitor.seen_return_break_continue } @@ -205,8 +205,8 @@ fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) - if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind; if utils::match_qpath(struct_qpath, &paths::OPTION_SOME); if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind; - if !contains_return_break_continue(arms[0].body); - if !contains_return_break_continue(arms[1].body); + if !contains_return_break_continue_macro(arms[0].body); + if !contains_return_break_continue_macro(arms[1].body); then { let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" }; let some_body = extract_body_from_arm(&arms[0])?; From 5150277a4f765bb113e163adc7eb495dcbb57129 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sun, 31 May 2020 15:37:21 -0700 Subject: [PATCH 254/526] Used clippy to clean itself --- clippy_lints/src/attrs.rs | 14 ++----- clippy_lints/src/if_let_mutex.rs | 8 +--- clippy_lints/src/len_zero.rs | 8 +--- clippy_lints/src/literal_representation.rs | 7 ++-- clippy_lints/src/loops.rs | 26 +++--------- clippy_lints/src/methods/mod.rs | 6 +-- .../src/methods/unnecessary_filter_map.rs | 6 +-- clippy_lints/src/minmax.rs | 21 +++++----- clippy_lints/src/misc.rs | 8 +--- clippy_lints/src/option_if_let_else.rs | 4 +- clippy_lints/src/returns.rs | 9 +---- clippy_lints/src/shadow.rs | 10 ++--- clippy_lints/src/types.rs | 12 +++--- clippy_lints/src/use_self.rs | 8 +--- clippy_lints/src/utils/attrs.rs | 14 +++---- clippy_lints/src/utils/mod.rs | 40 ++++--------------- clippy_lints/src/utils/numeric_literal.rs | 6 +-- clippy_lints/src/utils/sugg.rs | 8 +--- clippy_lints/src/write.rs | 6 +-- 19 files changed, 67 insertions(+), 154 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 2d0855f6895..cfad9d79f2b 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -481,15 +481,11 @@ fn is_relevant_trait(cx: &LateContext<'_>, item: &TraitItem<'_>) -> bool { } fn is_relevant_block(cx: &LateContext<'_>, tables: &ty::TypeckTables<'_>, block: &Block<'_>) -> bool { - if let Some(stmt) = block.stmts.first() { - match &stmt.kind { + block.stmts.first().map_or(block.expr.as_ref().map_or(false, |e| is_relevant_expr(cx, tables, e)), |stmt| match &stmt.kind { StmtKind::Local(_) => true, StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, tables, expr), _ => false, - } - } else { - block.expr.as_ref().map_or(false, |e| is_relevant_expr(cx, tables, e)) - } + }) } fn is_relevant_expr(cx: &LateContext<'_>, tables: &ty::TypeckTables<'_>, expr: &Expr<'_>) -> bool { @@ -499,11 +495,7 @@ fn is_relevant_expr(cx: &LateContext<'_>, tables: &ty::TypeckTables<'_>, expr: & ExprKind::Ret(None) | ExprKind::Break(_, None) => false, ExprKind::Call(path_expr, _) => { if let ExprKind::Path(qpath) = &path_expr.kind { - if let Some(fun_id) = tables.qpath_res(qpath, path_expr.hir_id).opt_def_id() { - !match_def_path(cx, fun_id, &paths::BEGIN_PANIC) - } else { - true - } + tables.qpath_res(qpath, path_expr.hir_id).opt_def_id().map_or(true, |fun_id| !match_def_path(cx, fun_id, &paths::BEGIN_PANIC)) } else { true } diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs index f911cb68ea5..7e44618e90e 100644 --- a/clippy_lints/src/if_let_mutex.rs +++ b/clippy_lints/src/if_let_mutex.rs @@ -135,13 +135,9 @@ impl<'tcx> Visitor<'tcx> for ArmVisitor<'_, 'tcx> { } } -impl<'tcx> ArmVisitor<'_, 'tcx> { +impl<'tcx, 'l> ArmVisitor<'tcx, 'l> { fn same_mutex(&self, cx: &LateContext<'_>, op_mutex: &Expr<'_>) -> bool { - if let Some(arm_mutex) = self.found_mutex { - SpanlessEq::new(cx).eq_expr(op_mutex, arm_mutex) - } else { - false - } + self.found_mutex.map_or(false, |arm_mutex| SpanlessEq::new(cx).eq_expr(op_mutex, arm_mutex)) } } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 26d96428771..f57fa830adc 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -303,14 +303,10 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let ty = &walk_ptrs_ty(cx.tables().expr_ty(expr)); match ty.kind { ty::Dynamic(ref tt, ..) => { - if let Some(principal) = tt.principal() { - cx.tcx + tt.principal().map_or(false, |principal| cx.tcx .associated_items(principal.def_id()) .in_definition_order() - .any(|item| is_is_empty(cx, &item)) - } else { - false - } + .any(|item| is_is_empty(cx, &item))) }, ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), ty::Adt(id, _) => has_is_empty_impl(cx, id.did), diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 7ba43562d7d..ea2e23bd3a1 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -264,10 +264,11 @@ impl LiteralDigitGrouping { let (part, mistyped_suffixes, missing_char) = if let Some((_, exponent)) = &mut num_lit.exponent { (exponent, &["32", "64"][..], 'f') - } else if let Some(fraction) = &mut num_lit.fraction { - (fraction, &["32", "64"][..], 'f') } else { - (&mut num_lit.integer, &["8", "16", "32", "64"][..], 'i') + num_lit.fraction.as_mut().map_or( + (&mut num_lit.integer, &["8", "16", "32", "64"][..], 'i'), + |fraction| (fraction, &["32", "64"][..], 'f') + ) }; let mut split = part.rsplit('_'); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index d821b513484..8d48f39a045 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -687,11 +687,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { } }, ExprKind::Break(_, ref e) | ExprKind::Ret(ref e) => { - if let Some(ref e) = *e { - combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak) - } else { - NeverLoopResult::AlwaysBreak - } + e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak)) }, ExprKind::InlineAsm(ref asm) => asm .operands @@ -1882,11 +1878,7 @@ fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.kind { ty::Array(_, n) => { - if let Some(val) = n.try_eval_usize(cx.tcx, cx.param_env) { - (0..=32).contains(&val) - } else { - false - } + n.try_eval_usize(cx.tcx, cx.param_env).map_or(false, |val| (0..=32).contains(&val)) }, _ => false, } @@ -1899,11 +1891,7 @@ fn extract_expr_from_first_stmt<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr< return None; } if let StmtKind::Local(ref local) = block.stmts[0].kind { - if let Some(expr) = local.init { - Some(expr) - } else { - None - } + local.init.map(|expr| expr) } else { None } @@ -2023,15 +2011,11 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { if let PatKind::Binding(.., ident, _) = local.pat.kind { self.name = Some(ident.name); - self.state = if let Some(ref init) = local.init { - if is_integer_const(&self.cx, init, 0) { + self.state = local.init.as_ref().map_or(VarState::Declared, |init| if is_integer_const(&self.cx, init, 0) { VarState::Warn } else { VarState::Declared - } - } else { - VarState::Declared - } + }) } } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 160304865c5..ddad16e163e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2461,11 +2461,7 @@ fn derefs_to_slice<'tcx>( ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym!(vec_type)), ty::Array(_, size) => { - if let Some(size) = size.try_eval_usize(cx.tcx, cx.param_env) { - size < 32 - } else { - false - } + size.try_eval_usize(cx.tcx, cx.param_env).map_or(false, |size| size < 32) }, ty::Ref(_, inner, _) => may_slice(cx, inner), _ => false, diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index fdcba110542..97909c97fc7 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -78,11 +78,7 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc (true, true) }, hir::ExprKind::Block(ref block, _) => { - if let Some(expr) = &block.expr { - check_expression(cx, arg_id, &expr) - } else { - (false, false) - } + block.expr.as_ref().map_or((false, false), |expr| check_expression(cx, arg_id, &expr)) }, hir::ExprKind::Match(_, arms, _) => { let mut found_mapping = false; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 0a2d577396a..a3d1a500aa7 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -86,16 +86,19 @@ fn fetch_const<'a>(cx: &LateContext<'_>, args: &'a [Expr<'a>], m: MinMax) -> Opt if args.len() != 2 { return None; } - if let Some(c) = constant_simple(cx, cx.tables(), &args[0]) { - if constant_simple(cx, cx.tables(), &args[1]).is_none() { - // otherwise ignore - Some((m, c, &args[1])) + constant_simple(cx, cx.tables, &args[0]).map_or_else( + || if let Some(c) = constant_simple(cx, cx.tables(), &args[1]) { + Some((m, c, &args[0])) } else { None + }, + |c| { + if constant_simple(cx, cx.tables, &args[1]).is_none() { + // otherwise ignore + Some((c, &args[1])) + } else { + None + } } - } else if let Some(c) = constant_simple(cx, cx.tables(), &args[1]) { - Some((m, c, &args[0])) - } else { - None - } + ).map(|(c, arg)| (m, c, arg)) } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 6a256627bd1..5b0f9d6e3ec 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -682,16 +682,12 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: /// `unused_variables`'s idea /// of what it means for an expression to be "used". fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - if let Some(parent) = get_parent_expr(cx, expr) { - match parent.kind { + get_parent_expr(cx, expr).map_or(true, |parent| match parent.kind { ExprKind::Assign(_, ref rhs, _) | ExprKind::AssignOp(_, _, ref rhs) => { SpanlessEq::new(cx).eq_expr(rhs, expr) }, _ => is_used(cx, parent), - } - } else { - true - } + }) } /// Tests whether an expression is in a macro expansion (e.g., something diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index be0c44cae34..b6d08b8ae17 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -37,6 +37,7 @@ declare_clippy_lint! { /// /// ```rust /// # let optional: Option<u32> = Some(0); + /// # fn do_complicated_function() -> u32 { 5 }; /// let _ = if let Some(foo) = optional { /// foo /// } else { @@ -54,9 +55,10 @@ declare_clippy_lint! { /// /// ```rust /// # let optional: Option<u32> = Some(0); + /// # fn do_complicated_function() -> u32 { 5 }; /// let _ = optional.map_or(5, |foo| foo); /// let _ = optional.map_or_else(||{ - /// let y = do_complicated_function; + /// let y = do_complicated_function(); /// y*y /// }, |foo| foo); /// ``` diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 3c939744173..4d54e3117fa 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -259,15 +259,10 @@ fn is_unit_expr(expr: &ast::Expr) -> bool { fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) { let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) { - if let Some(rpos) = fn_source.rfind("->") { - #[allow(clippy::cast_possible_truncation)] - ( + fn_source.rfind("->").map_or((ty.span, Applicability::MaybeIncorrect), |rpos| ( ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), Applicability::MachineApplicable, - ) - } else { - (ty.span, Applicability::MaybeIncorrect) - } + )) } else { (ty.span, Applicability::MaybeIncorrect) }; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 7da47ee4ff9..de94fb87147 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -164,15 +164,11 @@ fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: & } fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool { - let var_ty = cx.tables().node_type_opt(pat_id); - if let Some(var_ty) = var_ty { - match var_ty.kind { + let var_ty = cx.tables.node_type_opt(pat_id); + var_ty.map_or(false, |var_ty| match var_ty.kind { ty::Adt(..) => false, _ => true, - } - } else { - false - } + }) } fn check_pat<'tcx>( diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index b1345f0de5e..df87c1b9802 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1205,16 +1205,14 @@ fn span_lossless_lint(cx: &LateContext<'_>, expr: &Expr<'_>, op: &Expr<'_>, cast // has parens on the outside, they are no longer needed. let mut applicability = Applicability::MachineApplicable; let opt = snippet_opt(cx, op.span); - let sugg = if let Some(ref snip) = opt { - if should_strip_parens(op, snip) { + let sugg = opt.as_ref().map_or_else(|| { + applicability = Applicability::HasPlaceholders; + ".." + }, |snip| if should_strip_parens(op, snip) { &snip[1..snip.len() - 1] } else { snip.as_str() - } - } else { - applicability = Applicability::HasPlaceholders; - ".." - }; + }); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index f85db1e2006..eac7ae2358e 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -167,14 +167,10 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { if let TyKind::Path(QPath::Resolved(_, ref item_path)) = item_type.kind; then { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; - let should_check = if let Some(ref params) = *parameters { - !params.parenthesized && !params.args.iter().any(|arg| match arg { + let should_check = parameters.as_ref().map_or(true, |params| !params.parenthesized && !params.args.iter().any(|arg| match arg { GenericArg::Lifetime(_) => true, _ => false, - }) - } else { - true - }; + })); if should_check { let visitor = &mut UseSelfVisitor { diff --git a/clippy_lints/src/utils/attrs.rs b/clippy_lints/src/utils/attrs.rs index 4dcf6c105ec..2d72f9c3fe1 100644 --- a/clippy_lints/src/utils/attrs.rs +++ b/clippy_lints/src/utils/attrs.rs @@ -65,8 +65,7 @@ pub fn get_attr<'a>( }; let attr_segments = &attr.path.segments; if attr_segments.len() == 2 && attr_segments[0].ident.to_string() == "clippy" { - if let Some(deprecation_status) = - BUILTIN_ATTRIBUTES + BUILTIN_ATTRIBUTES .iter() .find_map(|(builtin_name, deprecation_status)| { if *builtin_name == attr_segments[1].ident.to_string() { @@ -74,8 +73,10 @@ pub fn get_attr<'a>( } else { None } - }) - { + }).map_or_else(|| { + sess.span_err(attr_segments[1].ident.span, "Usage of unknown attribute"); + false + }, |deprecation_status| { let mut diag = sess.struct_span_err(attr_segments[1].ident.span, "Usage of deprecated attribute"); match *deprecation_status { DeprecationStatus::Deprecated => { @@ -97,10 +98,7 @@ pub fn get_attr<'a>( attr_segments[1].ident.to_string() == name }, } - } else { - sess.span_err(attr_segments[1].ident.span, "Usage of unknown attribute"); - false - } + }) } else { false } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 99ba7d64331..6f23e968006 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -153,11 +153,7 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symb pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool { let def_id = cx.tables().type_dependent_def_id(expr.hir_id).unwrap(); let trt_id = cx.tcx.trait_of_item(def_id); - if let Some(trt_id) = trt_id { - match_def_path(cx, trt_id, path) - } else { - false - } + trt_id.map_or(false, |trt_id| match_def_path(cx, trt_id, path)) } /// Checks if an expression references a variable of the given name. @@ -600,21 +596,13 @@ pub fn snippet_block_with_applicability<'a, T: LintContext>( /// // ^^^^^^^^^^ /// ``` pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span { - if let Some(first_char_pos) = first_char_in_first_line(cx, span) { - span.with_lo(first_char_pos) - } else { - span - } + first_char_in_first_line(cx, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos)) } fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> { let line_span = line_span(cx, span); - if let Some(snip) = snippet_opt(cx, line_span) { - snip.find(|c: char| !c.is_whitespace()) - .map(|pos| line_span.lo() + BytePos::from_usize(pos)) - } else { - None - } + snippet_opt(cx, line_span).and_then(|snip| snip.find(|c: char| !c.is_whitespace()) + .map(|pos| line_span.lo() + BytePos::from_usize(pos))) } /// Returns the indentation of the line of a span @@ -626,11 +614,7 @@ fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePo /// // ^^ -- will return 4 /// ``` pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> { - if let Some(snip) = snippet_opt(cx, line_span(cx, span)) { - snip.find(|c: char| !c.is_whitespace()) - } else { - None - } + snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace())) } /// Extends the span to the beginning of the spans line, incl. whitespaces. @@ -738,8 +722,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio let enclosing_node = map .get_enclosing_scope(hir_id) .and_then(|enclosing_id| map.find(enclosing_id)); - if let Some(node) = enclosing_node { - match node { + enclosing_node.and_then(|node| match node { Node::Block(block) => Some(block), Node::Item(&Item { kind: ItemKind::Fn(_, _, eid), @@ -753,10 +736,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio _ => None, }, _ => None, - } - } else { - None - } + }) } /// Returns the base type for HIR references and pointers. @@ -1328,11 +1308,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { _ => None, }; - if let Some(did) = did { - must_use_attr(&cx.tcx.get_attrs(did)).is_some() - } else { - false - } + did.map_or(false, |did| must_use_attr(&cx.tcx.get_attrs(did)).is_some()) } pub fn is_no_std_crate(krate: &Crate<'_>) -> bool { diff --git a/clippy_lints/src/utils/numeric_literal.rs b/clippy_lints/src/utils/numeric_literal.rs index 99413153d49..7a79741b30b 100644 --- a/clippy_lints/src/utils/numeric_literal.rs +++ b/clippy_lints/src/utils/numeric_literal.rs @@ -200,12 +200,10 @@ impl<'a> NumericLiteral<'a> { fn split_suffix<'a>(src: &'a str, lit_kind: &LitKind) -> (&'a str, Option<&'a str>) { debug_assert!(lit_kind.is_numeric()); - if let Some(suffix_length) = lit_suffix_length(lit_kind) { + lit_suffix_length(lit_kind).map_or((src, None), |suffix_length| { let (unsuffixed, suffix) = src.split_at(src.len() - suffix_length); (unsuffixed, Some(suffix)) - } else { - (src, None) - } + }) } fn lit_suffix_length(lit_kind: &LitKind) -> Option<usize> { diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 8fc97f2fd64..20bea3cbabe 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -492,8 +492,7 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp { /// before it on its line. fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> { let lo = cx.sess().source_map().lookup_char_pos(span.lo()); - if let Some(line) = lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) { - if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') { + lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */).and_then(|line| if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') { // We can mix char and byte positions here because we only consider `[ \t]`. if lo.col == CharPos(pos) { Some(line[..pos].into()) @@ -502,10 +501,7 @@ fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> { } } else { None - } - } else { - None - } + }) } /// Convenience extension trait for `DiagnosticBuilder`. diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 732f4b28e06..3b10b7b82a0 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -297,12 +297,10 @@ impl EarlyLintPass for Write { if let (Some(fmt_str), expr) = self.check_tts(cx, &mac.args.inner_tokens(), true) { if fmt_str.symbol == Symbol::intern("") { let mut applicability = Applicability::MachineApplicable; - let suggestion = if let Some(e) = expr { - snippet_with_applicability(cx, e.span, "v", &mut applicability) - } else { + let suggestion = expr.map_or_else(|| { applicability = Applicability::HasPlaceholders; Cow::Borrowed("v") - }; + }, |e| snippet_with_applicability(cx, e.span, "v", &mut Applicability::MachineApplicable)); span_lint_and_sugg( cx, From 93f0f5d37b45c648aebf87fe7e7379599ba3e726 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Fri, 12 Jun 2020 08:32:38 -0700 Subject: [PATCH 255/526] Last few tweaks --- CHANGELOG.md | 1 - clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/minmax.rs | 3 +-- clippy_lints/src/option_if_let_else.rs | 2 +- clippy_lints/src/returns.rs | 9 +++++++-- src/lintlist/mod.rs | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a081bb85fe..01c0e4b0302 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1491,7 +1491,6 @@ Released 2018-09-13 [`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays [`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty [`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero -[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return [`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock [`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index cd91e7ceb32..fe34e4390d6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1161,6 +1161,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&needless_continue::NEEDLESS_CONTINUE), LintId::of(&needless_pass_by_value::NEEDLESS_PASS_BY_VALUE), LintId::of(&non_expressive_names::SIMILAR_NAMES), + LintId::of(&option_if_let_else::OPTION_IF_LET_ELSE), LintId::of(&ranges::RANGE_PLUS_ONE), LintId::of(&shadow::SHADOW_UNRELATED), LintId::of(&strings::STRING_ADD_ASSIGN), @@ -1372,7 +1373,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES), LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS), LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP), - LintId::of(&option_if_let_else::OPTION_IF_LET_ELSE), LintId::of(&overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), LintId::of(&panic_unimplemented::PANIC_PARAMS), LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL), @@ -1521,7 +1521,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES), - LintId::of(&option_if_let_else::OPTION_IF_LET_ELSE), LintId::of(&panic_unimplemented::PANIC_PARAMS), LintId::of(&ptr::CMP_NULL), LintId::of(&ptr::PTR_ARG), diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index a3d1a500aa7..6ec7f8cae5d 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -99,6 +99,5 @@ fn fetch_const<'a>(cx: &LateContext<'_>, args: &'a [Expr<'a>], m: MinMax) -> Opt } else { None } - } - ).map(|(c, arg)| (m, c, arg)) + }) } diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index b6d08b8ae17..c877cc6fa8b 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -63,7 +63,7 @@ declare_clippy_lint! { /// }, |foo| foo); /// ``` pub OPTION_IF_LET_ELSE, - style, + pedantic, "reimplementation of Option::map_or" } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 4d54e3117fa..3c939744173 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -259,10 +259,15 @@ fn is_unit_expr(expr: &ast::Expr) -> bool { fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) { let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) { - fn_source.rfind("->").map_or((ty.span, Applicability::MaybeIncorrect), |rpos| ( + if let Some(rpos) = fn_source.rfind("->") { + #[allow(clippy::cast_possible_truncation)] + ( ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), Applicability::MachineApplicable, - )) + ) + } else { + (ty.span, Applicability::MaybeIncorrect) + } } else { (ty.span, Applicability::MaybeIncorrect) }; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index b499d565fa7..e681f47f949 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1622,7 +1622,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ }, Lint { name: "option_if_let_else", - group: "style", + group: "pedantic", desc: "reimplementation of Option::map_or", deprecation: None, module: "option_if_let_else", From ccb999851aaa4d3e9cd97110bd6523a6c3df46fd Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 25 Jun 2020 11:39:58 -0700 Subject: [PATCH 256/526] Fix compile error from library change --- CHANGELOG.md | 1 + clippy_lints/src/option_if_let_else.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c0e4b0302..1a081bb85fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1491,6 +1491,7 @@ Released 2018-09-13 [`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays [`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty [`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero +[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return [`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock [`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index c877cc6fa8b..7e299dd5fd9 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -71,7 +71,7 @@ declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]); /// Returns true iff the given expression is the result of calling `Result::ok` fn is_result_ok(cx: &LateContext<'_, '_>, expr: &'_ Expr<'_>) -> bool { - if let ExprKind::MethodCall(ref path, _, &[ref receiver]) = &expr.kind { + if let ExprKind::MethodCall(ref path, _, &[ref receiver], _) = &expr.kind { path.ident.name.to_ident_string() == "ok" && match_type(cx, &cx.tables.expr_ty(&receiver), &paths::RESULT) } else { false From 6ce981225b73d6c3514b0abb759a5282521a17d9 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 25 Jun 2020 11:58:47 -0700 Subject: [PATCH 257/526] Clean existing lint code to match new lint --- clippy_lints/src/attrs.rs | 14 ++-- clippy_lints/src/if_let_mutex.rs | 5 +- clippy_lints/src/len_zero.rs | 12 ++-- clippy_lints/src/literal_representation.rs | 10 +-- clippy_lints/src/loops.rs | 20 +++--- clippy_lints/src/methods/mod.rs | 6 +- .../src/methods/unnecessary_filter_map.rs | 7 +- clippy_lints/src/minmax.rs | 2 +- clippy_lints/src/misc.rs | 8 +-- clippy_lints/src/option_if_let_else.rs | 2 +- clippy_lints/src/returns.rs | 18 ++--- clippy_lints/src/shadow.rs | 6 +- clippy_lints/src/types.rs | 21 +++--- clippy_lints/src/use_self.rs | 7 +- clippy_lints/src/utils/attrs.rs | 67 ++++++++++--------- clippy_lints/src/utils/mod.rs | 32 ++++----- clippy_lints/src/utils/sugg.rs | 16 +++-- clippy_lints/src/write.rs | 11 +-- 18 files changed, 148 insertions(+), 116 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index cfad9d79f2b..c4397560d7d 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -480,12 +480,15 @@ fn is_relevant_trait(cx: &LateContext<'_>, item: &TraitItem<'_>) -> bool { } } -fn is_relevant_block(cx: &LateContext<'_>, tables: &ty::TypeckTables<'_>, block: &Block<'_>) -> bool { - block.stmts.first().map_or(block.expr.as_ref().map_or(false, |e| is_relevant_expr(cx, tables, e)), |stmt| match &stmt.kind { +fn is_relevant_block(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, block: &Block<'_>) -> bool { + block.stmts.first().map_or( + block.expr.as_ref().map_or(false, |e| is_relevant_expr(cx, tables, e)), + |stmt| match &stmt.kind { StmtKind::Local(_) => true, StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, tables, expr), _ => false, - }) + }, + ) } fn is_relevant_expr(cx: &LateContext<'_>, tables: &ty::TypeckTables<'_>, expr: &Expr<'_>) -> bool { @@ -495,7 +498,10 @@ fn is_relevant_expr(cx: &LateContext<'_>, tables: &ty::TypeckTables<'_>, expr: & ExprKind::Ret(None) | ExprKind::Break(_, None) => false, ExprKind::Call(path_expr, _) => { if let ExprKind::Path(qpath) = &path_expr.kind { - tables.qpath_res(qpath, path_expr.hir_id).opt_def_id().map_or(true, |fun_id| !match_def_path(cx, fun_id, &paths::BEGIN_PANIC)) + tables + .qpath_res(qpath, path_expr.hir_id) + .opt_def_id() + .map_or(true, |fun_id| !match_def_path(cx, fun_id, &paths::BEGIN_PANIC)) } else { true } diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs index 7e44618e90e..5426e14ead5 100644 --- a/clippy_lints/src/if_let_mutex.rs +++ b/clippy_lints/src/if_let_mutex.rs @@ -136,8 +136,9 @@ impl<'tcx> Visitor<'tcx> for ArmVisitor<'_, 'tcx> { } impl<'tcx, 'l> ArmVisitor<'tcx, 'l> { - fn same_mutex(&self, cx: &LateContext<'_>, op_mutex: &Expr<'_>) -> bool { - self.found_mutex.map_or(false, |arm_mutex| SpanlessEq::new(cx).eq_expr(op_mutex, arm_mutex)) + fn same_mutex(&self, cx: &LateContext<'_, '_>, op_mutex: &Expr<'_>) -> bool { + self.found_mutex + .map_or(false, |arm_mutex| SpanlessEq::new(cx).eq_expr(op_mutex, arm_mutex)) } } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index f57fa830adc..1b09328ceab 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -302,12 +302,12 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let ty = &walk_ptrs_ty(cx.tables().expr_ty(expr)); match ty.kind { - ty::Dynamic(ref tt, ..) => { - tt.principal().map_or(false, |principal| cx.tcx - .associated_items(principal.def_id()) - .in_definition_order() - .any(|item| is_is_empty(cx, &item))) - }, + ty::Dynamic(ref tt, ..) => tt.principal().map_or(false, |principal| { + cx.tcx + .associated_items(principal.def_id()) + .in_definition_order() + .any(|item| is_is_empty(cx, &item)) + }), ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), ty::Adt(id, _) => has_is_empty_impl(cx, id.did), ty::Array(..) | ty::Slice(..) | ty::Str => true, diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index ea2e23bd3a1..a36fdca5d5d 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -265,10 +265,12 @@ impl LiteralDigitGrouping { let (part, mistyped_suffixes, missing_char) = if let Some((_, exponent)) = &mut num_lit.exponent { (exponent, &["32", "64"][..], 'f') } else { - num_lit.fraction.as_mut().map_or( - (&mut num_lit.integer, &["8", "16", "32", "64"][..], 'i'), - |fraction| (fraction, &["32", "64"][..], 'f') - ) + num_lit + .fraction + .as_mut() + .map_or((&mut num_lit.integer, &["8", "16", "32", "64"][..], 'i'), |fraction| { + (fraction, &["32", "64"][..], 'f') + }) }; let mut split = part.rsplit('_'); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8d48f39a045..b803d753b6d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -686,9 +686,9 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { NeverLoopResult::AlwaysBreak } }, - ExprKind::Break(_, ref e) | ExprKind::Ret(ref e) => { - e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak)) - }, + ExprKind::Break(_, ref e) | ExprKind::Ret(ref e) => e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| { + combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak) + }), ExprKind::InlineAsm(ref asm) => asm .operands .iter() @@ -1877,9 +1877,9 @@ fn is_ref_iterable_type(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.kind { - ty::Array(_, n) => { - n.try_eval_usize(cx.tcx, cx.param_env).map_or(false, |val| (0..=32).contains(&val)) - }, + ty::Array(_, n) => n + .try_eval_usize(cx.tcx, cx.param_env) + .map_or(false, |val| (0..=32).contains(&val)), _ => false, } } @@ -1891,7 +1891,7 @@ fn extract_expr_from_first_stmt<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr< return None; } if let StmtKind::Local(ref local) = block.stmts[0].kind { - local.init.map(|expr| expr) + local.init //.map(|expr| expr) } else { None } @@ -2011,11 +2011,13 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { if let PatKind::Binding(.., ident, _) = local.pat.kind { self.name = Some(ident.name); - self.state = local.init.as_ref().map_or(VarState::Declared, |init| if is_integer_const(&self.cx, init, 0) { + self.state = local.init.as_ref().map_or(VarState::Declared, |init| { + if is_integer_const(&self.cx, init, 0) { VarState::Warn } else { VarState::Declared - }) + } + }) } } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index ddad16e163e..f1c8894c0ee 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2460,9 +2460,9 @@ fn derefs_to_slice<'tcx>( ty::Slice(_) => true, ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym!(vec_type)), - ty::Array(_, size) => { - size.try_eval_usize(cx.tcx, cx.param_env).map_or(false, |size| size < 32) - }, + ty::Array(_, size) => size + .try_eval_usize(cx.tcx, cx.param_env) + .map_or(false, |size| size < 32), ty::Ref(_, inner, _) => may_slice(cx, inner), _ => false, } diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index 97909c97fc7..75e123eb593 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -77,9 +77,10 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc } (true, true) }, - hir::ExprKind::Block(ref block, _) => { - block.expr.as_ref().map_or((false, false), |expr| check_expression(cx, arg_id, &expr)) - }, + hir::ExprKind::Block(ref block, _) => block + .expr + .as_ref() + .map_or((false, false), |expr| check_expression(cx, arg_id, &expr)), hir::ExprKind::Match(_, arms, _) => { let mut found_mapping = false; let mut found_filtering = false; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 6ec7f8cae5d..5eb8398d68e 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for MinMaxPass { } } -#[derive(PartialEq, Eq, Debug)] +#[derive(PartialEq, Eq, Debug, Clone, Copy)] enum MinMax { Min, Max, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 5b0f9d6e3ec..3d4225f36a7 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -683,11 +683,9 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: /// of what it means for an expression to be "used". fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { get_parent_expr(cx, expr).map_or(true, |parent| match parent.kind { - ExprKind::Assign(_, ref rhs, _) | ExprKind::AssignOp(_, _, ref rhs) => { - SpanlessEq::new(cx).eq_expr(rhs, expr) - }, - _ => is_used(cx, parent), - }) + ExprKind::Assign(_, ref rhs, _) | ExprKind::AssignOp(_, _, ref rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr), + _ => is_used(cx, parent), + }) } /// Tests whether an expression is in a macro expansion (e.g., something diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 7e299dd5fd9..ab9ea76a838 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -260,7 +260,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse { detection.some_expr, if detection.wrap_braces { " }" } else { "" }, ), - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 3c939744173..faef7e724dd 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -259,15 +259,15 @@ fn is_unit_expr(expr: &ast::Expr) -> bool { fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) { let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) { - if let Some(rpos) = fn_source.rfind("->") { - #[allow(clippy::cast_possible_truncation)] - ( - ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), - Applicability::MachineApplicable, - ) - } else { - (ty.span, Applicability::MaybeIncorrect) - } + fn_source + .rfind("->") + .map_or((ty.span, Applicability::MaybeIncorrect), |rpos| { + ( + #[allow(clippy::cast_possible_truncation)] + ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), + Applicability::MachineApplicable, + ) + }) } else { (ty.span, Applicability::MaybeIncorrect) }; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index de94fb87147..f16db2df3a9 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -166,9 +166,9 @@ fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: & fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool { let var_ty = cx.tables.node_type_opt(pat_id); var_ty.map_or(false, |var_ty| match var_ty.kind { - ty::Adt(..) => false, - _ => true, - }) + ty::Adt(..) => false, + _ => true, + }) } fn check_pat<'tcx>( diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index df87c1b9802..d6f31a99bb3 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1205,14 +1205,19 @@ fn span_lossless_lint(cx: &LateContext<'_>, expr: &Expr<'_>, op: &Expr<'_>, cast // has parens on the outside, they are no longer needed. let mut applicability = Applicability::MachineApplicable; let opt = snippet_opt(cx, op.span); - let sugg = opt.as_ref().map_or_else(|| { - applicability = Applicability::HasPlaceholders; - ".." - }, |snip| if should_strip_parens(op, snip) { - &snip[1..snip.len() - 1] - } else { - snip.as_str() - }); + let sugg = opt.as_ref().map_or_else( + || { + applicability = Applicability::HasPlaceholders; + ".." + }, + |snip| { + if should_strip_parens(op, snip) { + &snip[1..snip.len() - 1] + } else { + snip.as_str() + } + }, + ); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index eac7ae2358e..39a8c020872 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -167,10 +167,13 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { if let TyKind::Path(QPath::Resolved(_, ref item_path)) = item_type.kind; then { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; - let should_check = parameters.as_ref().map_or(true, |params| !params.parenthesized && !params.args.iter().any(|arg| match arg { + let should_check = parameters.as_ref().map_or( + true, + |params| !params.parenthesized && !params.args.iter().any(|arg| match arg { GenericArg::Lifetime(_) => true, _ => false, - })); + }) + ); if should_check { let visitor = &mut UseSelfVisitor { diff --git a/clippy_lints/src/utils/attrs.rs b/clippy_lints/src/utils/attrs.rs index 2d72f9c3fe1..4bb4b087c55 100644 --- a/clippy_lints/src/utils/attrs.rs +++ b/clippy_lints/src/utils/attrs.rs @@ -66,39 +66,44 @@ pub fn get_attr<'a>( let attr_segments = &attr.path.segments; if attr_segments.len() == 2 && attr_segments[0].ident.to_string() == "clippy" { BUILTIN_ATTRIBUTES - .iter() - .find_map(|(builtin_name, deprecation_status)| { - if *builtin_name == attr_segments[1].ident.to_string() { - Some(deprecation_status) - } else { - None + .iter() + .find_map(|(builtin_name, deprecation_status)| { + if *builtin_name == attr_segments[1].ident.to_string() { + Some(deprecation_status) + } else { + None + } + }) + .map_or_else( + || { + sess.span_err(attr_segments[1].ident.span, "Usage of unknown attribute"); + false + }, + |deprecation_status| { + let mut diag = + sess.struct_span_err(attr_segments[1].ident.span, "Usage of deprecated attribute"); + match *deprecation_status { + DeprecationStatus::Deprecated => { + diag.emit(); + false + }, + DeprecationStatus::Replaced(new_name) => { + diag.span_suggestion( + attr_segments[1].ident.span, + "consider using", + new_name.to_string(), + Applicability::MachineApplicable, + ); + diag.emit(); + false + }, + DeprecationStatus::None => { + diag.cancel(); + attr_segments[1].ident.to_string() == name + }, } - }).map_or_else(|| { - sess.span_err(attr_segments[1].ident.span, "Usage of unknown attribute"); - false - }, |deprecation_status| { - let mut diag = sess.struct_span_err(attr_segments[1].ident.span, "Usage of deprecated attribute"); - match *deprecation_status { - DeprecationStatus::Deprecated => { - diag.emit(); - false }, - DeprecationStatus::Replaced(new_name) => { - diag.span_suggestion( - attr_segments[1].ident.span, - "consider using", - new_name.to_string(), - Applicability::MachineApplicable, - ); - diag.emit(); - false - }, - DeprecationStatus::None => { - diag.cancel(); - attr_segments[1].ident.to_string() == name - }, - } - }) + ) } else { false } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6f23e968006..3a3b79925ff 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -601,8 +601,10 @@ pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span { fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> { let line_span = line_span(cx, span); - snippet_opt(cx, line_span).and_then(|snip| snip.find(|c: char| !c.is_whitespace()) - .map(|pos| line_span.lo() + BytePos::from_usize(pos))) + snippet_opt(cx, line_span).and_then(|snip| { + snip.find(|c: char| !c.is_whitespace()) + .map(|pos| line_span.lo() + BytePos::from_usize(pos)) + }) } /// Returns the indentation of the line of a span @@ -723,20 +725,20 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio .get_enclosing_scope(hir_id) .and_then(|enclosing_id| map.find(enclosing_id)); enclosing_node.and_then(|node| match node { - Node::Block(block) => Some(block), - Node::Item(&Item { - kind: ItemKind::Fn(_, _, eid), - .. - }) - | Node::ImplItem(&ImplItem { - kind: ImplItemKind::Fn(_, eid), - .. - }) => match cx.tcx.hir().body(eid).value.kind { - ExprKind::Block(ref block, _) => Some(block), - _ => None, - }, - _ => None, + Node::Block(block) => Some(block), + Node::Item(&Item { + kind: ItemKind::Fn(_, _, eid), + .. }) + | Node::ImplItem(&ImplItem { + kind: ImplItemKind::Fn(_, eid), + .. + }) => match cx.tcx.hir().body(eid).value.kind { + ExprKind::Block(ref block, _) => Some(block), + _ => None, + }, + _ => None, + }) } /// Returns the base type for HIR references and pointers. diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 20bea3cbabe..0ac7714fbeb 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -492,15 +492,19 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp { /// before it on its line. fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> { let lo = cx.sess().source_map().lookup_char_pos(span.lo()); - lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */).and_then(|line| if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') { - // We can mix char and byte positions here because we only consider `[ \t]`. - if lo.col == CharPos(pos) { - Some(line[..pos].into()) + lo.file + .get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) + .and_then(|line| { + if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') { + // We can mix char and byte positions here because we only consider `[ \t]`. + if lo.col == CharPos(pos) { + Some(line[..pos].into()) + } else { + None + } } else { None } - } else { - None }) } diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 3b10b7b82a0..063f94582b9 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -297,10 +297,13 @@ impl EarlyLintPass for Write { if let (Some(fmt_str), expr) = self.check_tts(cx, &mac.args.inner_tokens(), true) { if fmt_str.symbol == Symbol::intern("") { let mut applicability = Applicability::MachineApplicable; - let suggestion = expr.map_or_else(|| { - applicability = Applicability::HasPlaceholders; - Cow::Borrowed("v") - }, |e| snippet_with_applicability(cx, e.span, "v", &mut Applicability::MachineApplicable)); + let suggestion = expr.map_or_else( + || { + applicability = Applicability::HasPlaceholders; + Cow::Borrowed("v") + }, + |e| snippet_with_applicability(cx, e.span, "v", &mut Applicability::MachineApplicable), + ); span_lint_and_sugg( cx, From 6e2d55c8db04a80f9c217f2089066b29302f62a9 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sat, 27 Jun 2020 16:55:47 -0700 Subject: [PATCH 258/526] Update compile-test to follow new lint --- tests/compile-test.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 99505fc6b29..eb6d495acbe 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -12,19 +12,11 @@ use std::path::{Path, PathBuf}; mod cargo; fn host_lib() -> PathBuf { - if let Some(path) = option_env!("HOST_LIBS") { - PathBuf::from(path) - } else { - cargo::CARGO_TARGET_DIR.join(env!("PROFILE")) - } + option_env!("HOST_LIBS").map_or(cargo::CARGO_TARGET_DIR.join(env!("PROFILE")), PathBuf::from) } fn clippy_driver_path() -> PathBuf { - if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") { - PathBuf::from(path) - } else { - cargo::TARGET_LIB.join("clippy-driver") - } + option_env!("CLIPPY_DRIVER_PATH").map_or(cargo::TARGET_LIB.join("clippy-driver"), PathBuf::from) } // When we'll want to use `extern crate ..` for a dependency that is used From 1c32263176d95ae47928d1955e44a4315ffcea2d Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Wed, 1 Jul 2020 11:41:11 -0700 Subject: [PATCH 259/526] Formatted updates to lints --- clippy_lints/src/minmax.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 5eb8398d68e..2e5f5f10f4b 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -87,10 +87,12 @@ fn fetch_const<'a>(cx: &LateContext<'_>, args: &'a [Expr<'a>], m: MinMax) -> Opt return None; } constant_simple(cx, cx.tables, &args[0]).map_or_else( - || if let Some(c) = constant_simple(cx, cx.tables(), &args[1]) { - Some((m, c, &args[0])) - } else { - None + || { + if let Some(c) = constant_simple(cx, cx.tables(), &args[1]) { + Some((m, c, &args[0])) + } else { + None + } }, |c| { if constant_simple(cx, cx.tables, &args[1]).is_none() { @@ -99,5 +101,6 @@ fn fetch_const<'a>(cx: &LateContext<'_>, args: &'a [Expr<'a>], m: MinMax) -> Opt } else { None } - }) + }, + ) } From c8f700ea697f74ef8f86891b050c859cf457e3ab Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Fri, 3 Jul 2020 20:28:40 -0700 Subject: [PATCH 260/526] Fixed compile errors --- clippy_lints/src/attrs.rs | 2 +- clippy_lints/src/if_let_mutex.rs | 2 +- clippy_lints/src/minmax.rs | 14 ++++---------- clippy_lints/src/option_if_let_else.rs | 14 +++++++------- clippy_lints/src/shadow.rs | 2 +- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index c4397560d7d..d68d0d8ccf5 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -480,7 +480,7 @@ fn is_relevant_trait(cx: &LateContext<'_>, item: &TraitItem<'_>) -> bool { } } -fn is_relevant_block(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, block: &Block<'_>) -> bool { +fn is_relevant_block(cx: &LateContext<'_>, tables: &ty::TypeckTables<'_>, block: &Block<'_>) -> bool { block.stmts.first().map_or( block.expr.as_ref().map_or(false, |e| is_relevant_expr(cx, tables, e)), |stmt| match &stmt.kind { diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs index 5426e14ead5..fbd2eeacc6e 100644 --- a/clippy_lints/src/if_let_mutex.rs +++ b/clippy_lints/src/if_let_mutex.rs @@ -136,7 +136,7 @@ impl<'tcx> Visitor<'tcx> for ArmVisitor<'_, 'tcx> { } impl<'tcx, 'l> ArmVisitor<'tcx, 'l> { - fn same_mutex(&self, cx: &LateContext<'_, '_>, op_mutex: &Expr<'_>) -> bool { + fn same_mutex(&self, cx: &LateContext<'_>, op_mutex: &Expr<'_>) -> bool { self.found_mutex .map_or(false, |arm_mutex| SpanlessEq::new(cx).eq_expr(op_mutex, arm_mutex)) } diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 2e5f5f10f4b..c8aa98d3489 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -86,18 +86,12 @@ fn fetch_const<'a>(cx: &LateContext<'_>, args: &'a [Expr<'a>], m: MinMax) -> Opt if args.len() != 2 { return None; } - constant_simple(cx, cx.tables, &args[0]).map_or_else( - || { - if let Some(c) = constant_simple(cx, cx.tables(), &args[1]) { - Some((m, c, &args[0])) - } else { - None - } - }, + constant_simple(cx, cx.tables(), &args[0]).map_or_else( + || constant_simple(cx, cx.tables(), &args[1]).map(|c| (m, c, &args[0])), |c| { - if constant_simple(cx, cx.tables, &args[1]).is_none() { + if constant_simple(cx, cx.tables(), &args[1]).is_none() { // otherwise ignore - Some((c, &args[1])) + Some((m, c, &args[1])) } else { None } diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index ab9ea76a838..8dbe58763bf 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -70,9 +70,9 @@ declare_clippy_lint! { declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]); /// Returns true iff the given expression is the result of calling `Result::ok` -fn is_result_ok(cx: &LateContext<'_, '_>, expr: &'_ Expr<'_>) -> bool { +fn is_result_ok(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool { if let ExprKind::MethodCall(ref path, _, &[ref receiver], _) = &expr.kind { - path.ident.name.to_ident_string() == "ok" && match_type(cx, &cx.tables.expr_ty(&receiver), &paths::RESULT) + path.ident.name.to_ident_string() == "ok" && match_type(cx, &cx.tables().expr_ty(&receiver), &paths::RESULT) } else { false } @@ -157,7 +157,7 @@ fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> { /// If this is the else body of an if/else expression, then we need to wrap /// it in curcly braces. Otherwise, we don't. -fn should_wrap_in_braces(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn should_wrap_in_braces(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| { if let Some(Expr { kind: @@ -181,7 +181,7 @@ fn should_wrap_in_braces(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { }) } -fn format_option_in_sugg(cx: &LateContext<'_, '_>, cond_expr: &Expr<'_>, as_ref: bool, as_mut: bool) -> String { +fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: bool, as_mut: bool) -> String { format!( "{}{}", Sugg::hir(cx, cond_expr, "..").maybe_par(), @@ -198,7 +198,7 @@ fn format_option_in_sugg(cx: &LateContext<'_, '_>, cond_expr: &Expr<'_>, as_ref: /// If this expression is the option if let/else construct we're detecting, then /// this function returns an `OptionIfLetElseOccurence` struct with details if /// this construct is found, or None if this construct is not found. -fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -> Option<OptionIfLetElseOccurence> { +fn detect_option_if_let_else(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OptionIfLetElseOccurence> { if_chain! { if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind; @@ -242,8 +242,8 @@ fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) - } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'a> LateLintPass<'a> for OptionIfLetElse { + fn check_expr(&mut self, cx: &LateContext<'a>, expr: &Expr<'_>) { if let Some(detection) = detect_option_if_let_else(cx, expr) { span_lint_and_sugg( cx, diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index f16db2df3a9..4cdff63f118 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -164,7 +164,7 @@ fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: & } fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool { - let var_ty = cx.tables.node_type_opt(pat_id); + let var_ty = cx.tables().node_type_opt(pat_id); var_ty.map_or(false, |var_ty| match var_ty.kind { ty::Adt(..) => false, _ => true, From a6f1af75d71fcf8e029b78142370e7563798c503 Mon Sep 17 00:00:00 2001 From: Thiago Arrais <thiago.arrais@gmail.com> Date: Fri, 3 Apr 2020 13:58:52 -0300 Subject: [PATCH 261/526] Lint for x.powi(2) => x * x --- clippy_lints/src/floating_point_arithmetic.rs | 27 ++++++++++++++++++- tests/ui/floating_point_log.fixed | 10 +++---- tests/ui/floating_point_log.rs | 10 +++---- tests/ui/floating_point_log.stderr | 20 +++++++------- tests/ui/floating_point_powf.fixed | 4 +-- tests/ui/floating_point_powf.rs | 4 +-- tests/ui/floating_point_powf.stderr | 8 +++--- tests/ui/floating_point_powi.fixed | 12 +++++++++ tests/ui/floating_point_powi.rs | 12 +++++++++ tests/ui/floating_point_powi.stderr | 16 +++++++++++ 10 files changed, 94 insertions(+), 29 deletions(-) create mode 100644 tests/ui/floating_point_powi.fixed create mode 100644 tests/ui/floating_point_powi.rs create mode 100644 tests/ui/floating_point_powi.stderr diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 4efd0689267..e3ee4296119 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -1,6 +1,6 @@ use crate::consts::{ constant, constant_simple, Constant, - Constant::{F32, F64}, + Constant::{Int, F32, F64}, }; use crate::utils::{higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq}; use if_chain::if_chain; @@ -293,6 +293,30 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { } } +fn check_powi(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { + // Check argument + if let Some((value, _)) = constant(cx, cx.tables, &args[1]) { + let (lint, help, suggestion) = match value { + Int(2) => ( + IMPRECISE_FLOPS, + "square can be computed more accurately", + format!("{} * {}", Sugg::hir(cx, &args[0], ".."), Sugg::hir(cx, &args[0], "..")), + ), + _ => return, + }; + + span_lint_and_sugg( + cx, + lint, + expr.span, + help, + "consider using", + suggestion, + Applicability::MachineApplicable, + ); + } +} + // TODO: Lint expressions of the form `x.exp() - y` where y > 1 // and suggest usage of `x.exp_m1() - (y - 1)` instead fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { @@ -489,6 +513,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { "ln" => check_ln1p(cx, expr, args), "log" => check_log_base(cx, expr, args), "powf" => check_powf(cx, expr, args), + "powi" => check_powi(cx, expr, args), _ => {}, } } diff --git a/tests/ui/floating_point_log.fixed b/tests/ui/floating_point_log.fixed index 42c5e5d2bae..7dc7ee94aff 100644 --- a/tests/ui/floating_point_log.fixed +++ b/tests/ui/floating_point_log.fixed @@ -25,11 +25,11 @@ fn check_ln1p() { let _ = 2.0f32.ln_1p(); let _ = x.ln_1p(); let _ = (x / 2.0).ln_1p(); - let _ = x.powi(2).ln_1p(); - let _ = (x.powi(2) / 2.0).ln_1p(); + let _ = x.powi(3).ln_1p(); + let _ = (x.powi(3) / 2.0).ln_1p(); let _ = ((std::f32::consts::E - 1.0)).ln_1p(); let _ = x.ln_1p(); - let _ = x.powi(2).ln_1p(); + let _ = x.powi(3).ln_1p(); let _ = (x + 2.0).ln_1p(); let _ = (x / 2.0).ln_1p(); // Cases where the lint shouldn't be applied @@ -43,9 +43,9 @@ fn check_ln1p() { let _ = 2.0f64.ln_1p(); let _ = x.ln_1p(); let _ = (x / 2.0).ln_1p(); - let _ = x.powi(2).ln_1p(); + let _ = x.powi(3).ln_1p(); let _ = x.ln_1p(); - let _ = x.powi(2).ln_1p(); + let _ = x.powi(3).ln_1p(); let _ = (x + 2.0).ln_1p(); let _ = (x / 2.0).ln_1p(); // Cases where the lint shouldn't be applied diff --git a/tests/ui/floating_point_log.rs b/tests/ui/floating_point_log.rs index 8be0d9ad56f..01181484e7d 100644 --- a/tests/ui/floating_point_log.rs +++ b/tests/ui/floating_point_log.rs @@ -25,11 +25,11 @@ fn check_ln1p() { let _ = (1f32 + 2.0).ln(); let _ = (1.0 + x).ln(); let _ = (1.0 + x / 2.0).ln(); - let _ = (1.0 + x.powi(2)).ln(); - let _ = (1.0 + x.powi(2) / 2.0).ln(); + let _ = (1.0 + x.powi(3)).ln(); + let _ = (1.0 + x.powi(3) / 2.0).ln(); let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); let _ = (x + 1.0).ln(); - let _ = (x.powi(2) + 1.0).ln(); + let _ = (x.powi(3) + 1.0).ln(); let _ = (x + 2.0 + 1.0).ln(); let _ = (x / 2.0 + 1.0).ln(); // Cases where the lint shouldn't be applied @@ -43,9 +43,9 @@ fn check_ln1p() { let _ = (1f64 + 2.0).ln(); let _ = (1.0 + x).ln(); let _ = (1.0 + x / 2.0).ln(); - let _ = (1.0 + x.powi(2)).ln(); + let _ = (1.0 + x.powi(3)).ln(); let _ = (x + 1.0).ln(); - let _ = (x.powi(2) + 1.0).ln(); + let _ = (x.powi(3) + 1.0).ln(); let _ = (x + 2.0 + 1.0).ln(); let _ = (x / 2.0 + 1.0).ln(); // Cases where the lint shouldn't be applied diff --git a/tests/ui/floating_point_log.stderr b/tests/ui/floating_point_log.stderr index 943fbdb0b83..900dc2b7933 100644 --- a/tests/ui/floating_point_log.stderr +++ b/tests/ui/floating_point_log.stderr @@ -77,14 +77,14 @@ LL | let _ = (1.0 + x / 2.0).ln(); error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:28:13 | -LL | let _ = (1.0 + x.powi(2)).ln(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` +LL | let _ = (1.0 + x.powi(3)).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:29:13 | -LL | let _ = (1.0 + x.powi(2) / 2.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) / 2.0).ln_1p()` +LL | let _ = (1.0 + x.powi(3) / 2.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(3) / 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:30:13 @@ -101,8 +101,8 @@ LL | let _ = (x + 1.0).ln(); error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:32:13 | -LL | let _ = (x.powi(2) + 1.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` +LL | let _ = (x.powi(3) + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:33:13 @@ -143,8 +143,8 @@ LL | let _ = (1.0 + x / 2.0).ln(); error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:46:13 | -LL | let _ = (1.0 + x.powi(2)).ln(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` +LL | let _ = (1.0 + x.powi(3)).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:47:13 @@ -155,8 +155,8 @@ LL | let _ = (x + 1.0).ln(); error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:48:13 | -LL | let _ = (x.powi(2) + 1.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` +LL | let _ = (x.powi(3) + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:49:13 diff --git a/tests/ui/floating_point_powf.fixed b/tests/ui/floating_point_powf.fixed index 78a9d44829b..b0641a100cd 100644 --- a/tests/ui/floating_point_powf.fixed +++ b/tests/ui/floating_point_powf.fixed @@ -11,7 +11,7 @@ fn main() { let _ = (-3.1f32).exp(); let _ = x.sqrt(); let _ = x.cbrt(); - let _ = x.powi(2); + let _ = x.powi(3); let _ = x.powi(-2); let _ = x.powi(16_777_215); let _ = x.powi(-16_777_215); @@ -30,7 +30,7 @@ fn main() { let _ = (-3.1f64).exp(); let _ = x.sqrt(); let _ = x.cbrt(); - let _ = x.powi(2); + let _ = x.powi(3); let _ = x.powi(-2); let _ = x.powi(-2_147_483_648); let _ = x.powi(2_147_483_647); diff --git a/tests/ui/floating_point_powf.rs b/tests/ui/floating_point_powf.rs index dbc1cac5cb4..a0a2c973900 100644 --- a/tests/ui/floating_point_powf.rs +++ b/tests/ui/floating_point_powf.rs @@ -11,7 +11,7 @@ fn main() { let _ = std::f32::consts::E.powf(-3.1); let _ = x.powf(1.0 / 2.0); let _ = x.powf(1.0 / 3.0); - let _ = x.powf(2.0); + let _ = x.powf(3.0); let _ = x.powf(-2.0); let _ = x.powf(16_777_215.0); let _ = x.powf(-16_777_215.0); @@ -30,7 +30,7 @@ fn main() { let _ = std::f64::consts::E.powf(-3.1); let _ = x.powf(1.0 / 2.0); let _ = x.powf(1.0 / 3.0); - let _ = x.powf(2.0); + let _ = x.powf(3.0); let _ = x.powf(-2.0); let _ = x.powf(-2_147_483_648.0); let _ = x.powf(2_147_483_647.0); diff --git a/tests/ui/floating_point_powf.stderr b/tests/ui/floating_point_powf.stderr index ad5163f0079..2422eb911e9 100644 --- a/tests/ui/floating_point_powf.stderr +++ b/tests/ui/floating_point_powf.stderr @@ -53,8 +53,8 @@ LL | let _ = x.powf(1.0 / 3.0); error: exponentiation with integer powers can be computed more efficiently --> $DIR/floating_point_powf.rs:14:13 | -LL | let _ = x.powf(2.0); - | ^^^^^^^^^^^ help: consider using: `x.powi(2)` +LL | let _ = x.powf(3.0); + | ^^^^^^^^^^^ help: consider using: `x.powi(3)` error: exponentiation with integer powers can be computed more efficiently --> $DIR/floating_point_powf.rs:15:13 @@ -125,8 +125,8 @@ LL | let _ = x.powf(1.0 / 3.0); error: exponentiation with integer powers can be computed more efficiently --> $DIR/floating_point_powf.rs:33:13 | -LL | let _ = x.powf(2.0); - | ^^^^^^^^^^^ help: consider using: `x.powi(2)` +LL | let _ = x.powf(3.0); + | ^^^^^^^^^^^ help: consider using: `x.powi(3)` error: exponentiation with integer powers can be computed more efficiently --> $DIR/floating_point_powf.rs:34:13 diff --git a/tests/ui/floating_point_powi.fixed b/tests/ui/floating_point_powi.fixed new file mode 100644 index 00000000000..0ce6f72535d --- /dev/null +++ b/tests/ui/floating_point_powi.fixed @@ -0,0 +1,12 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] + +fn main() { + let one = 1; + let x = 3f32; + let _ = x * x; + let _ = x * x; + // Cases where the lint shouldn't be applied + let _ = x.powi(3); + let _ = x.powi(one + 1); +} diff --git a/tests/ui/floating_point_powi.rs b/tests/ui/floating_point_powi.rs new file mode 100644 index 00000000000..c87e836bedd --- /dev/null +++ b/tests/ui/floating_point_powi.rs @@ -0,0 +1,12 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] + +fn main() { + let one = 1; + let x = 3f32; + let _ = x.powi(2); + let _ = x.powi(1 + 1); + // Cases where the lint shouldn't be applied + let _ = x.powi(3); + let _ = x.powi(one + 1); +} diff --git a/tests/ui/floating_point_powi.stderr b/tests/ui/floating_point_powi.stderr new file mode 100644 index 00000000000..ae7bbaa4473 --- /dev/null +++ b/tests/ui/floating_point_powi.stderr @@ -0,0 +1,16 @@ +error: square can be computed more accurately + --> $DIR/floating_point_powi.rs:7:13 + | +LL | let _ = x.powi(2); + | ^^^^^^^^^ help: consider using: `x * x` + | + = note: `-D clippy::imprecise-flops` implied by `-D warnings` + +error: square can be computed more accurately + --> $DIR/floating_point_powi.rs:8:13 + | +LL | let _ = x.powi(1 + 1); + | ^^^^^^^^^^^^^ help: consider using: `x * x` + +error: aborting due to 2 previous errors + From f62798454c8a7f9f2c3e87e0a913b3bd79b6d2ed Mon Sep 17 00:00:00 2001 From: Thiago Arrais <thiago.arrais@gmail.com> Date: Mon, 25 May 2020 13:54:39 -0300 Subject: [PATCH 262/526] Lint (x * x + y * y).sqrt() => x.hypot(y) --- clippy_lints/src/floating_point_arithmetic.rs | 75 ++++++++++++++++++- tests/ui/floating_point_hypot.fixed | 13 ++++ tests/ui/floating_point_hypot.rs | 13 ++++ tests/ui/floating_point_hypot.stderr | 30 ++++++++ tests/ui/floating_point_mul_add.fixed | 5 ++ tests/ui/floating_point_mul_add.rs | 5 ++ tests/ui/floating_point_mul_add.stderr | 8 +- tests/ui/floating_point_powi.fixed | 7 +- tests/ui/floating_point_powi.rs | 7 +- tests/ui/floating_point_powi.stderr | 20 ++++- 10 files changed, 177 insertions(+), 6 deletions(-) create mode 100644 tests/ui/floating_point_hypot.fixed create mode 100644 tests/ui/floating_point_hypot.rs create mode 100644 tests/ui/floating_point_hypot.stderr diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index e3ee4296119..3b2e46a9a85 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -2,10 +2,10 @@ use crate::consts::{ constant, constant_simple, Constant, Constant::{Int, F32, F64}, }; -use crate::utils::{higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq}; +use crate::utils::{get_parent_expr, higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; +use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -296,6 +296,17 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { fn check_powi(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // Check argument if let Some((value, _)) = constant(cx, cx.tables, &args[1]) { + // TODO: need more specific check. this is too wide. remember also to include tests + if let Some(parent) = get_parent_expr(cx, expr) { + if let Some(grandparent) = get_parent_expr(cx, parent) { + if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args) = grandparent.kind { + if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() { + return; + } + } + } + } + let (lint, help, suggestion) = match value { Int(2) => ( IMPRECISE_FLOPS, @@ -317,6 +328,57 @@ fn check_powi(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { } } +fn detect_hypot(cx: &LateContext<'_, '_>, args: &[Expr<'_>]) -> Option<String> { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + ref add_lhs, + ref add_rhs, + ) = args[0].kind + { + // check if expression of the form x * x + y * y + if_chain! { + if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lmul_lhs, ref lmul_rhs) = add_lhs.kind; + if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref rmul_lhs, ref rmul_rhs) = add_rhs.kind; + if are_exprs_equal(cx, lmul_lhs, lmul_rhs); + if are_exprs_equal(cx, rmul_lhs, rmul_rhs); + then { + return Some(format!("{}.hypot({})", Sugg::hir(cx, &lmul_lhs, ".."), Sugg::hir(cx, &rmul_lhs, ".."))); + } + } + + // check if expression of the form x.powi(2) + y.powi(2) + if_chain! { + if let ExprKind::MethodCall(PathSegment { ident: lmethod_name, .. }, ref _lspan, ref largs) = add_lhs.kind; + if let ExprKind::MethodCall(PathSegment { ident: rmethod_name, .. }, ref _rspan, ref rargs) = add_rhs.kind; + if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi"; + if let Some((lvalue, _)) = constant(cx, cx.tables, &largs[1]); + if let Some((rvalue, _)) = constant(cx, cx.tables, &rargs[1]); + if Int(2) == lvalue && Int(2) == rvalue; + then { + return Some(format!("{}.hypot({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], ".."))); + } + } + } + + None +} + +fn check_hypot(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { + if let Some(message) = detect_hypot(cx, args) { + span_lint_and_sugg( + cx, + IMPRECISE_FLOPS, + expr.span, + "hypotenuse can be computed more accurately", + "consider using", + message, + Applicability::MachineApplicable, + ); + } +} + // TODO: Lint expressions of the form `x.exp() - y` where y > 1 // and suggest usage of `x.exp_m1() - (y - 1)` instead fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { @@ -368,6 +430,14 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { rhs, ) = &expr.kind { + if let Some(parent) = get_parent_expr(cx, expr) { + if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args) = parent.kind { + if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() { + return; + } + } + } + let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) { (inner_lhs, inner_rhs, rhs) } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) { @@ -514,6 +584,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { "log" => check_log_base(cx, expr, args), "powf" => check_powf(cx, expr, args), "powi" => check_powi(cx, expr, args), + "sqrt" => check_hypot(cx, expr, args), _ => {}, } } diff --git a/tests/ui/floating_point_hypot.fixed b/tests/ui/floating_point_hypot.fixed new file mode 100644 index 00000000000..f90695bc3fe --- /dev/null +++ b/tests/ui/floating_point_hypot.fixed @@ -0,0 +1,13 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] + +fn main() { + let x = 3f32; + let y = 4f32; + let _ = x.hypot(y); + let _ = (x + 1f32).hypot(y); + let _ = x.hypot(y); + // Cases where the lint shouldn't be applied + let _ = x.mul_add(x, y * y).sqrt(); + let _ = x.mul_add(4f32, y * y).sqrt(); +} diff --git a/tests/ui/floating_point_hypot.rs b/tests/ui/floating_point_hypot.rs new file mode 100644 index 00000000000..e7b048e262f --- /dev/null +++ b/tests/ui/floating_point_hypot.rs @@ -0,0 +1,13 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] + +fn main() { + let x = 3f32; + let y = 4f32; + let _ = (x * x + y * y).sqrt(); + let _ = ((x + 1f32) * (x + 1f32) + y * y).sqrt(); + let _ = (x.powi(2) + y.powi(2)).sqrt(); + // Cases where the lint shouldn't be applied + let _ = x.mul_add(x, y * y).sqrt(); + let _ = (x * 4f32 + y * y).sqrt(); +} diff --git a/tests/ui/floating_point_hypot.stderr b/tests/ui/floating_point_hypot.stderr new file mode 100644 index 00000000000..fe1dfc7a451 --- /dev/null +++ b/tests/ui/floating_point_hypot.stderr @@ -0,0 +1,30 @@ +error: hypotenuse can be computed more accurately + --> $DIR/floating_point_hypot.rs:7:13 + | +LL | let _ = (x * x + y * y).sqrt(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)` + | + = note: `-D clippy::imprecise-flops` implied by `-D warnings` + +error: hypotenuse can be computed more accurately + --> $DIR/floating_point_hypot.rs:8:13 + | +LL | let _ = ((x + 1f32) * (x + 1f32) + y * y).sqrt(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 1f32).hypot(y)` + +error: hypotenuse can be computed more accurately + --> $DIR/floating_point_hypot.rs:9:13 + | +LL | let _ = (x.powi(2) + y.powi(2)).sqrt(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_hypot.rs:12:13 + | +LL | let _ = (x * 4f32 + y * y).sqrt(); + | ^^^^^^^^^^^^^^^^^^ help: consider using: `x.mul_add(4f32, y * y)` + | + = note: `-D clippy::suboptimal-flops` implied by `-D warnings` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/floating_point_mul_add.fixed b/tests/ui/floating_point_mul_add.fixed index e343c37740d..911700bab00 100644 --- a/tests/ui/floating_point_mul_add.fixed +++ b/tests/ui/floating_point_mul_add.fixed @@ -18,4 +18,9 @@ fn main() { let _ = a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c)) + c; let _ = 1234.567_f64.mul_add(45.67834_f64, 0.0004_f64); + + let _ = a.mul_add(a, b).sqrt(); + + // Cases where the lint shouldn't be applied + let _ = (a * a + b * b).sqrt(); } diff --git a/tests/ui/floating_point_mul_add.rs b/tests/ui/floating_point_mul_add.rs index 810f929c856..d202385fc8a 100644 --- a/tests/ui/floating_point_mul_add.rs +++ b/tests/ui/floating_point_mul_add.rs @@ -18,4 +18,9 @@ fn main() { let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; + + let _ = (a * a + b).sqrt(); + + // Cases where the lint shouldn't be applied + let _ = (a * a + b * b).sqrt(); } diff --git a/tests/ui/floating_point_mul_add.stderr b/tests/ui/floating_point_mul_add.stderr index 2dfbf562d15..ac8d0c0cae0 100644 --- a/tests/ui/floating_point_mul_add.stderr +++ b/tests/ui/floating_point_mul_add.stderr @@ -54,5 +54,11 @@ error: multiply and add expressions can be calculated more efficiently and accur LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)` -error: aborting due to 9 previous errors +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_mul_add.rs:22:13 + | +LL | let _ = (a * a + b).sqrt(); + | ^^^^^^^^^^^ help: consider using: `a.mul_add(a, b)` + +error: aborting due to 10 previous errors diff --git a/tests/ui/floating_point_powi.fixed b/tests/ui/floating_point_powi.fixed index 0ce6f72535d..98766e68aaf 100644 --- a/tests/ui/floating_point_powi.fixed +++ b/tests/ui/floating_point_powi.fixed @@ -1,12 +1,17 @@ // run-rustfix -#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] +#![warn(clippy::imprecise_flops)] fn main() { let one = 1; let x = 3f32; let _ = x * x; let _ = x * x; + + let y = 4f32; + let _ = (x * x + y).sqrt(); + let _ = (x + y * y).sqrt(); // Cases where the lint shouldn't be applied let _ = x.powi(3); let _ = x.powi(one + 1); + let _ = x.hypot(y); } diff --git a/tests/ui/floating_point_powi.rs b/tests/ui/floating_point_powi.rs index c87e836bedd..3c4b636a3d8 100644 --- a/tests/ui/floating_point_powi.rs +++ b/tests/ui/floating_point_powi.rs @@ -1,12 +1,17 @@ // run-rustfix -#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] +#![warn(clippy::imprecise_flops)] fn main() { let one = 1; let x = 3f32; let _ = x.powi(2); let _ = x.powi(1 + 1); + + let y = 4f32; + let _ = (x.powi(2) + y).sqrt(); + let _ = (x + y.powi(2)).sqrt(); // Cases where the lint shouldn't be applied let _ = x.powi(3); let _ = x.powi(one + 1); + let _ = (x.powi(2) + y.powi(2)).sqrt(); } diff --git a/tests/ui/floating_point_powi.stderr b/tests/ui/floating_point_powi.stderr index ae7bbaa4473..f370e24bf05 100644 --- a/tests/ui/floating_point_powi.stderr +++ b/tests/ui/floating_point_powi.stderr @@ -12,5 +12,23 @@ error: square can be computed more accurately LL | let _ = x.powi(1 + 1); | ^^^^^^^^^^^^^ help: consider using: `x * x` -error: aborting due to 2 previous errors +error: square can be computed more accurately + --> $DIR/floating_point_powi.rs:11:14 + | +LL | let _ = (x.powi(2) + y).sqrt(); + | ^^^^^^^^^ help: consider using: `x * x` + +error: square can be computed more accurately + --> $DIR/floating_point_powi.rs:12:18 + | +LL | let _ = (x + y.powi(2)).sqrt(); + | ^^^^^^^^^ help: consider using: `y * y` + +error: hypotenuse can be computed more accurately + --> $DIR/floating_point_powi.rs:16:13 + | +LL | let _ = (x.powi(2) + y.powi(2)).sqrt(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)` + +error: aborting due to 5 previous errors From 2e8a1be444afc6a9b5137d3e7e4fdcfcb1f89e0d Mon Sep 17 00:00:00 2001 From: robojumper <robojumper@gmail.com> Date: Sun, 5 Jul 2020 22:10:59 +0200 Subject: [PATCH 263/526] new lint: match_like_matches_macro --- CHANGELOG.md | 1 + clippy_lints/src/matches.rs | 395 +++++++++++++++++- .../src/redundant_pattern_matching.rs | 260 ------------ src/lintlist/mod.rs | 9 +- tests/ui/find_map.rs | 1 + tests/ui/find_map.stderr | 2 +- tests/ui/match_expr_like_matches_macro.fixed | 32 ++ tests/ui/match_expr_like_matches_macro.rs | 41 ++ tests/ui/match_expr_like_matches_macro.stderr | 42 ++ tests/ui/neg_cmp_op_on_partial_ord.rs | 2 +- tests/ui/question_mark.fixed | 5 +- tests/ui/question_mark.rs | 5 +- tests/ui/question_mark.stderr | 20 +- tests/ui/redundant_pattern_matching.fixed | 8 +- tests/ui/redundant_pattern_matching.rs | 8 +- tests/ui/redundant_pattern_matching.stderr | 56 +-- ...undant_pattern_matching_const_result.fixed | 2 +- ...redundant_pattern_matching_const_result.rs | 2 +- 18 files changed, 563 insertions(+), 328 deletions(-) delete mode 100644 clippy_lints/src/redundant_pattern_matching.rs create mode 100644 tests/ui/match_expr_like_matches_macro.fixed create mode 100644 tests/ui/match_expr_like_matches_macro.rs create mode 100644 tests/ui/match_expr_like_matches_macro.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a081bb85fe..6261ca4879a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1513,6 +1513,7 @@ Released 2018-09-13 [`map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or [`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref [`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool +[`match_like_matches_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro [`match_on_vec_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_on_vec_items [`match_overlapping_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_overlapping_arm [`match_ref_pats`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_ref_pats diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index b754a45aa40..34aa2981535 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -13,14 +13,14 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::CtorKind; use rustc_hir::{ - Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Node, Pat, PatKind, - QPath, RangeEnd, + Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Guard, Local, MatchSource, Mutability, Node, Pat, + PatKind, QPath, RangeEnd, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::source_map::Span; +use rustc_span::source_map::{Span, Spanned}; use std::cmp::Ordering; use std::collections::Bound; @@ -409,6 +409,67 @@ declare_clippy_lint! { "a match on a struct that binds all fields but still uses the wildcard pattern" } +declare_clippy_lint! { + /// **What it does:** Lint for redundant pattern matching over `Result` or + /// `Option` + /// + /// **Why is this bad?** It's more concise and clear to just use the proper + /// utility function + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// if let Ok(_) = Ok::<i32, i32>(42) {} + /// if let Err(_) = Err::<i32, i32>(42) {} + /// if let None = None::<()> {} + /// if let Some(_) = Some(42) {} + /// match Ok::<i32, i32>(42) { + /// Ok(_) => true, + /// Err(_) => false, + /// }; + /// ``` + /// + /// The more idiomatic use would be: + /// + /// ```rust + /// if Ok::<i32, i32>(42).is_ok() {} + /// if Err::<i32, i32>(42).is_err() {} + /// if None::<()>.is_none() {} + /// if Some(42).is_some() {} + /// Ok::<i32, i32>(42).is_ok(); + /// ``` + pub REDUNDANT_PATTERN_MATCHING, + style, + "use the proper utility function avoiding an `if let`" +} + +declare_clippy_lint! { + /// **What it does:** Checks for `match` expressions producing a `bool` that could be written using `matches!` + /// + /// **Why is this bad?** Readability and needless complexity. + /// + /// **Known problems:** This can turn an intentionally exhaustive match into a non-exhaustive one. + /// + /// **Example:** + /// ```rust + /// let x = Some(5); + /// + /// // Bad + /// let a = match x { + /// Some(0) => true, + /// _ => false, + /// }; + /// + /// // Good + /// let a = matches!(x, Some(5)); + /// ``` + pub MATCH_LIKE_MATCHES_MACRO, + style, + "a match that could be written with the matches! macro" +} + #[derive(Default)] pub struct Matches { infallible_destructuring_match_linted: bool, @@ -427,7 +488,9 @@ impl_lint_pass!(Matches => [ WILDCARD_IN_OR_PATTERNS, MATCH_SINGLE_BINDING, INFALLIBLE_DESTRUCTURING_MATCH, - REST_PAT_IN_FULLY_BOUND_STRUCTS + REST_PAT_IN_FULLY_BOUND_STRUCTS, + REDUNDANT_PATTERN_MATCHING, + MATCH_LIKE_MATCHES_MACRO ]); impl<'tcx> LateLintPass<'tcx> for Matches { @@ -435,6 +498,11 @@ impl<'tcx> LateLintPass<'tcx> for Matches { if in_external_macro(cx.sess(), expr.span) { return; } + + if !redundant_pattern_match::check(cx, expr) { + check_match_like_matches(cx, expr); + } + if let ExprKind::Match(ref ex, ref arms, MatchSource::Normal) = expr.kind { check_single_match(cx, ex, arms, expr); check_match_bool(cx, ex, arms, expr); @@ -802,13 +870,8 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) // Some simple checks for exhaustive patterns. // There is a room for improvements to detect more cases, // but it can be more expensive to do so. - let is_pattern_exhaustive = |pat: &&Pat<'_>| { - if let PatKind::Wild | PatKind::Binding(.., None) = pat.kind { - true - } else { - false - } - }; + let is_pattern_exhaustive = + |pat: &&Pat<'_>| matches!(pat.kind, PatKind::Wild | PatKind::Binding(.., None)); if patterns.iter().all(is_pattern_exhaustive) { missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id())); } @@ -989,6 +1052,78 @@ fn check_wild_in_or_pats(cx: &LateContext<'_>, arms: &[Arm<'_>]) { } } +/// Lint a `match` or `if let .. { .. } else { .. }` expr that could be replaced by `matches!` +fn check_match_like_matches<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if let ExprKind::Match(ex, arms, ref match_source) = &expr.kind { + match match_source { + MatchSource::Normal => find_matches_sugg(cx, ex, arms, expr, false), + MatchSource::IfLetDesugar { .. } => find_matches_sugg(cx, ex, arms, expr, true), + _ => return, + } + } +} + +/// Lint a `match` or desugared `if let` for replacement by `matches!` +fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>, desugared: bool) { + if_chain! { + if arms.len() == 2; + if cx.tables().expr_ty(expr).is_bool(); + if let Some(first) = find_bool_lit(&arms[0].body.kind, desugared); + if let Some(second) = find_bool_lit(&arms[1].body.kind, desugared); + if first != second; + then { + let mut applicability = Applicability::MachineApplicable; + + let pat_and_guard = if let Some(Guard::If(g)) = arms[0].guard { + format!("{} if {}", snippet_with_applicability(cx, arms[0].pat.span, "..", &mut applicability), snippet_with_applicability(cx, g.span, "..", &mut applicability)) + } else { + format!("{}", snippet_with_applicability(cx, arms[0].pat.span, "..", &mut applicability)) + }; + span_lint_and_sugg( + cx, + MATCH_LIKE_MATCHES_MACRO, + expr.span, + &format!("{} expression looks like `matches!` macro", if desugared { "if let .. else" } else { "match" }), + "try this", + format!( + "{}matches!({}, {})", + if first { "" } else { "!" }, + snippet_with_applicability(cx, ex.span, "..", &mut applicability), + pat_and_guard, + ), + applicability, + ) + } + } +} + +/// Extract a `bool` or `{ bool }` +fn find_bool_lit(ex: &ExprKind<'_>, desugared: bool) -> Option<bool> { + match ex { + ExprKind::Lit(Spanned { + node: LitKind::Bool(b), .. + }) => Some(*b), + ExprKind::Block( + rustc_hir::Block { + stmts: &[], + expr: Some(exp), + .. + }, + _, + ) if desugared => { + if let ExprKind::Lit(Spanned { + node: LitKind::Bool(b), .. + }) = exp.kind + { + Some(b) + } else { + None + } + }, + _ => None, + } +} + fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], expr: &Expr<'_>) { if in_macro(expr.span) || arms.len() != 1 || is_refutable(cx, arms[0].pat) { return; @@ -1179,10 +1314,7 @@ fn is_unit_expr(expr: &Expr<'_>) -> bool { // Checks if arm has the form `None => None` fn is_none_arm(arm: &Arm<'_>) -> bool { - match arm.pat.kind { - PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => true, - _ => false, - } + matches!(arm.pat.kind, PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE)) } // Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`) @@ -1293,6 +1425,239 @@ where None } +mod redundant_pattern_match { + use super::REDUNDANT_PATTERN_MATCHING; + use crate::utils::{in_constant, match_qpath, match_trait_method, paths, snippet, span_lint_and_then}; + use if_chain::if_chain; + use rustc_ast::ast::LitKind; + use rustc_errors::Applicability; + use rustc_hir::{Arm, Expr, ExprKind, HirId, MatchSource, PatKind, QPath}; + use rustc_lint::LateContext; + use rustc_middle::ty; + use rustc_mir::const_eval::is_const_fn; + use rustc_span::source_map::Symbol; + + pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { + if let ExprKind::Match(op, arms, ref match_source) = &expr.kind { + match match_source { + MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms), + MatchSource::IfLetDesugar { .. } => find_sugg_for_if_let(cx, expr, op, arms, "if"), + MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, arms, "while"), + _ => false, + } + } else { + false + } + } + + fn find_sugg_for_if_let<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: &Expr<'_>, + arms: &[Arm<'_>], + keyword: &'static str, + ) -> bool { + fn find_suggestion(cx: &LateContext<'_>, hir_id: HirId, path: &QPath<'_>) -> Option<&'static str> { + if match_qpath(path, &paths::RESULT_OK) && can_suggest(cx, hir_id, sym!(result_type), "is_ok") { + return Some("is_ok()"); + } + if match_qpath(path, &paths::RESULT_ERR) && can_suggest(cx, hir_id, sym!(result_type), "is_err") { + return Some("is_err()"); + } + if match_qpath(path, &paths::OPTION_SOME) && can_suggest(cx, hir_id, sym!(option_type), "is_some") { + return Some("is_some()"); + } + if match_qpath(path, &paths::OPTION_NONE) && can_suggest(cx, hir_id, sym!(option_type), "is_none") { + return Some("is_none()"); + } + None + } + + let hir_id = expr.hir_id; + let good_method = match arms[0].pat.kind { + PatKind::TupleStruct(ref path, ref patterns, _) if patterns.len() == 1 => { + if let PatKind::Wild = patterns[0].kind { + find_suggestion(cx, hir_id, path) + } else { + None + } + }, + PatKind::Path(ref path) => find_suggestion(cx, hir_id, path), + _ => None, + }; + let good_method = match good_method { + Some(method) => method, + None => return false, + }; + + // check that `while_let_on_iterator` lint does not trigger + if_chain! { + if keyword == "while"; + if let ExprKind::MethodCall(method_path, _, _, _) = op.kind; + if method_path.ident.name == sym!(next); + if match_trait_method(cx, op, &paths::ITERATOR); + then { + return false; + } + } + + span_lint_and_then( + cx, + REDUNDANT_PATTERN_MATCHING, + arms[0].pat.span, + &format!("redundant pattern matching, consider using `{}`", good_method), + |diag| { + // while let ... = ... { ... } + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + let expr_span = expr.span; + + // while let ... = ... { ... } + // ^^^ + let op_span = op.span.source_callsite(); + + // while let ... = ... { ... } + // ^^^^^^^^^^^^^^^^^^^ + let span = expr_span.until(op_span.shrink_to_hi()); + diag.span_suggestion( + span, + "try this", + format!("{} {}.{}", keyword, snippet(cx, op_span, "_"), good_method), + Applicability::MachineApplicable, // snippet + ); + }, + ); + true + } + + fn find_sugg_for_match<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: &Expr<'_>, + arms: &[Arm<'_>], + ) -> bool { + if arms.len() == 2 { + let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind); + + let hir_id = expr.hir_id; + let found_good_method = match node_pair { + ( + PatKind::TupleStruct(ref path_left, ref patterns_left, _), + PatKind::TupleStruct(ref path_right, ref patterns_right, _), + ) if patterns_left.len() == 1 && patterns_right.len() == 1 => { + if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) { + find_good_method_for_match( + arms, + path_left, + path_right, + &paths::RESULT_OK, + &paths::RESULT_ERR, + "is_ok()", + "is_err()", + || can_suggest(cx, hir_id, sym!(result_type), "is_ok"), + || can_suggest(cx, hir_id, sym!(result_type), "is_err"), + ) + } else { + None + } + }, + (PatKind::TupleStruct(ref path_left, ref patterns, _), PatKind::Path(ref path_right)) + | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, ref patterns, _)) + if patterns.len() == 1 => + { + if let PatKind::Wild = patterns[0].kind { + find_good_method_for_match( + arms, + path_left, + path_right, + &paths::OPTION_SOME, + &paths::OPTION_NONE, + "is_some()", + "is_none()", + || can_suggest(cx, hir_id, sym!(option_type), "is_some"), + || can_suggest(cx, hir_id, sym!(option_type), "is_none"), + ) + } else { + None + } + }, + _ => None, + }; + + if let Some(good_method) = found_good_method { + span_lint_and_then( + cx, + REDUNDANT_PATTERN_MATCHING, + expr.span, + &format!("redundant pattern matching, consider using `{}`", good_method), + |diag| { + let span = expr.span.to(op.span); + diag.span_suggestion( + span, + "try this", + format!("{}.{}", snippet(cx, op.span, "_"), good_method), + Applicability::MaybeIncorrect, // snippet + ); + }, + ); + return true; + } + } + false + } + + #[allow(clippy::too_many_arguments)] + fn find_good_method_for_match<'a>( + arms: &[Arm<'_>], + path_left: &QPath<'_>, + path_right: &QPath<'_>, + expected_left: &[&str], + expected_right: &[&str], + should_be_left: &'a str, + should_be_right: &'a str, + can_suggest_left: impl Fn() -> bool, + can_suggest_right: impl Fn() -> bool, + ) -> Option<&'a str> { + let body_node_pair = if match_qpath(path_left, expected_left) && match_qpath(path_right, expected_right) { + (&(*arms[0].body).kind, &(*arms[1].body).kind) + } else if match_qpath(path_right, expected_left) && match_qpath(path_left, expected_right) { + (&(*arms[1].body).kind, &(*arms[0].body).kind) + } else { + return None; + }; + + match body_node_pair { + (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => match (&lit_left.node, &lit_right.node) { + (LitKind::Bool(true), LitKind::Bool(false)) if can_suggest_left() => Some(should_be_left), + (LitKind::Bool(false), LitKind::Bool(true)) if can_suggest_right() => Some(should_be_right), + _ => None, + }, + _ => None, + } + } + + fn can_suggest(cx: &LateContext<'_>, hir_id: HirId, diag_item: Symbol, name: &str) -> bool { + if !in_constant(cx, hir_id) { + return true; + } + + // Avoid suggesting calls to non-`const fn`s in const contexts, see #5697. + cx.tcx + .get_diagnostic_item(diag_item) + .and_then(|def_id| { + cx.tcx.inherent_impls(def_id).iter().find_map(|imp| { + cx.tcx + .associated_items(*imp) + .in_definition_order() + .find_map(|item| match item.kind { + ty::AssocKind::Fn if item.ident.name.as_str() == name => Some(item.def_id), + _ => None, + }) + }) + }) + .map_or(false, |def_id| is_const_fn(cx.tcx, def_id)) + } +} + #[test] fn test_overlapping() { use rustc_span::source_map::DUMMY_SP; diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs deleted file mode 100644 index d8d16efb978..00000000000 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ /dev/null @@ -1,260 +0,0 @@ -use crate::utils::{in_constant, match_qpath, match_trait_method, paths, snippet, span_lint_and_then}; -use if_chain::if_chain; -use rustc_ast::ast::LitKind; -use rustc_errors::Applicability; -use rustc_hir::{Arm, Expr, ExprKind, HirId, MatchSource, PatKind, QPath}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; -use rustc_mir::const_eval::is_const_fn; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Symbol; - -declare_clippy_lint! { - /// **What it does:** Lint for redundant pattern matching over `Result` or - /// `Option` - /// - /// **Why is this bad?** It's more concise and clear to just use the proper - /// utility function - /// - /// **Known problems:** None. - /// - /// **Example:** - /// - /// ```rust - /// if let Ok(_) = Ok::<i32, i32>(42) {} - /// if let Err(_) = Err::<i32, i32>(42) {} - /// if let None = None::<()> {} - /// if let Some(_) = Some(42) {} - /// match Ok::<i32, i32>(42) { - /// Ok(_) => true, - /// Err(_) => false, - /// }; - /// ``` - /// - /// The more idiomatic use would be: - /// - /// ```rust - /// if Ok::<i32, i32>(42).is_ok() {} - /// if Err::<i32, i32>(42).is_err() {} - /// if None::<()>.is_none() {} - /// if Some(42).is_some() {} - /// Ok::<i32, i32>(42).is_ok(); - /// ``` - pub REDUNDANT_PATTERN_MATCHING, - style, - "use the proper utility function avoiding an `if let`" -} - -declare_lint_pass!(RedundantPatternMatching => [REDUNDANT_PATTERN_MATCHING]); - -impl<'tcx> LateLintPass<'tcx> for RedundantPatternMatching { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Match(op, arms, ref match_source) = &expr.kind { - match match_source { - MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms), - MatchSource::IfLetDesugar { .. } => find_sugg_for_if_let(cx, expr, op, arms, "if"), - MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, arms, "while"), - _ => return, - } - } - } -} - -fn find_sugg_for_if_let<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx Expr<'_>, - op: &Expr<'_>, - arms: &[Arm<'_>], - keyword: &'static str, -) { - fn find_suggestion(cx: &LateContext<'_>, hir_id: HirId, path: &QPath<'_>) -> Option<&'static str> { - if match_qpath(path, &paths::RESULT_OK) && can_suggest(cx, hir_id, sym!(result_type), "is_ok") { - return Some("is_ok()"); - } - if match_qpath(path, &paths::RESULT_ERR) && can_suggest(cx, hir_id, sym!(result_type), "is_err") { - return Some("is_err()"); - } - if match_qpath(path, &paths::OPTION_SOME) && can_suggest(cx, hir_id, sym!(option_type), "is_some") { - return Some("is_some()"); - } - if match_qpath(path, &paths::OPTION_NONE) && can_suggest(cx, hir_id, sym!(option_type), "is_none") { - return Some("is_none()"); - } - None - } - - let hir_id = expr.hir_id; - let good_method = match arms[0].pat.kind { - PatKind::TupleStruct(ref path, ref patterns, _) if patterns.len() == 1 => { - if let PatKind::Wild = patterns[0].kind { - find_suggestion(cx, hir_id, path) - } else { - None - } - }, - PatKind::Path(ref path) => find_suggestion(cx, hir_id, path), - _ => None, - }; - let good_method = match good_method { - Some(method) => method, - None => return, - }; - - // check that `while_let_on_iterator` lint does not trigger - if_chain! { - if keyword == "while"; - if let ExprKind::MethodCall(method_path, _, _, _) = op.kind; - if method_path.ident.name == sym!(next); - if match_trait_method(cx, op, &paths::ITERATOR); - then { - return; - } - } - - span_lint_and_then( - cx, - REDUNDANT_PATTERN_MATCHING, - arms[0].pat.span, - &format!("redundant pattern matching, consider using `{}`", good_method), - |diag| { - // while let ... = ... { ... } - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - let expr_span = expr.span; - - // while let ... = ... { ... } - // ^^^ - let op_span = op.span.source_callsite(); - - // while let ... = ... { ... } - // ^^^^^^^^^^^^^^^^^^^ - let span = expr_span.until(op_span.shrink_to_hi()); - diag.span_suggestion( - span, - "try this", - format!("{} {}.{}", keyword, snippet(cx, op_span, "_"), good_method), - Applicability::MachineApplicable, // snippet - ); - }, - ); -} - -fn find_sugg_for_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op: &Expr<'_>, arms: &[Arm<'_>]) { - if arms.len() == 2 { - let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind); - - let hir_id = expr.hir_id; - let found_good_method = match node_pair { - ( - PatKind::TupleStruct(ref path_left, ref patterns_left, _), - PatKind::TupleStruct(ref path_right, ref patterns_right, _), - ) if patterns_left.len() == 1 && patterns_right.len() == 1 => { - if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) { - find_good_method_for_match( - arms, - path_left, - path_right, - &paths::RESULT_OK, - &paths::RESULT_ERR, - "is_ok()", - "is_err()", - || can_suggest(cx, hir_id, sym!(result_type), "is_ok"), - || can_suggest(cx, hir_id, sym!(result_type), "is_err"), - ) - } else { - None - } - }, - (PatKind::TupleStruct(ref path_left, ref patterns, _), PatKind::Path(ref path_right)) - | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, ref patterns, _)) - if patterns.len() == 1 => - { - if let PatKind::Wild = patterns[0].kind { - find_good_method_for_match( - arms, - path_left, - path_right, - &paths::OPTION_SOME, - &paths::OPTION_NONE, - "is_some()", - "is_none()", - || can_suggest(cx, hir_id, sym!(option_type), "is_some"), - || can_suggest(cx, hir_id, sym!(option_type), "is_none"), - ) - } else { - None - } - }, - _ => None, - }; - - if let Some(good_method) = found_good_method { - span_lint_and_then( - cx, - REDUNDANT_PATTERN_MATCHING, - expr.span, - &format!("redundant pattern matching, consider using `{}`", good_method), - |diag| { - let span = expr.span.to(op.span); - diag.span_suggestion( - span, - "try this", - format!("{}.{}", snippet(cx, op.span, "_"), good_method), - Applicability::MaybeIncorrect, // snippet - ); - }, - ); - } - } -} - -#[allow(clippy::too_many_arguments)] -fn find_good_method_for_match<'a>( - arms: &[Arm<'_>], - path_left: &QPath<'_>, - path_right: &QPath<'_>, - expected_left: &[&str], - expected_right: &[&str], - should_be_left: &'a str, - should_be_right: &'a str, - can_suggest_left: impl Fn() -> bool, - can_suggest_right: impl Fn() -> bool, -) -> Option<&'a str> { - let body_node_pair = if match_qpath(path_left, expected_left) && match_qpath(path_right, expected_right) { - (&(*arms[0].body).kind, &(*arms[1].body).kind) - } else if match_qpath(path_right, expected_left) && match_qpath(path_left, expected_right) { - (&(*arms[1].body).kind, &(*arms[0].body).kind) - } else { - return None; - }; - - match body_node_pair { - (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => match (&lit_left.node, &lit_right.node) { - (LitKind::Bool(true), LitKind::Bool(false)) if can_suggest_left() => Some(should_be_left), - (LitKind::Bool(false), LitKind::Bool(true)) if can_suggest_right() => Some(should_be_right), - _ => None, - }, - _ => None, - } -} - -fn can_suggest(cx: &LateContext<'_>, hir_id: HirId, diag_item: Symbol, name: &str) -> bool { - if !in_constant(cx, hir_id) { - return true; - } - - // Avoid suggesting calls to non-`const fn`s in const contexts, see #5697. - cx.tcx - .get_diagnostic_item(diag_item) - .and_then(|def_id| { - cx.tcx.inherent_impls(def_id).iter().find_map(|imp| { - cx.tcx - .associated_items(*imp) - .in_definition_order() - .find_map(|item| match item.kind { - ty::AssocKind::Fn if item.ident.name.as_str() == name => Some(item.def_id), - _ => None, - }) - }) - }) - .map_or(false, |def_id| is_const_fn(cx.tcx, def_id)) -} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index e681f47f949..888b4755484 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1179,6 +1179,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "matches", }, + Lint { + name: "match_like_matches_macro", + group: "style", + desc: "a match that could be written with the matches! macro", + deprecation: None, + module: "matches", + }, Lint { name: "match_on_vec_items", group: "pedantic", @@ -1856,7 +1863,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ group: "style", desc: "use the proper utility function avoiding an `if let`", deprecation: None, - module: "redundant_pattern_matching", + module: "matches", }, Lint { name: "redundant_pub_crate", diff --git a/tests/ui/find_map.rs b/tests/ui/find_map.rs index c28cca144ca..88d3b0e7490 100644 --- a/tests/ui/find_map.rs +++ b/tests/ui/find_map.rs @@ -19,6 +19,7 @@ fn main() { let _: Option<i32> = a.iter().find(|s| s.parse::<i32>().is_ok()).map(|s| s.parse().unwrap()); + #[allow(clippy::match_like_matches_macro)] let _: Option<Flavor> = desserts_of_the_week .iter() .find(|dessert| match *dessert { diff --git a/tests/ui/find_map.stderr b/tests/ui/find_map.stderr index 92f40fe6f1f..f279850fef8 100644 --- a/tests/ui/find_map.stderr +++ b/tests/ui/find_map.stderr @@ -8,7 +8,7 @@ LL | let _: Option<i32> = a.iter().find(|s| s.parse::<i32>().is_ok()).map(|s = help: this is more succinctly expressed by calling `.find_map(..)` instead error: called `find(p).map(q)` on an `Iterator` - --> $DIR/find_map.rs:22:29 + --> $DIR/find_map.rs:23:29 | LL | let _: Option<Flavor> = desserts_of_the_week | _____________________________^ diff --git a/tests/ui/match_expr_like_matches_macro.fixed b/tests/ui/match_expr_like_matches_macro.fixed new file mode 100644 index 00000000000..2d1ac8836d6 --- /dev/null +++ b/tests/ui/match_expr_like_matches_macro.fixed @@ -0,0 +1,32 @@ +// run-rustfix + +#![warn(clippy::match_like_matches_macro)] + +fn main() { + let x = Some(5); + + // Lint + let _y = matches!(x, Some(0)); + + // Turn into is_none + let _z = x.is_none(); + + // Lint + let _z = !matches!(x, Some(r) if r == 0); + + // Lint + let _zz = matches!(x, Some(5)); + + // No lint + let _a = match x { + Some(_) => false, + None => false, + }; + + // No lint + let _a = match x { + Some(0) => false, + Some(_) => true, + None => false, + }; +} diff --git a/tests/ui/match_expr_like_matches_macro.rs b/tests/ui/match_expr_like_matches_macro.rs new file mode 100644 index 00000000000..376abf9244e --- /dev/null +++ b/tests/ui/match_expr_like_matches_macro.rs @@ -0,0 +1,41 @@ +// run-rustfix + +#![warn(clippy::match_like_matches_macro)] + +fn main() { + let x = Some(5); + + // Lint + let _y = match x { + Some(0) => true, + _ => false, + }; + + // Turn into is_none + let _z = match x { + Some(_) => false, + None => true, + }; + + // Lint + let _z = match x { + Some(r) if r == 0 => false, + _ => true, + }; + + // Lint + let _zz = if let Some(5) = x { true } else { false }; + + // No lint + let _a = match x { + Some(_) => false, + None => false, + }; + + // No lint + let _a = match x { + Some(0) => false, + Some(_) => true, + None => false, + }; +} diff --git a/tests/ui/match_expr_like_matches_macro.stderr b/tests/ui/match_expr_like_matches_macro.stderr new file mode 100644 index 00000000000..0b32af039a8 --- /dev/null +++ b/tests/ui/match_expr_like_matches_macro.stderr @@ -0,0 +1,42 @@ +error: match expression looks like `matches!` macro + --> $DIR/match_expr_like_matches_macro.rs:9:14 + | +LL | let _y = match x { + | ______________^ +LL | | Some(0) => true, +LL | | _ => false, +LL | | }; + | |_____^ help: try this: `matches!(x, Some(0))` + | + = note: `-D clippy::match-like-matches-macro` implied by `-D warnings` + +error: redundant pattern matching, consider using `is_none()` + --> $DIR/match_expr_like_matches_macro.rs:15:14 + | +LL | let _z = match x { + | ______________^ +LL | | Some(_) => false, +LL | | None => true, +LL | | }; + | |_____^ help: try this: `x.is_none()` + | + = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + +error: match expression looks like `matches!` macro + --> $DIR/match_expr_like_matches_macro.rs:21:14 + | +LL | let _z = match x { + | ______________^ +LL | | Some(r) if r == 0 => false, +LL | | _ => true, +LL | | }; + | |_____^ help: try this: `!matches!(x, Some(r) if r == 0)` + +error: if let .. else expression looks like `matches!` macro + --> $DIR/match_expr_like_matches_macro.rs:27:15 + | +LL | let _zz = if let Some(5) = x { true } else { false }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index ca70e3b7148..0cee0a28fc7 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -4,7 +4,7 @@ use std::cmp::Ordering; -#[allow(clippy::unnested_or_patterns)] +#[allow(clippy::unnested_or_patterns, clippy::match_like_matches_macro)] #[warn(clippy::neg_cmp_op_on_partial_ord)] fn main() { let a_value = 1.0; diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index 11dff94a288..bd13cf1bdfa 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -23,10 +23,7 @@ pub enum SeemsOption<T> { impl<T> SeemsOption<T> { pub fn is_none(&self) -> bool { - match *self { - SeemsOption::None => true, - SeemsOption::Some(_) => false, - } + matches!(*self, SeemsOption::None) } } diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 1d0ee82b4f7..94479e68555 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -25,10 +25,7 @@ pub enum SeemsOption<T> { impl<T> SeemsOption<T> { pub fn is_none(&self) -> bool { - match *self { - SeemsOption::None => true, - SeemsOption::Some(_) => false, - } + matches!(*self, SeemsOption::None) } } diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 502615fb175..be323035d6c 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:50:9 + --> $DIR/question_mark.rs:47:9 | LL | / if (self.opt).is_none() { LL | | return None; @@ -17,7 +17,7 @@ LL | | } | |_________^ help: replace it with: `(self.opt)?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:54:9 + --> $DIR/question_mark.rs:51:9 | LL | / if self.opt.is_none() { LL | | return None @@ -25,7 +25,7 @@ LL | | } | |_________^ help: replace it with: `self.opt?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:58:17 + --> $DIR/question_mark.rs:55:17 | LL | let _ = if self.opt.is_none() { | _________________^ @@ -36,7 +36,7 @@ LL | | }; | |_________^ help: replace it with: `Some(self.opt?)` error: this if-let-else may be rewritten with the `?` operator - --> $DIR/question_mark.rs:64:17 + --> $DIR/question_mark.rs:61:17 | LL | let _ = if let Some(x) = self.opt { | _________________^ @@ -47,7 +47,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:81:9 + --> $DIR/question_mark.rs:78:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -55,7 +55,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:89:9 + --> $DIR/question_mark.rs:86:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -63,7 +63,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:97:9 + --> $DIR/question_mark.rs:94:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -71,7 +71,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this if-let-else may be rewritten with the `?` operator - --> $DIR/question_mark.rs:104:26 + --> $DIR/question_mark.rs:101:26 | LL | let v: &Vec<_> = if let Some(ref v) = self.opt { | __________________________^ @@ -82,7 +82,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt.as_ref()?` error: this if-let-else may be rewritten with the `?` operator - --> $DIR/question_mark.rs:114:17 + --> $DIR/question_mark.rs:111:17 | LL | let v = if let Some(v) = self.opt { | _________________^ @@ -93,7 +93,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:129:5 + --> $DIR/question_mark.rs:126:5 | LL | / if f().is_none() { LL | | return None; diff --git a/tests/ui/redundant_pattern_matching.fixed b/tests/ui/redundant_pattern_matching.fixed index 8b4e2d21331..ce8582d2b22 100644 --- a/tests/ui/redundant_pattern_matching.fixed +++ b/tests/ui/redundant_pattern_matching.fixed @@ -2,7 +2,13 @@ #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] -#![allow(clippy::unit_arg, unused_must_use, clippy::needless_bool, deprecated)] +#![allow( + clippy::unit_arg, + unused_must_use, + clippy::needless_bool, + clippy::match_like_matches_macro, + deprecated +)] fn main() { if Ok::<i32, i32>(42).is_ok() {} diff --git a/tests/ui/redundant_pattern_matching.rs b/tests/ui/redundant_pattern_matching.rs index b0904e41b6f..a3a9aa40e3b 100644 --- a/tests/ui/redundant_pattern_matching.rs +++ b/tests/ui/redundant_pattern_matching.rs @@ -2,7 +2,13 @@ #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] -#![allow(clippy::unit_arg, unused_must_use, clippy::needless_bool, deprecated)] +#![allow( + clippy::unit_arg, + unused_must_use, + clippy::needless_bool, + clippy::match_like_matches_macro, + deprecated +)] fn main() { if let Ok(_) = Ok::<i32, i32>(42) {} diff --git a/tests/ui/redundant_pattern_matching.stderr b/tests/ui/redundant_pattern_matching.stderr index 51a6f4350d3..25d1476062e 100644 --- a/tests/ui/redundant_pattern_matching.stderr +++ b/tests/ui/redundant_pattern_matching.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:8:12 + --> $DIR/redundant_pattern_matching.rs:14:12 | LL | if let Ok(_) = Ok::<i32, i32>(42) {} | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()` @@ -7,67 +7,67 @@ LL | if let Ok(_) = Ok::<i32, i32>(42) {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:10:12 + --> $DIR/redundant_pattern_matching.rs:16:12 | LL | if let Err(_) = Err::<i32, i32>(42) {} | -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:12:12 + --> $DIR/redundant_pattern_matching.rs:18:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:14:12 + --> $DIR/redundant_pattern_matching.rs:20:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:16:12 + --> $DIR/redundant_pattern_matching.rs:22:12 | LL | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:22:15 + --> $DIR/redundant_pattern_matching.rs:28:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:24:15 + --> $DIR/redundant_pattern_matching.rs:30:15 | LL | while let None = Some(42) {} | ----------^^^^----------- help: try this: `while Some(42).is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:26:15 + --> $DIR/redundant_pattern_matching.rs:32:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try this: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:28:15 + --> $DIR/redundant_pattern_matching.rs:34:15 | LL | while let Ok(_) = Ok::<i32, i32>(10) {} | ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:30:15 + --> $DIR/redundant_pattern_matching.rs:36:15 | LL | while let Err(_) = Ok::<i32, i32>(10) {} | ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:33:15 + --> $DIR/redundant_pattern_matching.rs:39:15 | LL | while let Some(_) = v.pop() { | ----------^^^^^^^---------- help: try this: `while v.pop().is_some()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:49:5 + --> $DIR/redundant_pattern_matching.rs:55:5 | LL | / match Ok::<i32, i32>(42) { LL | | Ok(_) => true, @@ -76,7 +76,7 @@ LL | | }; | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:54:5 + --> $DIR/redundant_pattern_matching.rs:60:5 | LL | / match Ok::<i32, i32>(42) { LL | | Ok(_) => false, @@ -85,7 +85,7 @@ LL | | }; | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:59:5 + --> $DIR/redundant_pattern_matching.rs:65:5 | LL | / match Err::<i32, i32>(42) { LL | | Ok(_) => false, @@ -94,7 +94,7 @@ LL | | }; | |_____^ help: try this: `Err::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:64:5 + --> $DIR/redundant_pattern_matching.rs:70:5 | LL | / match Err::<i32, i32>(42) { LL | | Ok(_) => true, @@ -103,7 +103,7 @@ LL | | }; | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:69:5 + --> $DIR/redundant_pattern_matching.rs:75:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -112,7 +112,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:74:5 + --> $DIR/redundant_pattern_matching.rs:80:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -121,7 +121,7 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:79:13 + --> $DIR/redundant_pattern_matching.rs:85:13 | LL | let _ = match None::<()> { | _____________^ @@ -131,61 +131,61 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:84:20 + --> $DIR/redundant_pattern_matching.rs:90:20 | LL | let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false }; | -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:87:20 + --> $DIR/redundant_pattern_matching.rs:93:20 | LL | let x = if let Some(_) = opt { true } else { false }; | -------^^^^^^^------ help: try this: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:93:20 + --> $DIR/redundant_pattern_matching.rs:99:20 | LL | let _ = if let Some(_) = gen_opt() { | -------^^^^^^^------------ help: try this: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:95:19 + --> $DIR/redundant_pattern_matching.rs:101:19 | LL | } else if let None = gen_opt() { | -------^^^^------------ help: try this: `if gen_opt().is_none()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:97:19 + --> $DIR/redundant_pattern_matching.rs:103:19 | LL | } else if let Ok(_) = gen_res() { | -------^^^^^------------ help: try this: `if gen_res().is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:99:19 + --> $DIR/redundant_pattern_matching.rs:105:19 | LL | } else if let Err(_) = gen_res() { | -------^^^^^^------------ help: try this: `if gen_res().is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:132:19 + --> $DIR/redundant_pattern_matching.rs:138:19 | LL | while let Some(_) = r#try!(result_opt()) {} | ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:133:16 + --> $DIR/redundant_pattern_matching.rs:139:16 | LL | if let Some(_) = r#try!(result_opt()) {} | -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:139:12 + --> $DIR/redundant_pattern_matching.rs:145:12 | LL | if let Some(_) = m!() {} | -------^^^^^^^------- help: try this: `if m!().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:140:15 + --> $DIR/redundant_pattern_matching.rs:146:15 | LL | while let Some(_) = m!() {} | ----------^^^^^^^------- help: try this: `while m!().is_some()` diff --git a/tests/ui/redundant_pattern_matching_const_result.fixed b/tests/ui/redundant_pattern_matching_const_result.fixed index 8a81e92f04a..de3fe00d5fa 100644 --- a/tests/ui/redundant_pattern_matching_const_result.fixed +++ b/tests/ui/redundant_pattern_matching_const_result.fixed @@ -2,7 +2,7 @@ #![feature(const_result)] #![warn(clippy::redundant_pattern_matching)] -#![allow(unused)] +#![allow(clippy::match_like_matches_macro, unused)] // Test that results are linted with the feature enabled. diff --git a/tests/ui/redundant_pattern_matching_const_result.rs b/tests/ui/redundant_pattern_matching_const_result.rs index 1cd515441d1..b77969d53d9 100644 --- a/tests/ui/redundant_pattern_matching_const_result.rs +++ b/tests/ui/redundant_pattern_matching_const_result.rs @@ -2,7 +2,7 @@ #![feature(const_result)] #![warn(clippy::redundant_pattern_matching)] -#![allow(unused)] +#![allow(clippy::match_like_matches_macro, unused)] // Test that results are linted with the feature enabled. From 0c8afa39ce8b2e7f0f9be7fc33fe3993d9bc3c53 Mon Sep 17 00:00:00 2001 From: Thiago Arrais <thiago.arrais@gmail.com> Date: Mon, 1 Jun 2020 18:32:52 -0300 Subject: [PATCH 264/526] Lint x.log(b) / y.log(b) => x.log(y) --- clippy_lints/src/floating_point_arithmetic.rs | 65 ++++++++++++++++--- tests/ui/floating_point_logbase.fixed | 16 +++++ tests/ui/floating_point_logbase.rs | 16 +++++ tests/ui/floating_point_logbase.stderr | 28 ++++++++ 4 files changed, 115 insertions(+), 10 deletions(-) create mode 100644 tests/ui/floating_point_logbase.fixed create mode 100644 tests/ui/floating_point_logbase.rs create mode 100644 tests/ui/floating_point_logbase.stderr diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 3b2e46a9a85..9f241c2c3a2 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -293,13 +293,13 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { } } -fn check_powi(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { +fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // Check argument - if let Some((value, _)) = constant(cx, cx.tables, &args[1]) { + if let Some((value, _)) = constant(cx, cx.tables(), &args[1]) { // TODO: need more specific check. this is too wide. remember also to include tests if let Some(parent) = get_parent_expr(cx, expr) { if let Some(grandparent) = get_parent_expr(cx, parent) { - if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args) = grandparent.kind { + if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = grandparent.kind { if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() { return; } @@ -328,7 +328,7 @@ fn check_powi(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { } } -fn detect_hypot(cx: &LateContext<'_, '_>, args: &[Expr<'_>]) -> Option<String> { +fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> { if let ExprKind::Binary( Spanned { node: BinOpKind::Add, .. @@ -350,11 +350,11 @@ fn detect_hypot(cx: &LateContext<'_, '_>, args: &[Expr<'_>]) -> Option<String> { // check if expression of the form x.powi(2) + y.powi(2) if_chain! { - if let ExprKind::MethodCall(PathSegment { ident: lmethod_name, .. }, ref _lspan, ref largs) = add_lhs.kind; - if let ExprKind::MethodCall(PathSegment { ident: rmethod_name, .. }, ref _rspan, ref rargs) = add_rhs.kind; + if let ExprKind::MethodCall(PathSegment { ident: lmethod_name, .. }, ref _lspan, ref largs, _) = add_lhs.kind; + if let ExprKind::MethodCall(PathSegment { ident: rmethod_name, .. }, ref _rspan, ref rargs, _) = add_rhs.kind; if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi"; - if let Some((lvalue, _)) = constant(cx, cx.tables, &largs[1]); - if let Some((rvalue, _)) = constant(cx, cx.tables, &rargs[1]); + if let Some((lvalue, _)) = constant(cx, cx.tables(), &largs[1]); + if let Some((rvalue, _)) = constant(cx, cx.tables(), &rargs[1]); if Int(2) == lvalue && Int(2) == rvalue; then { return Some(format!("{}.hypot({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], ".."))); @@ -365,7 +365,7 @@ fn detect_hypot(cx: &LateContext<'_, '_>, args: &[Expr<'_>]) -> Option<String> { None } -fn check_hypot(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { +fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { if let Some(message) = detect_hypot(cx, args) { span_lint_and_sugg( cx, @@ -431,7 +431,7 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { ) = &expr.kind { if let Some(parent) = get_parent_expr(cx, expr) { - if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args) = parent.kind { + if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = parent.kind { if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() { return; } @@ -573,6 +573,50 @@ fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { } } +fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool { + if_chain! { + if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, ref args_a, _) = expr_a.kind; + if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, ref args_b, _) = expr_b.kind; + then { + return method_name_a.as_str() == method_name_b.as_str() && + args_a.len() == args_b.len() && + ( + ["ln", "log2", "log10"].contains(&&*method_name_a.as_str()) || + method_name_a.as_str() == "log" && args_a.len() == 2 && are_exprs_equal(cx, &args_a[1], &args_b[1]) + ); + } + } + + false +} + +fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { + // check if expression of the form x.logN() / y.logN() + if_chain! { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Div, .. + }, + lhs, + rhs, + ) = &expr.kind; + if are_same_base_logs(cx, lhs, rhs); + if let ExprKind::MethodCall(_, _, ref largs, _) = lhs.kind; + if let ExprKind::MethodCall(_, _, ref rargs, _) = rhs.kind; + then { + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "division of logarithms can be calculated more efficiently and accurately", + "consider using", + format!("{}.log({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], ".."),), + Applicability::MachineApplicable, + ); + } + } +} + impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::MethodCall(ref path, _, args, _) = &expr.kind { @@ -592,6 +636,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { check_expm1(cx, expr); check_mul_add(cx, expr); check_custom_abs(cx, expr); + check_log_division(cx, expr); } } } diff --git a/tests/ui/floating_point_logbase.fixed b/tests/ui/floating_point_logbase.fixed new file mode 100644 index 00000000000..13962a272d4 --- /dev/null +++ b/tests/ui/floating_point_logbase.fixed @@ -0,0 +1,16 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops)] + +fn main() { + let x = 3f32; + let y = 5f32; + let _ = x.log(y); + let _ = x.log(y); + let _ = x.log(y); + let _ = x.log(y); + // Cases where the lint shouldn't be applied + let _ = x.ln() / y.powf(3.2); + let _ = x.powf(3.2) / y.powf(3.2); + let _ = x.powf(3.2) / y.ln(); + let _ = x.log(5f32) / y.log(7f32); +} diff --git a/tests/ui/floating_point_logbase.rs b/tests/ui/floating_point_logbase.rs new file mode 100644 index 00000000000..26bc20d5370 --- /dev/null +++ b/tests/ui/floating_point_logbase.rs @@ -0,0 +1,16 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops)] + +fn main() { + let x = 3f32; + let y = 5f32; + let _ = x.ln() / y.ln(); + let _ = x.log2() / y.log2(); + let _ = x.log10() / y.log10(); + let _ = x.log(5f32) / y.log(5f32); + // Cases where the lint shouldn't be applied + let _ = x.ln() / y.powf(3.2); + let _ = x.powf(3.2) / y.powf(3.2); + let _ = x.powf(3.2) / y.ln(); + let _ = x.log(5f32) / y.log(7f32); +} diff --git a/tests/ui/floating_point_logbase.stderr b/tests/ui/floating_point_logbase.stderr new file mode 100644 index 00000000000..fa956b9139e --- /dev/null +++ b/tests/ui/floating_point_logbase.stderr @@ -0,0 +1,28 @@ +error: division of logarithms can be calculated more efficiently and accurately + --> $DIR/floating_point_logbase.rs:7:13 + | +LL | let _ = x.ln() / y.ln(); + | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + | + = note: `-D clippy::suboptimal-flops` implied by `-D warnings` + +error: division of logarithms can be calculated more efficiently and accurately + --> $DIR/floating_point_logbase.rs:8:13 + | +LL | let _ = x.log2() / y.log2(); + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: division of logarithms can be calculated more efficiently and accurately + --> $DIR/floating_point_logbase.rs:9:13 + | +LL | let _ = x.log10() / y.log10(); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: division of logarithms can be calculated more efficiently and accurately + --> $DIR/floating_point_logbase.rs:10:13 + | +LL | let _ = x.log(5f32) / y.log(5f32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: aborting due to 4 previous errors + From 1740dda76386aff7205b2a709a32c95e8cbc0d57 Mon Sep 17 00:00:00 2001 From: robojumper <robojumper@gmail.com> Date: Sun, 5 Jul 2020 22:11:19 +0200 Subject: [PATCH 265/526] fix match_like_matches_macro in clippy --- clippy_lints/src/assign_ops.rs | 1 + clippy_lints/src/comparison_chain.rs | 5 +--- clippy_lints/src/eq_op.rs | 30 +++++++++++------------ clippy_lints/src/escape.rs | 5 +--- clippy_lints/src/eta_reduction.rs | 5 +--- clippy_lints/src/formatting.rs | 12 ++------- clippy_lints/src/functions.rs | 8 +----- clippy_lints/src/lib.rs | 11 +++++---- clippy_lints/src/lifetimes.rs | 16 ++++++------ clippy_lints/src/loops.rs | 10 ++------ clippy_lints/src/methods/mod.rs | 16 ++++-------- clippy_lints/src/misc.rs | 7 +----- clippy_lints/src/misc_early.rs | 18 +++++--------- clippy_lints/src/missing_inline.rs | 9 ++++--- clippy_lints/src/new_without_default.rs | 10 +++++--- clippy_lints/src/non_copy_const.rs | 8 +++--- clippy_lints/src/precedence.rs | 10 ++------ clippy_lints/src/regex.rs | 7 +----- clippy_lints/src/shadow.rs | 5 +--- clippy_lints/src/temporary_assignment.rs | 8 +----- clippy_lints/src/types.rs | 29 ++++++---------------- clippy_lints/src/unnamed_address.rs | 14 ++++------- clippy_lints/src/use_self.rs | 6 ++--- clippy_lints/src/utils/ast_utils.rs | 5 +--- clippy_lints/src/utils/mod.rs | 11 ++------- clippy_lints/src/utils/numeric_literal.rs | 2 +- src/driver.rs | 9 ++----- 27 files changed, 91 insertions(+), 186 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index bc6e868823f..3d48bf739eb 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -237,6 +237,7 @@ fn is_commutative(op: hir::BinOpKind) -> bool { use rustc_hir::BinOpKind::{ Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub, }; + #[allow(clippy::match_like_matches_macro)] match op { Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true, Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false, diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index 26476af4cb6..25ccabc1c88 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -122,8 +122,5 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain { } fn kind_is_cmp(kind: BinOpKind) -> bool { - match kind { - BinOpKind::Lt | BinOpKind::Gt | BinOpKind::Eq => true, - _ => false, - } + matches!(kind, BinOpKind::Lt | BinOpKind::Gt | BinOpKind::Eq) } diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index ca921dcfdfe..7839908fe4c 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -214,20 +214,20 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { } fn is_valid_operator(op: BinOp) -> bool { - match op.node { + matches!( + op.node, BinOpKind::Sub - | BinOpKind::Div - | BinOpKind::Eq - | BinOpKind::Lt - | BinOpKind::Le - | BinOpKind::Gt - | BinOpKind::Ge - | BinOpKind::Ne - | BinOpKind::And - | BinOpKind::Or - | BinOpKind::BitXor - | BinOpKind::BitAnd - | BinOpKind::BitOr => true, - _ => false, - } + | BinOpKind::Div + | BinOpKind::Eq + | BinOpKind::Lt + | BinOpKind::Le + | BinOpKind::Gt + | BinOpKind::Ge + | BinOpKind::Ne + | BinOpKind::And + | BinOpKind::Or + | BinOpKind::BitXor + | BinOpKind::BitAnd + | BinOpKind::BitOr + ) } diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index d40cdfcca9f..32fc01149d8 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -105,10 +105,7 @@ fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool { _ => return false, } - match map.find(map.get_parent_node(id)) { - Some(Node::Param(_)) => true, - _ => false, - } + matches!(map.find(map.get_parent_node(id)), Some(Node::Param(_))) } impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index ceed6a74c4f..fb26b9fc27d 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -175,10 +175,7 @@ fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_a fn match_borrow_depth(lhs: Ty<'_>, rhs: Ty<'_>) -> bool { match (&lhs.kind, &rhs.kind) { (ty::Ref(_, t1, mut1), ty::Ref(_, t2, mut2)) => mut1 == mut2 && match_borrow_depth(&t1, &t2), - (l, r) => match (l, r) { - (ty::Ref(_, _, _), _) | (_, ty::Ref(_, _, _)) => false, - (_, _) => true, - }, + (l, r) => !matches!((l, r), (ty::Ref(_, _, _), _) | (_, ty::Ref(_, _, _))), } } diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 156246fb8bb..1bd16e6cce5 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -305,18 +305,10 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) { } fn is_block(expr: &Expr) -> bool { - if let ExprKind::Block(..) = expr.kind { - true - } else { - false - } + matches!(expr.kind, ExprKind::Block(..)) } /// Check if the expression is an `if` or `if let` fn is_if(expr: &Expr) -> bool { - if let ExprKind::If(..) = expr.kind { - true - } else { - false - } + matches!(expr.kind, ExprKind::If(..)) } diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 3f030dd8422..63133a4872a 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -645,13 +645,7 @@ fn is_mutated_static(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> bool { use hir::ExprKind::{Field, Index, Path}; match e.kind { - Path(ref qpath) => { - if let Res::Local(_) = qpath_res(cx, qpath, e.hir_id) { - false - } else { - true - } - }, + Path(ref qpath) => !matches!(qpath_res(cx, qpath, e.hir_id), Res::Local(_)), Field(ref inner, _) | Index(ref inner, _) => is_mutated_static(cx, inner), _ => false, } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index fe34e4390d6..c4f1af8f4e4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -277,7 +277,6 @@ mod question_mark; mod ranges; mod redundant_clone; mod redundant_field_names; -mod redundant_pattern_matching; mod redundant_pub_crate; mod redundant_static_lifetimes; mod reference; @@ -623,11 +622,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &matches::INFALLIBLE_DESTRUCTURING_MATCH, &matches::MATCH_AS_REF, &matches::MATCH_BOOL, + &matches::MATCH_LIKE_MATCHES_MACRO, &matches::MATCH_OVERLAPPING_ARM, &matches::MATCH_REF_PATS, &matches::MATCH_SINGLE_BINDING, &matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS, &matches::MATCH_WILD_ERR_ARM, + &matches::REDUNDANT_PATTERN_MATCHING, &matches::REST_PAT_IN_FULLY_BOUND_STRUCTS, &matches::SINGLE_MATCH, &matches::SINGLE_MATCH_ELSE, @@ -757,7 +758,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &ranges::REVERSED_EMPTY_RANGES, &redundant_clone::REDUNDANT_CLONE, &redundant_field_names::REDUNDANT_FIELD_NAMES, - &redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING, &redundant_pub_crate::REDUNDANT_PUB_CRATE, &redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES, &reference::DEREF_ADDROF, @@ -956,7 +956,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box missing_doc::MissingDoc::new()); store.register_late_pass(|| box missing_inline::MissingInline); store.register_late_pass(|| box if_let_some_result::OkIfLet); - store.register_late_pass(|| box redundant_pattern_matching::RedundantPatternMatching); store.register_late_pass(|| box partialeq_ne_impl::PartialEqNeImpl); store.register_late_pass(|| box unused_io_amount::UnusedIoAmount); let enum_variant_size_threshold = conf.enum_variant_size_threshold; @@ -1295,9 +1294,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN), LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), LintId::of(&matches::MATCH_AS_REF), + LintId::of(&matches::MATCH_LIKE_MATCHES_MACRO), LintId::of(&matches::MATCH_OVERLAPPING_ARM), LintId::of(&matches::MATCH_REF_PATS), LintId::of(&matches::MATCH_SINGLE_BINDING), + LintId::of(&matches::REDUNDANT_PATTERN_MATCHING), LintId::of(&matches::SINGLE_MATCH), LintId::of(&matches::WILDCARD_IN_OR_PATTERNS), LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), @@ -1387,7 +1388,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ranges::REVERSED_EMPTY_RANGES), LintId::of(&redundant_clone::REDUNDANT_CLONE), LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES), - LintId::of(&redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING), LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), LintId::of(&reference::DEREF_ADDROF), LintId::of(&reference::REF_IN_DEREF), @@ -1488,8 +1488,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), LintId::of(&map_clone::MAP_CLONE), LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), + LintId::of(&matches::MATCH_LIKE_MATCHES_MACRO), LintId::of(&matches::MATCH_OVERLAPPING_ARM), LintId::of(&matches::MATCH_REF_PATS), + LintId::of(&matches::REDUNDANT_PATTERN_MATCHING), LintId::of(&matches::SINGLE_MATCH), LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE), LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT), @@ -1526,7 +1528,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ptr::PTR_ARG), LintId::of(&question_mark::QUESTION_MARK), LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES), - LintId::of(&redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING), LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), LintId::of(®ex::TRIVIAL_REGEX), LintId::of(&returns::NEEDLESS_RETURN), diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index a79f94855bd..168f9f953e4 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -129,10 +129,10 @@ fn check_fn_inner<'tcx>( } let mut bounds_lts = Vec::new(); - let types = generics.params.iter().filter(|param| match param.kind { - GenericParamKind::Type { .. } => true, - _ => false, - }); + let types = generics + .params + .iter() + .filter(|param| matches!(param.kind, GenericParamKind::Type { .. })); for typ in types { for bound in typ.bounds { let mut visitor = RefVisitor::new(cx); @@ -337,10 +337,10 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> { fn collect_anonymous_lifetimes(&mut self, qpath: &QPath<'_>, ty: &Ty<'_>) { if let Some(ref last_path_segment) = last_path_segment(qpath).args { if !last_path_segment.parenthesized - && !last_path_segment.args.iter().any(|arg| match arg { - GenericArg::Lifetime(_) => true, - _ => false, - }) + && !last_path_segment + .args + .iter() + .any(|arg| matches!(arg, GenericArg::Lifetime(_))) { let hir_id = ty.hir_id; match self.cx.qpath_res(qpath, hir_id) { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index b803d753b6d..396bb659109 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2091,17 +2091,11 @@ fn var_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<HirId> { } fn is_loop(expr: &Expr<'_>) -> bool { - match expr.kind { - ExprKind::Loop(..) => true, - _ => false, - } + matches!(expr.kind, ExprKind::Loop(..)) } fn is_conditional(expr: &Expr<'_>) -> bool { - match expr.kind { - ExprKind::Match(..) => true, - _ => false, - } + matches!(expr.kind, ExprKind::Match(..)) } fn is_nested(cx: &LateContext<'_>, match_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool { diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index f1c8894c0ee..4c595029ff7 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1844,10 +1844,10 @@ fn lint_expect_fun_call( ty::Ref(ty::ReStatic, ..) ) }), - hir::ExprKind::Path(ref p) => match cx.qpath_res(p, arg.hir_id) { - hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static, _) => true, - _ => false, - }, + hir::ExprKind::Path(ref p) => matches!( + cx.qpath_res(p, arg.hir_id), + hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static, _) + ), _ => false, } } @@ -2028,13 +2028,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Exp .tables() .expr_adjustments(arg) .iter() - .filter(|adj| { - if let ty::adjustment::Adjust::Deref(_) = adj.kind { - true - } else { - false - } - }) + .filter(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(_))) .count(); let derefs: String = iter::repeat('*').take(deref_count).collect(); snip = Some(("try dereferencing it", format!("{}{}", derefs, snippet))); diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 3d4225f36a7..400f4b609af 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -694,12 +694,7 @@ fn in_attributes_expansion(expr: &Expr<'_>) -> bool { use rustc_span::hygiene::MacroKind; if expr.span.from_expansion() { let data = expr.span.ctxt().outer_expn_data(); - - if let ExpnKind::Macro(MacroKind::Attr, _) = data.kind { - true - } else { - false - } + matches!(data.kind, ExpnKind::Macro(MacroKind::Attr, _)) } else { false } diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index ad39e59d067..b84a1a3fe24 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -641,28 +641,22 @@ fn check_unneeded_wildcard_pattern(cx: &EarlyContext<'_>, pat: &Pat) { ); } - #[allow(clippy::trivially_copy_pass_by_ref)] - fn is_wild<P: std::ops::Deref<Target = Pat>>(pat: &&P) -> bool { - if let PatKind::Wild = pat.kind { - true - } else { - false - } - } - if let Some(rest_index) = patterns.iter().position(|pat| pat.is_rest()) { if let Some((left_index, left_pat)) = patterns[..rest_index] .iter() .rev() - .take_while(is_wild) + .take_while(|pat| matches!(pat.kind, PatKind::Wild)) .enumerate() .last() { span_lint(cx, left_pat.span.until(patterns[rest_index].span), left_index == 0); } - if let Some((right_index, right_pat)) = - patterns[rest_index + 1..].iter().take_while(is_wild).enumerate().last() + if let Some((right_index, right_pat)) = patterns[rest_index + 1..] + .iter() + .take_while(|pat| matches!(pat.kind, PatKind::Wild)) + .enumerate() + .last() { span_lint( cx, diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index bf80b62afe6..9c962673537 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -71,10 +71,11 @@ fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[ast::Attribute], sp fn is_executable(cx: &LateContext<'_>) -> bool { use rustc_session::config::CrateType; - cx.tcx.sess.crate_types().iter().any(|t: &CrateType| match t { - CrateType::Executable => true, - _ => false, - }) + cx.tcx + .sess + .crate_types() + .iter() + .any(|t: &CrateType| matches!(t, CrateType::Executable)) } declare_lint_pass!(MissingInline => [MISSING_INLINE_IN_PUBLIC_ITEMS]); diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 2597f5f6f17..621ebdef2f0 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -80,10 +80,12 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { // can't be implemented for unsafe new return; } - if impl_item.generics.params.iter().any(|gen| match gen.kind { - hir::GenericParamKind::Type { .. } => true, - _ => false, - }) { + if impl_item + .generics + .params + .iter() + .any(|gen| matches!(gen.kind, hir::GenericParamKind::Type { .. })) + { // when the result of `new()` depends on a type parameter we should not require // an // impl of `Default` diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index c11a2ff9ee0..a3521c31a6b 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -238,10 +238,10 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { let ty = if needs_check_adjustment { let adjustments = cx.tables().expr_adjustments(dereferenced_expr); - if let Some(i) = adjustments.iter().position(|adj| match adj.kind { - Adjust::Borrow(_) | Adjust::Deref(_) => true, - _ => false, - }) { + if let Some(i) = adjustments + .iter() + .position(|adj| matches!(adj.kind, Adjust::Borrow(_) | Adjust::Deref(_))) + { if i == 0 { cx.tables().expr_ty(dereferenced_expr) } else { diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 7dce23dd223..04be96aa64c 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -148,17 +148,11 @@ fn is_arith_expr(expr: &Expr) -> bool { #[must_use] fn is_bit_op(op: BinOpKind) -> bool { use rustc_ast::ast::BinOpKind::{BitAnd, BitOr, BitXor, Shl, Shr}; - match op { - BitXor | BitAnd | BitOr | Shl | Shr => true, - _ => false, - } + matches!(op, BitXor | BitAnd | BitOr | Shl | Shr) } #[must_use] fn is_arith_op(op: BinOpKind) -> bool { use rustc_ast::ast::BinOpKind::{Add, Div, Mul, Rem, Sub}; - match op { - Add | Sub | Mul | Div | Rem => true, - _ => false, - } + matches!(op, Add | Sub | Mul | Div | Rem) } diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index d8c8eff2c85..f204a0ffb2c 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -99,12 +99,7 @@ fn is_trivial_regex(s: ®ex_syntax::hir::Hir) -> Option<&'static str> { use regex_syntax::hir::Anchor::{EndText, StartText}; use regex_syntax::hir::HirKind::{Alternation, Anchor, Concat, Empty, Literal}; - let is_literal = |e: &[regex_syntax::hir::Hir]| { - e.iter().all(|e| match *e.kind() { - Literal(_) => true, - _ => false, - }) - }; + let is_literal = |e: &[regex_syntax::hir::Hir]| e.iter().all(|e| matches!(*e.kind(), Literal(_))); match *s.kind() { Empty | Anchor(_) => Some("the regex is unlikely to be useful as it is"), diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 4cdff63f118..194786c5c41 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -165,10 +165,7 @@ fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: & fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool { let var_ty = cx.tables().node_type_opt(pat_id); - var_ty.map_or(false, |var_ty| match var_ty.kind { - ty::Adt(..) => false, - _ => true, - }) + var_ty.map_or(false, |var_ty| !matches!(var_ty.kind, ty::Adt(..))) } fn check_pat<'tcx>( diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 509bbfd27c1..1aeff1baa36 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -25,13 +25,7 @@ declare_clippy_lint! { fn is_temporary(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match &expr.kind { ExprKind::Struct(..) | ExprKind::Tup(..) => true, - ExprKind::Path(qpath) => { - if let Res::Def(DefKind::Const, ..) = cx.qpath_res(qpath, expr.hir_id) { - true - } else { - false - } - }, + ExprKind::Path(qpath) => matches!(cx.qpath_res(qpath, expr.hir_id), Res::Def(DefKind::Const, ..)), _ => false, } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index d6f31a99bb3..71207caecf5 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -775,11 +775,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitArg { .iter() .filter(|arg| { if is_unit(cx.tables().expr_ty(arg)) && !is_unit_literal(arg) { - if let ExprKind::Match(.., MatchSource::TryDesugar) = &arg.kind { - false - } else { - true - } + !matches!(&arg.kind, ExprKind::Match(.., MatchSource::TryDesugar)) } else { false } @@ -899,17 +895,11 @@ fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool { } fn is_unit(ty: Ty<'_>) -> bool { - match ty.kind { - ty::Tuple(slice) if slice.is_empty() => true, - _ => false, - } + matches!(ty.kind, ty::Tuple(slice) if slice.is_empty()) } fn is_unit_literal(expr: &Expr<'_>) -> bool { - match expr.kind { - ExprKind::Tup(ref slice) if slice.is_empty() => true, - _ => false, - } + matches!(expr.kind, ExprKind::Tup(ref slice) if slice.is_empty()) } declare_clippy_lint! { @@ -1154,10 +1144,7 @@ fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_>) -> u64 { } fn is_isize_or_usize(typ: Ty<'_>) -> bool { - match typ.kind { - ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => true, - _ => false, - } + matches!(typ.kind, ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize)) } fn span_precision_loss_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to_f64: bool) { @@ -1737,10 +1724,10 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyKind::TraitObject(ref param_bounds, _) => { let has_lifetime_parameters = param_bounds.iter().any(|bound| { - bound.bound_generic_params.iter().any(|gen| match gen.kind { - GenericParamKind::Lifetime { .. } => true, - _ => false, - }) + bound + .bound_generic_params + .iter() + .any(|gen| matches!(gen.kind, GenericParamKind::Lifetime { .. })) }); if has_lifetime_parameters { // complex trait bounds like A<'a, 'b> diff --git a/clippy_lints/src/unnamed_address.rs b/clippy_lints/src/unnamed_address.rs index b9aa202b328..25d136e564d 100644 --- a/clippy_lints/src/unnamed_address.rs +++ b/clippy_lints/src/unnamed_address.rs @@ -58,10 +58,10 @@ declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS, VTABLE_ADDRESS_COM impl LateLintPass<'_> for UnnamedAddress { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { fn is_comparison(binop: BinOpKind) -> bool { - match binop { - BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt => true, - _ => false, - } + matches!( + binop, + BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt + ) } fn is_trait_ptr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { @@ -72,11 +72,7 @@ impl LateLintPass<'_> for UnnamedAddress { } fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - if let ty::FnDef(..) = cx.tables().expr_ty(expr).kind { - true - } else { - false - } + matches!(cx.tables().expr_ty(expr).kind, ty::FnDef(..)) } if_chain! { diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 39a8c020872..776c6bc57ca 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -169,10 +169,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; let should_check = parameters.as_ref().map_or( true, - |params| !params.parenthesized && !params.args.iter().any(|arg| match arg { - GenericArg::Lifetime(_) => true, - _ => false, - }) + |params| !params.parenthesized + &&!params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))) ); if should_check { diff --git a/clippy_lints/src/utils/ast_utils.rs b/clippy_lints/src/utils/ast_utils.rs index e19a79dd8da..58c1103da9f 100755 --- a/clippy_lints/src/utils/ast_utils.rs +++ b/clippy_lints/src/utils/ast_utils.rs @@ -387,10 +387,7 @@ pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool { } pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool { - match (l, r) { - (Defaultness::Final, Defaultness::Final) | (Defaultness::Default(_), Defaultness::Default(_)) => true, - _ => false, - } + matches!((l, r), (Defaultness::Final, Defaultness::Final) | (Defaultness::Default(_), Defaultness::Default(_))) } pub fn eq_vis(l: &Visibility, r: &Visibility) -> bool { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 3a3b79925ff..0b4cba3fc42 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -102,11 +102,7 @@ pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool { #[must_use] pub fn in_macro(span: Span) -> bool { if span.from_expansion() { - if let ExpnKind::Desugaring(..) = span.ctxt().outer_expn_data().kind { - false - } else { - true - } + !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..)) } else { false } @@ -127,10 +123,7 @@ pub fn is_present_in_source<T: LintContext>(cx: &T, span: Span) -> bool { /// Checks if given pattern is a wildcard (`_`) pub fn is_wild<'tcx>(pat: &impl std::ops::Deref<Target = Pat<'tcx>>) -> bool { - match pat.kind { - PatKind::Wild => true, - _ => false, - } + matches!(pat.kind, PatKind::Wild) } /// Checks if type is struct, enum or union type with the given def path. diff --git a/clippy_lints/src/utils/numeric_literal.rs b/clippy_lints/src/utils/numeric_literal.rs index 7a79741b30b..87cb454f654 100644 --- a/clippy_lints/src/utils/numeric_literal.rs +++ b/clippy_lints/src/utils/numeric_literal.rs @@ -51,7 +51,7 @@ impl<'a> NumericLiteral<'a> { pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option<NumericLiteral<'a>> { if lit_kind.is_numeric() && src.chars().next().map_or(false, |c| c.is_digit(10)) { let (unsuffixed, suffix) = split_suffix(&src, lit_kind); - let float = if let LitKind::Float(..) = lit_kind { true } else { false }; + let float = matches!(lit_kind, LitKind::Float(..)); Some(NumericLiteral::new(unsuffixed, suffix, float)) } else { None diff --git a/src/driver.rs b/src/driver.rs index decd3a79cce..47315fa64cd 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -382,13 +382,8 @@ pub fn main() { let should_describe_lints = || { let args: Vec<_> = env::args().collect(); - args.windows(2).any(|args| { - args[1] == "help" - && match args[0].as_str() { - "-W" | "-A" | "-D" | "-F" => true, - _ => false, - } - }) + args.windows(2) + .any(|args| args[1] == "help" && matches!(args[0].as_str(), "-W" | "-A" | "-D" | "-F")) }; if !wrapper_mode && should_describe_lints() { From 076ec872ce122403f3c75f20c773c64b194a5891 Mon Sep 17 00:00:00 2001 From: Thiago Arrais <thiago.arrais@gmail.com> Date: Wed, 10 Jun 2020 13:52:00 -0300 Subject: [PATCH 266/526] Lint for to_radians and to_degrees --- clippy_lints/src/floating_point_arithmetic.rs | 64 ++++++++++++++++++- tests/ui/floating_point_rad.fixed | 13 ++++ tests/ui/floating_point_rad.rs | 13 ++++ tests/ui/floating_point_rad.stderr | 16 +++++ 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 tests/ui/floating_point_rad.fixed create mode 100644 tests/ui/floating_point_rad.rs create mode 100644 tests/ui/floating_point_rad.stderr diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 9f241c2c3a2..d88e47f396c 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -350,8 +350,18 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> { // check if expression of the form x.powi(2) + y.powi(2) if_chain! { - if let ExprKind::MethodCall(PathSegment { ident: lmethod_name, .. }, ref _lspan, ref largs, _) = add_lhs.kind; - if let ExprKind::MethodCall(PathSegment { ident: rmethod_name, .. }, ref _rspan, ref rargs, _) = add_rhs.kind; + if let ExprKind::MethodCall( + PathSegment { ident: lmethod_name, .. }, + ref _lspan, + ref largs, + _ + ) = add_lhs.kind; + if let ExprKind::MethodCall( + PathSegment { ident: rmethod_name, .. }, + ref _rspan, + ref rargs, + _ + ) = add_rhs.kind; if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi"; if let Some((lvalue, _)) = constant(cx, cx.tables(), &largs[1]); if let Some((rvalue, _)) = constant(cx, cx.tables(), &rargs[1]); @@ -617,6 +627,55 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { } } +fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { + if_chain! { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Div, .. + }, + div_lhs, + div_rhs, + ) = &expr.kind; + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + mul_lhs, + mul_rhs, + ) = &div_lhs.kind; + if let Some((rvalue, _)) = constant(cx, cx.tables(), div_rhs); + if let Some((lvalue, _)) = constant(cx, cx.tables(), mul_rhs); + then { + if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) && + (F32(180_f32) == lvalue || F64(180_f64) == lvalue) + { + span_lint_and_sugg( + cx, + IMPRECISE_FLOPS, + expr.span, + "conversion to degrees can be done more accurately", + "consider using", + format!("{}.to_degrees()", Sugg::hir(cx, &mul_lhs, "..")), + Applicability::MachineApplicable, + ); + } else if + (F32(180_f32) == rvalue || F64(180_f64) == rvalue) && + (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue) + { + span_lint_and_sugg( + cx, + IMPRECISE_FLOPS, + expr.span, + "conversion to radians can be done more accurately", + "consider using", + format!("{}.to_radians()", Sugg::hir(cx, &mul_lhs, "..")), + Applicability::MachineApplicable, + ); + } + } + } +} + impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::MethodCall(ref path, _, args, _) = &expr.kind { @@ -637,6 +696,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { check_mul_add(cx, expr); check_custom_abs(cx, expr); check_log_division(cx, expr); + check_radians(cx, expr); } } } diff --git a/tests/ui/floating_point_rad.fixed b/tests/ui/floating_point_rad.fixed new file mode 100644 index 00000000000..64461417a6a --- /dev/null +++ b/tests/ui/floating_point_rad.fixed @@ -0,0 +1,13 @@ +// run-rustfix +#![warn(clippy::imprecise_flops)] + +fn main() { + let x = 3f32; + let _ = x.to_degrees(); + let _ = x.to_radians(); + // Cases where the lint shouldn't be applied + let _ = x * 90f32 / std::f32::consts::PI; + let _ = x * std::f32::consts::PI / 90f32; + let _ = x * 180f32 / std::f32::consts::E; + let _ = x * std::f32::consts::E / 180f32; +} diff --git a/tests/ui/floating_point_rad.rs b/tests/ui/floating_point_rad.rs new file mode 100644 index 00000000000..9046f184b3e --- /dev/null +++ b/tests/ui/floating_point_rad.rs @@ -0,0 +1,13 @@ +// run-rustfix +#![warn(clippy::imprecise_flops)] + +fn main() { + let x = 3f32; + let _ = x * 180f32 / std::f32::consts::PI; + let _ = x * std::f32::consts::PI / 180f32; + // Cases where the lint shouldn't be applied + let _ = x * 90f32 / std::f32::consts::PI; + let _ = x * std::f32::consts::PI / 90f32; + let _ = x * 180f32 / std::f32::consts::E; + let _ = x * std::f32::consts::E / 180f32; +} diff --git a/tests/ui/floating_point_rad.stderr b/tests/ui/floating_point_rad.stderr new file mode 100644 index 00000000000..81e81821513 --- /dev/null +++ b/tests/ui/floating_point_rad.stderr @@ -0,0 +1,16 @@ +error: conversion to degrees can be done more accurately + --> $DIR/floating_point_rad.rs:6:13 + | +LL | let _ = x * 180f32 / std::f32::consts::PI; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()` + | + = note: `-D clippy::imprecise-flops` implied by `-D warnings` + +error: conversion to radians can be done more accurately + --> $DIR/floating_point_rad.rs:7:13 + | +LL | let _ = x * std::f32::consts::PI / 180f32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()` + +error: aborting due to 2 previous errors + From f5596826fa59035e6c57d8968df0d61f69c2537b Mon Sep 17 00:00:00 2001 From: Thiago Arrais <thiago.arrais@gmail.com> Date: Mon, 15 Jun 2020 13:55:12 -0300 Subject: [PATCH 267/526] Better copy for lint message Since x.log(y) is actually implemented as x.ln() / y.ln() --- clippy_lints/src/floating_point_arithmetic.rs | 2 +- tests/ui/floating_point_logbase.stderr | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index d88e47f396c..b1e258f4b16 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -618,7 +618,7 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { cx, SUBOPTIMAL_FLOPS, expr.span, - "division of logarithms can be calculated more efficiently and accurately", + "log base can be expressed more clearly", "consider using", format!("{}.log({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], ".."),), Applicability::MachineApplicable, diff --git a/tests/ui/floating_point_logbase.stderr b/tests/ui/floating_point_logbase.stderr index fa956b9139e..78354c2f62d 100644 --- a/tests/ui/floating_point_logbase.stderr +++ b/tests/ui/floating_point_logbase.stderr @@ -1,4 +1,4 @@ -error: division of logarithms can be calculated more efficiently and accurately +error: log base can be expressed more clearly --> $DIR/floating_point_logbase.rs:7:13 | LL | let _ = x.ln() / y.ln(); @@ -6,19 +6,19 @@ LL | let _ = x.ln() / y.ln(); | = note: `-D clippy::suboptimal-flops` implied by `-D warnings` -error: division of logarithms can be calculated more efficiently and accurately +error: log base can be expressed more clearly --> $DIR/floating_point_logbase.rs:8:13 | LL | let _ = x.log2() / y.log2(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` -error: division of logarithms can be calculated more efficiently and accurately +error: log base can be expressed more clearly --> $DIR/floating_point_logbase.rs:9:13 | LL | let _ = x.log10() / y.log10(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` -error: division of logarithms can be calculated more efficiently and accurately +error: log base can be expressed more clearly --> $DIR/floating_point_logbase.rs:10:13 | LL | let _ = x.log(5f32) / y.log(5f32); From db7bc6b3bd0e58c8fbf7507713a4214299f39c36 Mon Sep 17 00:00:00 2001 From: Thiago Arrais <thiago.arrais@gmail.com> Date: Mon, 15 Jun 2020 13:59:44 -0300 Subject: [PATCH 268/526] Place radian lints under suboptimal_flops --- clippy_lints/src/floating_point_arithmetic.rs | 4 ++-- tests/ui/floating_point_rad.fixed | 2 +- tests/ui/floating_point_rad.rs | 2 +- tests/ui/floating_point_rad.stderr | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index b1e258f4b16..beb0b234408 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -651,7 +651,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { { span_lint_and_sugg( cx, - IMPRECISE_FLOPS, + SUBOPTIMAL_FLOPS, expr.span, "conversion to degrees can be done more accurately", "consider using", @@ -664,7 +664,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { { span_lint_and_sugg( cx, - IMPRECISE_FLOPS, + SUBOPTIMAL_FLOPS, expr.span, "conversion to radians can be done more accurately", "consider using", diff --git a/tests/ui/floating_point_rad.fixed b/tests/ui/floating_point_rad.fixed index 64461417a6a..92480c5db8b 100644 --- a/tests/ui/floating_point_rad.fixed +++ b/tests/ui/floating_point_rad.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::imprecise_flops)] +#![warn(clippy::suboptimal_flops)] fn main() { let x = 3f32; diff --git a/tests/ui/floating_point_rad.rs b/tests/ui/floating_point_rad.rs index 9046f184b3e..062e7c3fdc1 100644 --- a/tests/ui/floating_point_rad.rs +++ b/tests/ui/floating_point_rad.rs @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::imprecise_flops)] +#![warn(clippy::suboptimal_flops)] fn main() { let x = 3f32; diff --git a/tests/ui/floating_point_rad.stderr b/tests/ui/floating_point_rad.stderr index 81e81821513..a6ffdca64ee 100644 --- a/tests/ui/floating_point_rad.stderr +++ b/tests/ui/floating_point_rad.stderr @@ -4,7 +4,7 @@ error: conversion to degrees can be done more accurately LL | let _ = x * 180f32 / std::f32::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()` | - = note: `-D clippy::imprecise-flops` implied by `-D warnings` + = note: `-D clippy::suboptimal-flops` implied by `-D warnings` error: conversion to radians can be done more accurately --> $DIR/floating_point_rad.rs:7:13 From 6dc066fdb9103122cd918b1b38e26fa6edbc7e2e Mon Sep 17 00:00:00 2001 From: Thiago Arrais <thiago.arrais@gmail.com> Date: Wed, 17 Jun 2020 13:43:11 -0300 Subject: [PATCH 269/526] Includes TODO comment for hypot lint --- tests/ui/floating_point_hypot.fixed | 5 +++-- tests/ui/floating_point_hypot.rs | 3 ++- tests/ui/floating_point_hypot.stderr | 10 +--------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/tests/ui/floating_point_hypot.fixed b/tests/ui/floating_point_hypot.fixed index f90695bc3fe..bbe411b3f48 100644 --- a/tests/ui/floating_point_hypot.fixed +++ b/tests/ui/floating_point_hypot.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] +#![warn(clippy::imprecise_flops)] fn main() { let x = 3f32; @@ -8,6 +8,7 @@ fn main() { let _ = (x + 1f32).hypot(y); let _ = x.hypot(y); // Cases where the lint shouldn't be applied + // TODO: linting this adds some complexity, but could be done let _ = x.mul_add(x, y * y).sqrt(); - let _ = x.mul_add(4f32, y * y).sqrt(); + let _ = (x * 4f32 + y * y).sqrt(); } diff --git a/tests/ui/floating_point_hypot.rs b/tests/ui/floating_point_hypot.rs index e7b048e262f..586fd170ea1 100644 --- a/tests/ui/floating_point_hypot.rs +++ b/tests/ui/floating_point_hypot.rs @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] +#![warn(clippy::imprecise_flops)] fn main() { let x = 3f32; @@ -8,6 +8,7 @@ fn main() { let _ = ((x + 1f32) * (x + 1f32) + y * y).sqrt(); let _ = (x.powi(2) + y.powi(2)).sqrt(); // Cases where the lint shouldn't be applied + // TODO: linting this adds some complexity, but could be done let _ = x.mul_add(x, y * y).sqrt(); let _ = (x * 4f32 + y * y).sqrt(); } diff --git a/tests/ui/floating_point_hypot.stderr b/tests/ui/floating_point_hypot.stderr index fe1dfc7a451..42069d9ee9e 100644 --- a/tests/ui/floating_point_hypot.stderr +++ b/tests/ui/floating_point_hypot.stderr @@ -18,13 +18,5 @@ error: hypotenuse can be computed more accurately LL | let _ = (x.powi(2) + y.powi(2)).sqrt(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)` -error: multiply and add expressions can be calculated more efficiently and accurately - --> $DIR/floating_point_hypot.rs:12:13 - | -LL | let _ = (x * 4f32 + y * y).sqrt(); - | ^^^^^^^^^^^^^^^^^^ help: consider using: `x.mul_add(4f32, y * y)` - | - = note: `-D clippy::suboptimal-flops` implied by `-D warnings` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors From 6be9491eace540d341f3b8dbf775a10e25f6431a Mon Sep 17 00:00:00 2001 From: Thiago Arrais <thiago.arrais@gmail.com> Date: Mon, 22 Jun 2020 14:16:27 -0300 Subject: [PATCH 270/526] Reclassify powi(2) lint under suboptimal_flops --- clippy_lints/src/floating_point_arithmetic.rs | 69 ++++++++++++------- tests/ui/floating_point_powi.fixed | 10 +-- tests/ui/floating_point_powi.rs | 4 +- tests/ui/floating_point_powi.stderr | 38 +++++----- 4 files changed, 75 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index beb0b234408..11bd0ae23aa 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -294,37 +294,56 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { } fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { - // Check argument if let Some((value, _)) = constant(cx, cx.tables(), &args[1]) { - // TODO: need more specific check. this is too wide. remember also to include tests - if let Some(parent) = get_parent_expr(cx, expr) { - if let Some(grandparent) = get_parent_expr(cx, parent) { - if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = grandparent.kind { - if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() { - return; + if value == Int(2) { + if let Some(parent) = get_parent_expr(cx, expr) { + if let Some(grandparent) = get_parent_expr(cx, parent) { + if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = grandparent.kind { + if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() { + return; + } } } + + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + ref lhs, + ref rhs, + ) = parent.kind + { + let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs }; + + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + parent.span, + "square can be computed more efficiently", + "consider using", + format!( + "{}.mul_add({}, {})", + Sugg::hir(cx, &args[0], ".."), + Sugg::hir(cx, &args[0], ".."), + Sugg::hir(cx, &other_addend, ".."), + ), + Applicability::MachineApplicable, + ); + + return; + } } - } - let (lint, help, suggestion) = match value { - Int(2) => ( - IMPRECISE_FLOPS, - "square can be computed more accurately", + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "square can be computed more efficiently", + "consider using", format!("{} * {}", Sugg::hir(cx, &args[0], ".."), Sugg::hir(cx, &args[0], "..")), - ), - _ => return, - }; - - span_lint_and_sugg( - cx, - lint, - expr.span, - help, - "consider using", - suggestion, - Applicability::MachineApplicable, - ); + Applicability::MachineApplicable, + ); + } } } diff --git a/tests/ui/floating_point_powi.fixed b/tests/ui/floating_point_powi.fixed index 98766e68aaf..56762400593 100644 --- a/tests/ui/floating_point_powi.fixed +++ b/tests/ui/floating_point_powi.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::imprecise_flops)] +#![warn(clippy::suboptimal_flops)] fn main() { let one = 1; @@ -8,10 +8,12 @@ fn main() { let _ = x * x; let y = 4f32; - let _ = (x * x + y).sqrt(); - let _ = (x + y * y).sqrt(); + let _ = x.mul_add(x, y); + let _ = y.mul_add(y, x); + let _ = x.mul_add(x, y).sqrt(); + let _ = y.mul_add(y, x).sqrt(); // Cases where the lint shouldn't be applied let _ = x.powi(3); let _ = x.powi(one + 1); - let _ = x.hypot(y); + let _ = (x.powi(2) + y.powi(2)).sqrt(); } diff --git a/tests/ui/floating_point_powi.rs b/tests/ui/floating_point_powi.rs index 3c4b636a3d8..1f800e4628d 100644 --- a/tests/ui/floating_point_powi.rs +++ b/tests/ui/floating_point_powi.rs @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::imprecise_flops)] +#![warn(clippy::suboptimal_flops)] fn main() { let one = 1; @@ -8,6 +8,8 @@ fn main() { let _ = x.powi(1 + 1); let y = 4f32; + let _ = x.powi(2) + y; + let _ = x + y.powi(2); let _ = (x.powi(2) + y).sqrt(); let _ = (x + y.powi(2)).sqrt(); // Cases where the lint shouldn't be applied diff --git a/tests/ui/floating_point_powi.stderr b/tests/ui/floating_point_powi.stderr index f370e24bf05..d5a5f1bcca1 100644 --- a/tests/ui/floating_point_powi.stderr +++ b/tests/ui/floating_point_powi.stderr @@ -1,34 +1,40 @@ -error: square can be computed more accurately +error: square can be computed more efficiently --> $DIR/floating_point_powi.rs:7:13 | LL | let _ = x.powi(2); | ^^^^^^^^^ help: consider using: `x * x` | - = note: `-D clippy::imprecise-flops` implied by `-D warnings` + = note: `-D clippy::suboptimal-flops` implied by `-D warnings` -error: square can be computed more accurately +error: square can be computed more efficiently --> $DIR/floating_point_powi.rs:8:13 | LL | let _ = x.powi(1 + 1); | ^^^^^^^^^^^^^ help: consider using: `x * x` -error: square can be computed more accurately - --> $DIR/floating_point_powi.rs:11:14 +error: square can be computed more efficiently + --> $DIR/floating_point_powi.rs:11:13 + | +LL | let _ = x.powi(2) + y; + | ^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)` + +error: square can be computed more efficiently + --> $DIR/floating_point_powi.rs:12:13 + | +LL | let _ = x + y.powi(2); + | ^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)` + +error: square can be computed more efficiently + --> $DIR/floating_point_powi.rs:13:13 | LL | let _ = (x.powi(2) + y).sqrt(); - | ^^^^^^^^^ help: consider using: `x * x` + | ^^^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)` -error: square can be computed more accurately - --> $DIR/floating_point_powi.rs:12:18 +error: square can be computed more efficiently + --> $DIR/floating_point_powi.rs:14:13 | LL | let _ = (x + y.powi(2)).sqrt(); - | ^^^^^^^^^ help: consider using: `y * y` + | ^^^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)` -error: hypotenuse can be computed more accurately - --> $DIR/floating_point_powi.rs:16:13 - | -LL | let _ = (x.powi(2) + y.powi(2)).sqrt(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)` - -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors From 3065201eb3a0c4976de7ef5b5b924afde1b18325 Mon Sep 17 00:00:00 2001 From: Thiago Arrais <thiago.arrais@gmail.com> Date: Mon, 6 Jul 2020 13:14:52 -0300 Subject: [PATCH 271/526] =?UTF-8?q?Includes=20TODO=20for=20constants=20equ?= =?UTF-8?q?ivalent=20to=20=CF=80/180?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clippy_lints/src/floating_point_arithmetic.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 11bd0ae23aa..3087d6a940a 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -665,6 +665,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { if let Some((rvalue, _)) = constant(cx, cx.tables(), div_rhs); if let Some((lvalue, _)) = constant(cx, cx.tables(), mul_rhs); then { + // TODO: also check for constant values near PI/180 or 180/PI if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) && (F32(180_f32) == lvalue || F64(180_f64) == lvalue) { From 5307cb5614e7498f069bb634ab293e176e63c67f Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Sat, 4 Jul 2020 22:50:03 +0900 Subject: [PATCH 272/526] Add a lint for `.repeat(1)` fix #3028. --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 ++ clippy_lints/src/repeat_once.rs | 126 ++++++++++++++++++++++++++++++++ src/lintlist/mod.rs | 7 ++ tests/ui/repeat_once.fixed | 16 ++++ tests/ui/repeat_once.rs | 16 ++++ tests/ui/repeat_once.stderr | 40 ++++++++++ 7 files changed, 211 insertions(+) create mode 100644 clippy_lints/src/repeat_once.rs create mode 100644 tests/ui/repeat_once.fixed create mode 100644 tests/ui/repeat_once.rs create mode 100644 tests/ui/repeat_once.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a081bb85fe..c5bbaac0df6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1616,6 +1616,7 @@ Released 2018-09-13 [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro +[`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once [`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts [`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs [`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_or_into_option diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index fe34e4390d6..0f362dbf86b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -282,6 +282,7 @@ mod redundant_pub_crate; mod redundant_static_lifetimes; mod reference; mod regex; +mod repeat_once; mod returns; mod serde_api; mod shadow; @@ -764,6 +765,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &reference::REF_IN_DEREF, ®ex::INVALID_REGEX, ®ex::TRIVIAL_REGEX, + &repeat_once::REPEAT_ONCE, &returns::NEEDLESS_RETURN, &returns::UNUSED_UNIT, &serde_api::SERDE_API_MISUSE, @@ -1071,6 +1073,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box macro_use::MacroUseImports::default()); store.register_late_pass(|| box map_identity::MapIdentity); store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch); + store.register_late_pass(|| box repeat_once::RepeatOnce); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1393,6 +1396,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&reference::REF_IN_DEREF), LintId::of(®ex::INVALID_REGEX), LintId::of(®ex::TRIVIAL_REGEX), + LintId::of(&repeat_once::REPEAT_ONCE), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), LintId::of(&serde_api::SERDE_API_MISUSE), @@ -1602,6 +1606,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ranges::RANGE_ZIP_WITH_LEN), LintId::of(&reference::DEREF_ADDROF), LintId::of(&reference::REF_IN_DEREF), + LintId::of(&repeat_once::REPEAT_ONCE), LintId::of(&swap::MANUAL_SWAP), LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT), LintId::of(&transmute::CROSSPOINTER_TRANSMUTE), diff --git a/clippy_lints/src/repeat_once.rs b/clippy_lints/src/repeat_once.rs new file mode 100644 index 00000000000..af3c948ec82 --- /dev/null +++ b/clippy_lints/src/repeat_once.rs @@ -0,0 +1,126 @@ +use crate::consts::{miri_to_const, Constant}; +use crate::utils::{in_macro, is_type_diagnostic_item, snippet, span_lint_and_sugg, walk_ptrs_ty}; +use if_chain::if_chain; +use rustc_ast::ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Ty}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Checks for usage of `.repeat(1)` and suggest the following method for each types. + /// - `.to_string()` for `str` + /// - `.clone()` for `String` + /// - `.to_vec()` for `slice` + /// + /// **Why is this bad?** For example, `String.repeat(1)` is equivalent to `.clone()`. If cloning the string is the intention behind thi, `clone()` should be used. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// fn main() { + /// let x = String::from("hello world").repeat(1); + /// } + /// ``` + /// Use instead: + /// ```rust + /// fn main() { + /// let x = String::from("hello world").clone(); + /// } + /// ``` + pub REPEAT_ONCE, + complexity, + "using `.repeat(1)` instead of `String.clone()`, `str.to_string()` or `slice.to_vec()` " +} + +declare_lint_pass!(RepeatOnce => [REPEAT_ONCE]); + +impl<'tcx> LateLintPass<'tcx> for RepeatOnce { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'tcx Expr<'_>) { + if_chain! { + if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind; + if path.ident.name == sym!(repeat); + if is_once(cx, &args[1]) && !in_macro(args[0].span); + then { + let ty = walk_ptrs_ty(cx.tables().expr_ty(&args[0])); + if is_str(ty){ + span_lint_and_sugg( + cx, + REPEAT_ONCE, + expr.span, + "calling `repeat(1)` on str", + "consider using `.to_string()` instead", + format!("{}.to_string()", snippet(cx, args[0].span, r#""...""#)), + Applicability::MachineApplicable, + ); + } else if is_slice(ty) { + span_lint_and_sugg( + cx, + REPEAT_ONCE, + expr.span, + "calling `repeat(1)` on slice", + "consider using `.to_vec()` instead", + format!("{}.to_vec()", snippet(cx, args[0].span, r#""...""#)), + Applicability::MachineApplicable, + ); + } else if is_type_diagnostic_item(cx, ty, sym!(string_type)) { + span_lint_and_sugg( + cx, + REPEAT_ONCE, + expr.span, + "calling `repeat(1)` on a string literal", + "consider using `.clone()` instead", + format!("{}.clone()", snippet(cx, args[0].span, r#""...""#)), + Applicability::MachineApplicable, + ); + } + } + } + } +} + +fn is_once<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> bool { + match expr.kind { + ExprKind::Lit(ref lit) => { + if let LitKind::Int(ref lit_content, _) = lit.node { + *lit_content == 1 + } else { + false + } + }, + ExprKind::Path(rustc_hir::QPath::Resolved(None, path)) => { + if let Res::Def(DefKind::Const, def_id) = path.res { + let ty = cx.tcx.type_of(def_id); + let con = cx + .tcx + .const_eval_poly(def_id) + .ok() + .map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty)) + .unwrap(); + let con = miri_to_const(con); + con == Some(Constant::Int(1)) + } else { + false + } + }, + _ => false, + } +} + +fn is_str(ty: Ty<'_>) -> bool { + match ty.kind { + ty::Str => true, + _ => false, + } +} + +fn is_slice(ty: Ty<'_>) -> bool { + match ty.kind { + ty::Slice(..) | ty::Array(..) => true, + _ => false, + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index e681f47f949..078924d3f9b 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1879,6 +1879,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "reference", }, + Lint { + name: "repeat_once", + group: "complexity", + desc: "using `.repeat(1)` instead of `String.clone()`, `str.to_string()` or `slice.to_vec()` ", + deprecation: None, + module: "repeat_once", + }, Lint { name: "rest_pat_in_fully_bound_structs", group: "restriction", diff --git a/tests/ui/repeat_once.fixed b/tests/ui/repeat_once.fixed new file mode 100644 index 00000000000..a637c22fbcd --- /dev/null +++ b/tests/ui/repeat_once.fixed @@ -0,0 +1,16 @@ +// run-rustfix +#![warn(clippy::repeat_once)] +#[allow(unused, clippy::many_single_char_names, clippy::redundant_clone)] +fn main() { + const N: usize = 1; + let s = "str"; + let string = "String".to_string(); + let slice = [1; 5]; + + let a = [1; 5].to_vec(); + let b = slice.to_vec(); + let c = "hello".to_string(); + let d = "hi".to_string(); + let e = s.to_string(); + let f = string.clone(); +} diff --git a/tests/ui/repeat_once.rs b/tests/ui/repeat_once.rs new file mode 100644 index 00000000000..d99ca1b5b55 --- /dev/null +++ b/tests/ui/repeat_once.rs @@ -0,0 +1,16 @@ +// run-rustfix +#![warn(clippy::repeat_once)] +#[allow(unused, clippy::many_single_char_names, clippy::redundant_clone)] +fn main() { + const N: usize = 1; + let s = "str"; + let string = "String".to_string(); + let slice = [1; 5]; + + let a = [1; 5].repeat(1); + let b = slice.repeat(1); + let c = "hello".repeat(N); + let d = "hi".repeat(1); + let e = s.repeat(1); + let f = string.repeat(1); +} diff --git a/tests/ui/repeat_once.stderr b/tests/ui/repeat_once.stderr new file mode 100644 index 00000000000..915eea3bfc6 --- /dev/null +++ b/tests/ui/repeat_once.stderr @@ -0,0 +1,40 @@ +error: calling `repeat(1)` on slice + --> $DIR/repeat_once.rs:10:13 + | +LL | let a = [1; 5].repeat(1); + | ^^^^^^^^^^^^^^^^ help: consider using `.to_vec()` instead: `[1; 5].to_vec()` + | + = note: `-D clippy::repeat-once` implied by `-D warnings` + +error: calling `repeat(1)` on slice + --> $DIR/repeat_once.rs:11:13 + | +LL | let b = slice.repeat(1); + | ^^^^^^^^^^^^^^^ help: consider using `.to_vec()` instead: `slice.to_vec()` + +error: calling `repeat(1)` on str + --> $DIR/repeat_once.rs:12:13 + | +LL | let c = "hello".repeat(N); + | ^^^^^^^^^^^^^^^^^ help: consider using `.to_string()` instead: `"hello".to_string()` + +error: calling `repeat(1)` on str + --> $DIR/repeat_once.rs:13:13 + | +LL | let d = "hi".repeat(1); + | ^^^^^^^^^^^^^^ help: consider using `.to_string()` instead: `"hi".to_string()` + +error: calling `repeat(1)` on str + --> $DIR/repeat_once.rs:14:13 + | +LL | let e = s.repeat(1); + | ^^^^^^^^^^^ help: consider using `.to_string()` instead: `s.to_string()` + +error: calling `repeat(1)` on a string literal + --> $DIR/repeat_once.rs:15:13 + | +LL | let f = string.repeat(1); + | ^^^^^^^^^^^^^^^^ help: consider using `.clone()` instead: `string.clone()` + +error: aborting due to 6 previous errors + From 37d75da266443dd4253ceedebd692ba77dd72e03 Mon Sep 17 00:00:00 2001 From: robojumper <robojumper@gmail.com> Date: Wed, 8 Jul 2020 18:04:51 +0200 Subject: [PATCH 273/526] make match_like_matches_macro only apply to matches with a wildcard --- clippy_lints/src/assign_ops.rs | 1 - clippy_lints/src/matches.rs | 41 +++++++++---------- tests/ui/match_expr_like_matches_macro.fixed | 14 ++++--- tests/ui/match_expr_like_matches_macro.rs | 17 +++++--- tests/ui/match_expr_like_matches_macro.stderr | 28 +++++++++---- tests/ui/question_mark.fixed | 5 ++- tests/ui/question_mark.rs | 5 ++- tests/ui/question_mark.stderr | 20 ++++----- 8 files changed, 77 insertions(+), 54 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 3d48bf739eb..bc6e868823f 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -237,7 +237,6 @@ fn is_commutative(op: hir::BinOpKind) -> bool { use rustc_hir::BinOpKind::{ Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub, }; - #[allow(clippy::match_like_matches_macro)] match op { Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true, Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 34aa2981535..aeabb99a30d 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -446,11 +446,12 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Checks for `match` expressions producing a `bool` that could be written using `matches!` + /// **What it does:** Checks for `match` or `if let` expressions producing a + /// `bool` that could be written using `matches!` /// /// **Why is this bad?** Readability and needless complexity. /// - /// **Known problems:** This can turn an intentionally exhaustive match into a non-exhaustive one. + /// **Known problems:** None /// /// **Example:** /// ```rust @@ -462,8 +463,14 @@ declare_clippy_lint! { /// _ => false, /// }; /// + /// let a = if let Some(0) = x { + /// true + /// } else { + /// false + /// }; + /// /// // Good - /// let a = matches!(x, Some(5)); + /// let a = matches!(x, Some(0)); /// ``` pub MATCH_LIKE_MATCHES_MACRO, style, @@ -499,9 +506,8 @@ impl<'tcx> LateLintPass<'tcx> for Matches { return; } - if !redundant_pattern_match::check(cx, expr) { - check_match_like_matches(cx, expr); - } + redundant_pattern_match::check(cx, expr); + check_match_like_matches(cx, expr); if let ExprKind::Match(ref ex, ref arms, MatchSource::Normal) = expr.kind { check_single_match(cx, ex, arms, expr); @@ -1068,6 +1074,7 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr if_chain! { if arms.len() == 2; if cx.tables().expr_ty(expr).is_bool(); + if is_wild(&arms[1].pat); if let Some(first) = find_bool_lit(&arms[0].body.kind, desugared); if let Some(second) = find_bool_lit(&arms[1].body.kind, desugared); if first != second; @@ -1437,16 +1444,14 @@ mod redundant_pattern_match { use rustc_mir::const_eval::is_const_fn; use rustc_span::source_map::Symbol; - pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { + pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Match(op, arms, ref match_source) = &expr.kind { match match_source { MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms), MatchSource::IfLetDesugar { .. } => find_sugg_for_if_let(cx, expr, op, arms, "if"), MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, arms, "while"), - _ => false, + _ => {}, } - } else { - false } } @@ -1456,7 +1461,7 @@ mod redundant_pattern_match { op: &Expr<'_>, arms: &[Arm<'_>], keyword: &'static str, - ) -> bool { + ) { fn find_suggestion(cx: &LateContext<'_>, hir_id: HirId, path: &QPath<'_>) -> Option<&'static str> { if match_qpath(path, &paths::RESULT_OK) && can_suggest(cx, hir_id, sym!(result_type), "is_ok") { return Some("is_ok()"); @@ -1487,7 +1492,7 @@ mod redundant_pattern_match { }; let good_method = match good_method { Some(method) => method, - None => return false, + None => return, }; // check that `while_let_on_iterator` lint does not trigger @@ -1497,7 +1502,7 @@ mod redundant_pattern_match { if method_path.ident.name == sym!(next); if match_trait_method(cx, op, &paths::ITERATOR); then { - return false; + return; } } @@ -1526,15 +1531,9 @@ mod redundant_pattern_match { ); }, ); - true } - fn find_sugg_for_match<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx Expr<'_>, - op: &Expr<'_>, - arms: &[Arm<'_>], - ) -> bool { + fn find_sugg_for_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op: &Expr<'_>, arms: &[Arm<'_>]) { if arms.len() == 2 { let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind); @@ -1599,10 +1598,8 @@ mod redundant_pattern_match { ); }, ); - return true; } } - false } #[allow(clippy::too_many_arguments)] diff --git a/tests/ui/match_expr_like_matches_macro.fixed b/tests/ui/match_expr_like_matches_macro.fixed index 2d1ac8836d6..f3e19092480 100644 --- a/tests/ui/match_expr_like_matches_macro.fixed +++ b/tests/ui/match_expr_like_matches_macro.fixed @@ -1,6 +1,7 @@ // run-rustfix #![warn(clippy::match_like_matches_macro)] +#![allow(unreachable_patterns)] fn main() { let x = Some(5); @@ -8,25 +9,28 @@ fn main() { // Lint let _y = matches!(x, Some(0)); + // Lint + let _w = matches!(x, Some(_)); + // Turn into is_none let _z = x.is_none(); // Lint - let _z = !matches!(x, Some(r) if r == 0); + let _zz = !matches!(x, Some(r) if r == 0); // Lint - let _zz = matches!(x, Some(5)); + let _zzz = matches!(x, Some(5)); // No lint let _a = match x { Some(_) => false, - None => false, + _ => false, }; // No lint - let _a = match x { + let _ab = match x { Some(0) => false, - Some(_) => true, + _ => true, None => false, }; } diff --git a/tests/ui/match_expr_like_matches_macro.rs b/tests/ui/match_expr_like_matches_macro.rs index 376abf9244e..fbae7c18b92 100644 --- a/tests/ui/match_expr_like_matches_macro.rs +++ b/tests/ui/match_expr_like_matches_macro.rs @@ -1,6 +1,7 @@ // run-rustfix #![warn(clippy::match_like_matches_macro)] +#![allow(unreachable_patterns)] fn main() { let x = Some(5); @@ -11,6 +12,12 @@ fn main() { _ => false, }; + // Lint + let _w = match x { + Some(_) => true, + _ => false, + }; + // Turn into is_none let _z = match x { Some(_) => false, @@ -18,24 +25,24 @@ fn main() { }; // Lint - let _z = match x { + let _zz = match x { Some(r) if r == 0 => false, _ => true, }; // Lint - let _zz = if let Some(5) = x { true } else { false }; + let _zzz = if let Some(5) = x { true } else { false }; // No lint let _a = match x { Some(_) => false, - None => false, + _ => false, }; // No lint - let _a = match x { + let _ab = match x { Some(0) => false, - Some(_) => true, + _ => true, None => false, }; } diff --git a/tests/ui/match_expr_like_matches_macro.stderr b/tests/ui/match_expr_like_matches_macro.stderr index 0b32af039a8..4668f8565a6 100644 --- a/tests/ui/match_expr_like_matches_macro.stderr +++ b/tests/ui/match_expr_like_matches_macro.stderr @@ -1,5 +1,5 @@ error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:9:14 + --> $DIR/match_expr_like_matches_macro.rs:10:14 | LL | let _y = match x { | ______________^ @@ -10,8 +10,18 @@ LL | | }; | = note: `-D clippy::match-like-matches-macro` implied by `-D warnings` +error: match expression looks like `matches!` macro + --> $DIR/match_expr_like_matches_macro.rs:16:14 + | +LL | let _w = match x { + | ______________^ +LL | | Some(_) => true, +LL | | _ => false, +LL | | }; + | |_____^ help: try this: `matches!(x, Some(_))` + error: redundant pattern matching, consider using `is_none()` - --> $DIR/match_expr_like_matches_macro.rs:15:14 + --> $DIR/match_expr_like_matches_macro.rs:22:14 | LL | let _z = match x { | ______________^ @@ -23,20 +33,20 @@ LL | | }; = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:21:14 + --> $DIR/match_expr_like_matches_macro.rs:28:15 | -LL | let _z = match x { - | ______________^ +LL | let _zz = match x { + | _______________^ LL | | Some(r) if r == 0 => false, LL | | _ => true, LL | | }; | |_____^ help: try this: `!matches!(x, Some(r) if r == 0)` error: if let .. else expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:27:15 + --> $DIR/match_expr_like_matches_macro.rs:34:16 | -LL | let _zz = if let Some(5) = x { true } else { false }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))` +LL | let _zzz = if let Some(5) = x { true } else { false }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index bd13cf1bdfa..11dff94a288 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -23,7 +23,10 @@ pub enum SeemsOption<T> { impl<T> SeemsOption<T> { pub fn is_none(&self) -> bool { - matches!(*self, SeemsOption::None) + match *self { + SeemsOption::None => true, + SeemsOption::Some(_) => false, + } } } diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 94479e68555..1d0ee82b4f7 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -25,7 +25,10 @@ pub enum SeemsOption<T> { impl<T> SeemsOption<T> { pub fn is_none(&self) -> bool { - matches!(*self, SeemsOption::None) + match *self { + SeemsOption::None => true, + SeemsOption::Some(_) => false, + } } } diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index be323035d6c..502615fb175 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:47:9 + --> $DIR/question_mark.rs:50:9 | LL | / if (self.opt).is_none() { LL | | return None; @@ -17,7 +17,7 @@ LL | | } | |_________^ help: replace it with: `(self.opt)?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:51:9 + --> $DIR/question_mark.rs:54:9 | LL | / if self.opt.is_none() { LL | | return None @@ -25,7 +25,7 @@ LL | | } | |_________^ help: replace it with: `self.opt?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:55:17 + --> $DIR/question_mark.rs:58:17 | LL | let _ = if self.opt.is_none() { | _________________^ @@ -36,7 +36,7 @@ LL | | }; | |_________^ help: replace it with: `Some(self.opt?)` error: this if-let-else may be rewritten with the `?` operator - --> $DIR/question_mark.rs:61:17 + --> $DIR/question_mark.rs:64:17 | LL | let _ = if let Some(x) = self.opt { | _________________^ @@ -47,7 +47,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:78:9 + --> $DIR/question_mark.rs:81:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -55,7 +55,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:86:9 + --> $DIR/question_mark.rs:89:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -63,7 +63,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:94:9 + --> $DIR/question_mark.rs:97:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -71,7 +71,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this if-let-else may be rewritten with the `?` operator - --> $DIR/question_mark.rs:101:26 + --> $DIR/question_mark.rs:104:26 | LL | let v: &Vec<_> = if let Some(ref v) = self.opt { | __________________________^ @@ -82,7 +82,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt.as_ref()?` error: this if-let-else may be rewritten with the `?` operator - --> $DIR/question_mark.rs:111:17 + --> $DIR/question_mark.rs:114:17 | LL | let v = if let Some(v) = self.opt { | _________________^ @@ -93,7 +93,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:126:5 + --> $DIR/question_mark.rs:129:5 | LL | / if f().is_none() { LL | | return None; From db1c946aaa02e1192d271dbcfe4598d726806108 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Tue, 30 Jun 2020 21:48:34 +0200 Subject: [PATCH 274/526] unnecessary_sort_by: avoid linting if key borrows --- clippy_lints/src/let_and_return.rs | 21 ++--------- clippy_lints/src/unnecessary_sort_by.rs | 48 +++++++++++++++---------- clippy_lints/src/utils/mod.rs | 15 ++++++++ tests/ui/unnecessary_sort_by.fixed | 46 +++++++++++++++++++++--- tests/ui/unnecessary_sort_by.rs | 46 +++++++++++++++++++++--- 5 files changed, 131 insertions(+), 45 deletions(-) diff --git a/clippy_lints/src/let_and_return.rs b/clippy_lints/src/let_and_return.rs index ddc41f89f8d..fa560ffb980 100644 --- a/clippy_lints/src/let_and_return.rs +++ b/clippy_lints/src/let_and_return.rs @@ -1,6 +1,5 @@ use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{Block, Expr, ExprKind, PatKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -9,7 +8,7 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty::subst::GenericArgKind; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::{in_macro, match_qpath, snippet_opt, span_lint_and_then}; +use crate::utils::{fn_def_id, in_macro, match_qpath, snippet_opt, span_lint_and_then}; declare_clippy_lint! { /// **What it does:** Checks for `let`-bindings, which are subsequently @@ -97,22 +96,6 @@ struct BorrowVisitor<'a, 'tcx> { borrows: bool, } -impl BorrowVisitor<'_, '_> { - fn fn_def_id(&self, expr: &Expr<'_>) -> Option<DefId> { - match &expr.kind { - ExprKind::MethodCall(..) => self.cx.tables().type_dependent_def_id(expr.hir_id), - ExprKind::Call( - Expr { - kind: ExprKind::Path(qpath), - .. - }, - .., - ) => self.cx.qpath_res(qpath, expr.hir_id).opt_def_id(), - _ => None, - } - } -} - impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> { type Map = Map<'tcx>; @@ -121,7 +104,7 @@ impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> { return; } - if let Some(def_id) = self.fn_def_id(expr) { + if let Some(def_id) = fn_def_id(self.cx, expr) { self.borrows = self .cx .tcx diff --git a/clippy_lints/src/unnecessary_sort_by.rs b/clippy_lints/src/unnecessary_sort_by.rs index d940776817c..91c1789a2ff 100644 --- a/clippy_lints/src/unnecessary_sort_by.rs +++ b/clippy_lints/src/unnecessary_sort_by.rs @@ -5,24 +5,23 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, subst::GenericArgKind}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Ident; declare_clippy_lint! { /// **What it does:** - /// Detects when people use `Vec::sort_by` and pass in a function + /// Detects uses of `Vec::sort_by` passing in a closure /// which compares the two arguments, either directly or indirectly. /// /// **Why is this bad?** /// It is more clear to use `Vec::sort_by_key` (or `Vec::sort` if - /// possible) than to use `Vec::sort_by` and and a more complicated + /// possible) than to use `Vec::sort_by` and a more complicated /// closure. /// /// **Known problems:** - /// If the suggested `Vec::sort_by_key` uses Reverse and it isn't - /// imported by a use statement in the current frame, then a `use` - /// statement that imports it will need to be added (which this lint - /// can't do). + /// If the suggested `Vec::sort_by_key` uses Reverse and it isn't already + /// imported by a use statement, then it will need to be added manually. /// /// **Example:** /// @@ -201,28 +200,41 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> { }; let vec_name = Sugg::hir(cx, &args[0], "..").to_string(); let unstable = name == "sort_unstable_by"; + if_chain! { if let ExprKind::Path(QPath::Resolved(_, Path { segments: [PathSegment { ident: left_name, .. }], .. })) = &left_expr.kind; if left_name == left_ident; then { - Some(LintTrigger::Sort(SortDetection { vec_name, unstable })) - } - else { - Some(LintTrigger::SortByKey(SortByKeyDetection { - vec_name, - unstable, - closure_arg, - closure_body, - reverse - })) + return Some(LintTrigger::Sort(SortDetection { vec_name, unstable })) + } else { + if !key_returns_borrow(cx, left_expr) { + return Some(LintTrigger::SortByKey(SortByKeyDetection { + vec_name, + unstable, + closure_arg, + closure_body, + reverse + })) + } } } - } else { - None } } + + None +} + +fn key_returns_borrow(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let Some(def_id) = utils::fn_def_id(cx, expr) { + let output = cx.tcx.fn_sig(def_id).output(); + let ty = output.skip_binder(); + return matches!(ty.kind, ty::Ref(..)) + || ty.walk().any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))); + } + + false } impl LateLintPass<'_> for UnnecessarySortBy { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 3a3b79925ff..93075b9f0b5 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1363,6 +1363,21 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool { ) } +/// Returns the `DefId` of the callee if the given expression is a function or method call. +pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> { + match &expr.kind { + ExprKind::MethodCall(..) => cx.tables().type_dependent_def_id(expr.hir_id), + ExprKind::Call( + Expr { + kind: ExprKind::Path(qpath), + .. + }, + .., + ) => cx.tables().qpath_res(qpath, expr.hir_id).opt_def_id(), + _ => None, + } +} + pub fn run_lints(cx: &LateContext<'_>, lints: &[&'static Lint], id: HirId) -> bool { lints.iter().any(|lint| { matches!( diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index 779fd57707a..c017d1cf9a4 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -2,11 +2,11 @@ use std::cmp::Reverse; -fn id(x: isize) -> isize { - x -} +fn unnecessary_sort_by() { + fn id(x: isize) -> isize { + x + } -fn main() { let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; // Forward examples vec.sort(); @@ -24,3 +24,41 @@ fn main() { vec.sort_by(|_, b| b.cmp(c)); vec.sort_unstable_by(|a, _| a.cmp(c)); } + +// Should not be linted to avoid hitting https://github.com/rust-lang/rust/issues/34162 +mod issue_5754 { + struct Test(String); + + #[derive(PartialOrd, Ord, PartialEq, Eq)] + struct Wrapper<'a>(&'a str); + + impl Test { + fn name(&self) -> &str { + &self.0 + } + + fn wrapped(&self) -> Wrapper<'_> { + Wrapper(&self.0) + } + } + + pub fn test() { + let mut args: Vec<Test> = vec![]; + + // Forward + args.sort_by(|a, b| a.name().cmp(b.name())); + args.sort_by(|a, b| a.wrapped().cmp(&b.wrapped())); + args.sort_unstable_by(|a, b| a.name().cmp(b.name())); + args.sort_unstable_by(|a, b| a.wrapped().cmp(&b.wrapped())); + // Reverse + args.sort_by(|a, b| b.name().cmp(a.name())); + args.sort_by(|a, b| b.wrapped().cmp(&a.wrapped())); + args.sort_unstable_by(|a, b| b.name().cmp(a.name())); + args.sort_unstable_by(|a, b| b.wrapped().cmp(&a.wrapped())); + } +} + +fn main() { + unnecessary_sort_by(); + issue_5754::test(); +} diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index 0485a5630af..1929c72b2f2 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -2,11 +2,11 @@ use std::cmp::Reverse; -fn id(x: isize) -> isize { - x -} +fn unnecessary_sort_by() { + fn id(x: isize) -> isize { + x + } -fn main() { let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5]; // Forward examples vec.sort_by(|a, b| a.cmp(b)); @@ -24,3 +24,41 @@ fn main() { vec.sort_by(|_, b| b.cmp(c)); vec.sort_unstable_by(|a, _| a.cmp(c)); } + +// Should not be linted to avoid hitting https://github.com/rust-lang/rust/issues/34162 +mod issue_5754 { + struct Test(String); + + #[derive(PartialOrd, Ord, PartialEq, Eq)] + struct Wrapper<'a>(&'a str); + + impl Test { + fn name(&self) -> &str { + &self.0 + } + + fn wrapped(&self) -> Wrapper<'_> { + Wrapper(&self.0) + } + } + + pub fn test() { + let mut args: Vec<Test> = vec![]; + + // Forward + args.sort_by(|a, b| a.name().cmp(b.name())); + args.sort_by(|a, b| a.wrapped().cmp(&b.wrapped())); + args.sort_unstable_by(|a, b| a.name().cmp(b.name())); + args.sort_unstable_by(|a, b| a.wrapped().cmp(&b.wrapped())); + // Reverse + args.sort_by(|a, b| b.name().cmp(a.name())); + args.sort_by(|a, b| b.wrapped().cmp(&a.wrapped())); + args.sort_unstable_by(|a, b| b.name().cmp(a.name())); + args.sort_unstable_by(|a, b| b.wrapped().cmp(&a.wrapped())); + } +} + +fn main() { + unnecessary_sort_by(); + issue_5754::test(); +} From dac19e3afccc63ff976bcf0a5ee385bdd0e075d5 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Tue, 7 Jul 2020 00:35:51 +0200 Subject: [PATCH 275/526] single_match_else - single expr/stmt else block corner case --- clippy_lints/src/matches.rs | 20 +++++++----- tests/ui/single_match_else.rs | 51 +++++++++++++++++++++++++++++++ tests/ui/single_match_else.stderr | 44 ++++++++++++++++++++++++-- 3 files changed, 106 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index b754a45aa40..a6cc1097441 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -530,16 +530,22 @@ fn check_single_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], exp // the lint noisy in unnecessary situations return; } - let els = remove_blocks(&arms[1].body); - let els = if is_unit_expr(els) { + let els = arms[1].body; + let els = if is_unit_expr(remove_blocks(els)) { None - } else if let ExprKind::Block(_, _) = els.kind { - // matches with blocks that contain statements are prettier as `if let + else` - Some(els) + } else if let ExprKind::Block(Block { stmts, expr: block_expr, .. }, _) = els.kind { + if stmts.len() == 1 && block_expr.is_none() || stmts.is_empty() && block_expr.is_some() { + // single statement/expr "else" block, don't lint + return; + } else { + // block with 2+ statements or 1 expr and 1+ statement + Some(els) + } } else { - // allow match arms with just expressions - return; + // not a block, don't lint + return; }; + let ty = cx.tables().expr_ty(ex); if ty.kind != ty::Bool || is_allowed(cx, MATCH_BOOL, ex.hir_id) { check_single_match_single_pattern(cx, ex, arms, expr, els); diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index 34193be0b75..b624a41a29b 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -1,4 +1,6 @@ #![warn(clippy::single_match_else)] +#![allow(clippy::needless_return)] +#![allow(clippy::no_effect)] enum ExprNode { ExprAddrOf, @@ -30,6 +32,55 @@ macro_rules! unwrap_addr { }; } +#[rustfmt::skip] fn main() { unwrap_addr!(ExprNode::Unicorns); + + // + // don't lint single exprs/statements + // + + // don't lint here + match Some(1) { + Some(a) => println!("${:?}", a), + None => return, + } + + // don't lint here + match Some(1) { + Some(a) => println!("${:?}", a), + None => { + return + }, + } + + // don't lint here + match Some(1) { + Some(a) => println!("${:?}", a), + None => { + return; + }, + } + + // + // lint multiple exprs/statements "else" blocks + // + + // lint here + match Some(1) { + Some(a) => println!("${:?}", a), + None => { + println!("else block"); + return + }, + } + + // lint here + match Some(1) { + Some(a) => println!("${:?}", a), + None => { + println!("else block"); + return; + }, + } } diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index 59861d46eb3..3a07c2ec542 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match_else.rs:12:5 + --> $DIR/single_match_else.rs:14:5 | LL | / match ExprNode::Butterflies { LL | | ExprNode::ExprAddrOf => Some(&NODE), @@ -19,5 +19,45 @@ LL | None LL | } | -error: aborting due to previous error +error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:70:5 + | +LL | / match Some(1) { +LL | | Some(a) => println!("${:?}", a), +LL | | None => { +LL | | println!("else block"); +LL | | return +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL | if let Some(a) = Some(1) { println!("${:?}", a) } else { +LL | println!("else block"); +LL | return +LL | } + | + +error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:79:5 + | +LL | / match Some(1) { +LL | | Some(a) => println!("${:?}", a), +LL | | None => { +LL | | println!("else block"); +LL | | return; +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL | if let Some(a) = Some(1) { println!("${:?}", a) } else { +LL | println!("else block"); +LL | return; +LL | } + | + +error: aborting due to 3 previous errors From c79c6888a5509184112b774a56cfc5ca9f9f1e2b Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Thu, 9 Jul 2020 22:07:15 +0900 Subject: [PATCH 276/526] Fix a broken link in CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f7bdcb1be7..69a734e4ee4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -245,7 +245,7 @@ this to work, you will need the fix of `git subtree` available [here][gitgitgadget-pr]. [gitgitgadget-pr]: https://github.com/gitgitgadget/git/pull/493 -[subtree]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#external-dependencies-subtree +[subtree]: https://rustc-dev-guide.rust-lang.org/contributing.html#external-dependencies-subtree [`rust-lang/rust`]: https://github.com/rust-lang/rust ## Issue and PR triage From 298a1fa3bd8ec04350b1bff6a6d92e34abf2e198 Mon Sep 17 00:00:00 2001 From: Christian Duerr <contact@christianduerr.com> Date: Fri, 26 Jun 2020 17:03:10 +0200 Subject: [PATCH 277/526] Move range_minus_one to pedantic This moves the range_minus_one lint to the pedantic category, so there will not be any warnings emitted by default. This should work around problems where the suggestion is impossible to resolve due to the range consumer only accepting a specific range implementation, rather than the `RangeBounds` trait (see #3307). While it is possible to work around this by extracting the boundary into a variable, I don't think clippy should encourage people to disable or work around lints, but instead the lints should be fixable. So hopefully this will help until a proper implementation checks what the range is used for. --- clippy_lints/src/ranges.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index c164ec9aaf1..dd608de5723 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -52,6 +52,11 @@ declare_clippy_lint! { /// exclusive ranges, because they essentially add an extra branch that /// LLVM may fail to hoist out of the loop. /// + /// This will cause a warning that cannot be fixed if the consumer of the + /// range only accepts a specific range type, instead of the generic + /// `RangeBounds` trait + /// ([#3307](https://github.com/rust-lang/rust-clippy/issues/3307)). + /// /// **Example:** /// ```rust,ignore /// for x..(y+1) { .. } @@ -72,7 +77,10 @@ declare_clippy_lint! { /// **Why is this bad?** The code is more readable with an exclusive range /// like `x..y`. /// - /// **Known problems:** None. + /// **Known problems:** This will cause a warning that cannot be fixed if + /// the consumer of the range only accepts a specific range type, instead of + /// the generic `RangeBounds` trait + /// ([#3307](https://github.com/rust-lang/rust-clippy/issues/3307)). /// /// **Example:** /// ```rust,ignore @@ -83,7 +91,7 @@ declare_clippy_lint! { /// for x..y { .. } /// ``` pub RANGE_MINUS_ONE, - complexity, + pedantic, "`x..=(y-1)` reads better as `x..y`" } From ba2a85dadc61bbfeb483ca0d05ddfda213da1329 Mon Sep 17 00:00:00 2001 From: Christian Duerr <contact@christianduerr.com> Date: Fri, 3 Jul 2020 21:09:32 +0200 Subject: [PATCH 278/526] Run update_lints --- clippy_lints/src/lib.rs | 3 +-- src/lintlist/mod.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index fe34e4390d6..4d9776018cf 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1162,6 +1162,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&needless_pass_by_value::NEEDLESS_PASS_BY_VALUE), LintId::of(&non_expressive_names::SIMILAR_NAMES), LintId::of(&option_if_let_else::OPTION_IF_LET_ELSE), + LintId::of(&ranges::RANGE_MINUS_ONE), LintId::of(&ranges::RANGE_PLUS_ONE), LintId::of(&shadow::SHADOW_UNRELATED), LintId::of(&strings::STRING_ADD_ASSIGN), @@ -1382,7 +1383,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ptr::PTR_ARG), LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), LintId::of(&question_mark::QUESTION_MARK), - LintId::of(&ranges::RANGE_MINUS_ONE), LintId::of(&ranges::RANGE_ZIP_WITH_LEN), LintId::of(&ranges::REVERSED_EMPTY_RANGES), LintId::of(&redundant_clone::REDUNDANT_CLONE), @@ -1598,7 +1598,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL), LintId::of(&precedence::PRECEDENCE), LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), - LintId::of(&ranges::RANGE_MINUS_ONE), LintId::of(&ranges::RANGE_ZIP_WITH_LEN), LintId::of(&reference::DEREF_ADDROF), LintId::of(&reference::REF_IN_DEREF), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index e681f47f949..c20793ecd3e 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1783,7 +1783,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ }, Lint { name: "range_minus_one", - group: "complexity", + group: "pedantic", desc: "`x..=(y-1)` reads better as `x..y`", deprecation: None, module: "ranges", From 780a4c87de88d7f747c7847b71c90c8268fe4b66 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Fri, 10 Jul 2020 23:53:15 +0900 Subject: [PATCH 279/526] Fix typo --- clippy_lints/src/repeat_once.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/repeat_once.rs b/clippy_lints/src/repeat_once.rs index af3c948ec82..436374d7c54 100644 --- a/clippy_lints/src/repeat_once.rs +++ b/clippy_lints/src/repeat_once.rs @@ -15,7 +15,7 @@ declare_clippy_lint! { /// - `.clone()` for `String` /// - `.to_vec()` for `slice` /// - /// **Why is this bad?** For example, `String.repeat(1)` is equivalent to `.clone()`. If cloning the string is the intention behind thi, `clone()` should be used. + /// **Why is this bad?** For example, `String.repeat(1)` is equivalent to `.clone()`. If cloning the string is the intention behind this, `clone()` should be used. /// /// **Known problems:** None. /// From b3c719608d2c969323714517837f0c68aca23d81 Mon Sep 17 00:00:00 2001 From: Christian Duerr <contact@christianduerr.com> Date: Fri, 10 Jul 2020 17:23:03 +0200 Subject: [PATCH 280/526] Fix test failures --- tests/ui/range_plus_minus_one.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index 3cfed4125b3..7d034117547 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -7,6 +7,7 @@ fn f() -> usize { } #[warn(clippy::range_plus_one)] +#[warn(clippy::range_minus_one)] fn main() { for _ in 0..2 {} for _ in 0..=2 {} From afa4148cc6dee0f9e0ca5b33f2511b9305d84fcb Mon Sep 17 00:00:00 2001 From: Christian Duerr <contact@christianduerr.com> Date: Fri, 10 Jul 2020 17:53:01 +0200 Subject: [PATCH 281/526] Fix tests a bit more --- tests/ui/range_plus_minus_one.fixed | 1 + tests/ui/range_plus_minus_one.stderr | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/ui/range_plus_minus_one.fixed b/tests/ui/range_plus_minus_one.fixed index 6b402114099..19b253b0fe2 100644 --- a/tests/ui/range_plus_minus_one.fixed +++ b/tests/ui/range_plus_minus_one.fixed @@ -7,6 +7,7 @@ fn f() -> usize { } #[warn(clippy::range_plus_one)] +#[warn(clippy::range_minus_one)] fn main() { for _ in 0..2 {} for _ in 0..=2 {} diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index f72943a04f2..fb4f1658597 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -1,5 +1,5 @@ error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:14:14 + --> $DIR/range_plus_minus_one.rs:15:14 | LL | for _ in 0..3 + 1 {} | ^^^^^^^^ help: use: `0..=3` @@ -7,25 +7,25 @@ LL | for _ in 0..3 + 1 {} = note: `-D clippy::range-plus-one` implied by `-D warnings` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:17:14 + --> $DIR/range_plus_minus_one.rs:18:14 | LL | for _ in 0..1 + 5 {} | ^^^^^^^^ help: use: `0..=5` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:20:14 + --> $DIR/range_plus_minus_one.rs:21:14 | LL | for _ in 1..1 + 1 {} | ^^^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:26:14 + --> $DIR/range_plus_minus_one.rs:27:14 | LL | for _ in 0..(1 + f()) {} | ^^^^^^^^^^^^ help: use: `0..=f()` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:30:13 + --> $DIR/range_plus_minus_one.rs:31:13 | LL | let _ = ..=11 - 1; | ^^^^^^^^^ help: use: `..11` @@ -33,25 +33,25 @@ LL | let _ = ..=11 - 1; = note: `-D clippy::range-minus-one` implied by `-D warnings` error: an exclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:31:13 + --> $DIR/range_plus_minus_one.rs:32:13 | LL | let _ = ..=(11 - 1); | ^^^^^^^^^^^ help: use: `..11` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:32:13 + --> $DIR/range_plus_minus_one.rs:33:13 | LL | let _ = (1..11 + 1); | ^^^^^^^^^^^ help: use: `(1..=11)` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:33:13 + --> $DIR/range_plus_minus_one.rs:34:13 | LL | let _ = (f() + 1)..(f() + 1); | ^^^^^^^^^^^^^^^^^^^^ help: use: `((f() + 1)..=f())` error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:37:14 + --> $DIR/range_plus_minus_one.rs:38:14 | LL | for _ in 1..ONE + ONE {} | ^^^^^^^^^^^^ help: use: `1..=ONE` From 1b3bc16533a3e701616648920603c10674eb653b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Sat, 11 Jul 2020 12:28:21 +0200 Subject: [PATCH 282/526] Fix out of bounds access by checking length equality BEFORE accessing by index. Fixes #5780 --- clippy_lints/src/unnested_or_patterns.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 169a486d1eb..502bf0c4279 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -400,8 +400,8 @@ fn extend_with_matching( /// Are the patterns in `ps1` and `ps2` equal save for `ps1[idx]` compared to `ps2[idx]`? fn eq_pre_post(ps1: &[P<Pat>], ps2: &[P<Pat>], idx: usize) -> bool { - ps1[idx].is_rest() == ps2[idx].is_rest() // Avoid `[x, ..] | [x, 0]` => `[x, .. | 0]`. - && ps1.len() == ps2.len() + ps1.len() == ps2.len() + && ps1[idx].is_rest() == ps2[idx].is_rest() // Avoid `[x, ..] | [x, 0]` => `[x, .. | 0]`. && over(&ps1[..idx], &ps2[..idx], |l, r| eq_pat(l, r)) && over(&ps1[idx + 1..], &ps2[idx + 1..], |l, r| eq_pat(l, r)) } From 2c5f8ab582badb5b45124bcab01597cae46c7e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Sat, 11 Jul 2020 23:42:56 +0200 Subject: [PATCH 283/526] fix phrase in new_lint issue template --- .github/ISSUE_TEMPLATE/new_lint.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/new_lint.md b/.github/ISSUE_TEMPLATE/new_lint.md index 70445d7ef25..98fd0df685f 100644 --- a/.github/ISSUE_TEMPLATE/new_lint.md +++ b/.github/ISSUE_TEMPLATE/new_lint.md @@ -12,7 +12,7 @@ labels: L-lint - Kind: *See <https://github.com/rust-lang/rust-clippy/blob/master/README.md#clippy> for list of lint kinds* -*What benefit of this lint over old code?* +*What is the advantage of the recommended code over the original code* For example: - Remove bounce checking inserted by ... From f2419b9d6299fb07a1163b47dc273f64e0444a6c Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Tue, 14 Jul 2020 00:11:10 +0900 Subject: [PATCH 284/526] Refactoring to use `constant_context Use `constant_context`, `.is_str()` and `builtin_index()` to simplify. --- clippy_lints/src/repeat_once.rs | 54 +++------------------------------ 1 file changed, 5 insertions(+), 49 deletions(-) diff --git a/clippy_lints/src/repeat_once.rs b/clippy_lints/src/repeat_once.rs index 436374d7c54..3a0b3b1c257 100644 --- a/clippy_lints/src/repeat_once.rs +++ b/clippy_lints/src/repeat_once.rs @@ -1,12 +1,9 @@ -use crate::consts::{miri_to_const, Constant}; +use crate::consts::{constant_context, Constant}; use crate::utils::{in_macro, is_type_diagnostic_item, snippet, span_lint_and_sugg, walk_ptrs_ty}; use if_chain::if_chain; -use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -44,10 +41,11 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce { if_chain! { if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind; if path.ident.name == sym!(repeat); - if is_once(cx, &args[1]) && !in_macro(args[0].span); + if let Some(Constant::Int(1)) = constant_context(cx, cx.tables()).expr(&args[1]); + if !in_macro(args[0].span); then { let ty = walk_ptrs_ty(cx.tables().expr_ty(&args[0])); - if is_str(ty){ + if ty.is_str() { span_lint_and_sugg( cx, REPEAT_ONCE, @@ -57,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce { format!("{}.to_string()", snippet(cx, args[0].span, r#""...""#)), Applicability::MachineApplicable, ); - } else if is_slice(ty) { + } else if let Some(_) = ty.builtin_index() { span_lint_and_sugg( cx, REPEAT_ONCE, @@ -82,45 +80,3 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce { } } } - -fn is_once<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> bool { - match expr.kind { - ExprKind::Lit(ref lit) => { - if let LitKind::Int(ref lit_content, _) = lit.node { - *lit_content == 1 - } else { - false - } - }, - ExprKind::Path(rustc_hir::QPath::Resolved(None, path)) => { - if let Res::Def(DefKind::Const, def_id) = path.res { - let ty = cx.tcx.type_of(def_id); - let con = cx - .tcx - .const_eval_poly(def_id) - .ok() - .map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty)) - .unwrap(); - let con = miri_to_const(con); - con == Some(Constant::Int(1)) - } else { - false - } - }, - _ => false, - } -} - -fn is_str(ty: Ty<'_>) -> bool { - match ty.kind { - ty::Str => true, - _ => false, - } -} - -fn is_slice(ty: Ty<'_>) -> bool { - match ty.kind { - ty::Slice(..) | ty::Array(..) => true, - _ => false, - } -} From ff796b6d7082d5b5c073797aba17f454eebe3359 Mon Sep 17 00:00:00 2001 From: bjorn3 <bjorn3@users.noreply.github.com> Date: Fri, 19 Jun 2020 11:44:03 +0200 Subject: [PATCH 285/526] Rename collapsable_if fix suggestion to "collapse nested if block" The name "try" is confusing when shown as quick fix by rust-analyzer --- clippy_lints/src/collapsible_if.rs | 4 ++-- tests/ui/collapsible_else_if.stderr | 14 +++++++------- tests/ui/collapsible_if.stderr | 14 +++++++------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 8090f4673aa..42bff564de0 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -115,7 +115,7 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) { COLLAPSIBLE_IF, block.span, "this `else { if .. }` block can be collapsed", - "try", + "collapse nested if block", snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability).into_owned(), applicability, ); @@ -142,7 +142,7 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: & let rhs = Sugg::ast(cx, check_inner, ".."); diag.span_suggestion( expr.span, - "try", + "collapse nested if block", format!( "if {} {}", lhs.and(&rhs), diff --git a/tests/ui/collapsible_else_if.stderr b/tests/ui/collapsible_else_if.stderr index 28048999e8e..3d1c458879e 100644 --- a/tests/ui/collapsible_else_if.stderr +++ b/tests/ui/collapsible_else_if.stderr @@ -10,7 +10,7 @@ LL | | } | |_____^ | = note: `-D clippy::collapsible-if` implied by `-D warnings` -help: try +help: collapse nested if block | LL | } else if y == "world" { LL | println!("world!") @@ -28,7 +28,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | } else if let Some(42) = Some(42) { LL | println!("world!") @@ -48,7 +48,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | } else if y == "world" { LL | println!("world") @@ -71,7 +71,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | } else if let Some(42) = Some(42) { LL | println!("world") @@ -94,7 +94,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | } else if let Some(42) = Some(42) { LL | println!("world") @@ -117,7 +117,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | } else if x == "hello" { LL | println!("world") @@ -140,7 +140,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | } else if let Some(42) = Some(42) { LL | println!("world") diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 6440ff41be8..f56dd65b9dd 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -9,7 +9,7 @@ LL | | } | |_____^ | = note: `-D clippy::collapsible-if` implied by `-D warnings` -help: try +help: collapse nested if block | LL | if x == "hello" && y == "world" { LL | println!("Hello world!"); @@ -26,7 +26,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { LL | println!("Hello world!"); @@ -43,7 +43,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | if x == "hello" && x == "world" && (y == "world" || y == "hello") { LL | println!("Hello world!"); @@ -60,7 +60,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | if (x == "hello" || x == "world") && y == "world" && y == "hello" { LL | println!("Hello world!"); @@ -77,7 +77,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | if x == "hello" && x == "world" && y == "world" && y == "hello" { LL | println!("Hello world!"); @@ -94,7 +94,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | if 42 == 1337 && 'a' != 'A' { LL | println!("world!") @@ -111,7 +111,7 @@ LL | | } LL | | } | |_____^ | -help: try +help: collapse nested if block | LL | if x == "hello" && y == "world" { // Collapsible LL | println!("Hello world!"); From 201999ccfd18a9debe1f186f30f40659ebc6b933 Mon Sep 17 00:00:00 2001 From: Brian Warner <warner@lothar.com> Date: Mon, 13 Jul 2020 10:33:25 -0700 Subject: [PATCH 286/526] improve advice in iter_nth_zero The "use .next()" replacement advice is on the last line of the code snippet, where it is vulnerable to truncation. Display that advice at the beginning instead. closes #5783 --- clippy_lints/src/methods/mod.rs | 4 ++-- tests/ui/iter_nth_zero.stderr | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 4c595029ff7..565a08f1292 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2348,8 +2348,8 @@ fn lint_iter_nth_zero<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_ar cx, ITER_NTH_ZERO, expr.span, - "called `.nth(0)` on a `std::iter::Iterator`", - "try calling", + "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent", + "try calling .next() instead of .nth(0)", format!("{}.next()", snippet_with_applicability(cx, nth_args[0].span, "..", &mut applicability)), applicability, ); diff --git a/tests/ui/iter_nth_zero.stderr b/tests/ui/iter_nth_zero.stderr index 2b20a4ceb4a..6c4200a7905 100644 --- a/tests/ui/iter_nth_zero.stderr +++ b/tests/ui/iter_nth_zero.stderr @@ -1,22 +1,22 @@ -error: called `.nth(0)` on a `std::iter::Iterator` +error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent --> $DIR/iter_nth_zero.rs:20:14 | LL | let _x = s.iter().nth(0); - | ^^^^^^^^^^^^^^^ help: try calling: `s.iter().next()` + | ^^^^^^^^^^^^^^^ help: try calling .next() instead of .nth(0): `s.iter().next()` | = note: `-D clippy::iter-nth-zero` implied by `-D warnings` -error: called `.nth(0)` on a `std::iter::Iterator` +error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent --> $DIR/iter_nth_zero.rs:25:14 | LL | let _y = iter.nth(0); - | ^^^^^^^^^^^ help: try calling: `iter.next()` + | ^^^^^^^^^^^ help: try calling .next() instead of .nth(0): `iter.next()` -error: called `.nth(0)` on a `std::iter::Iterator` +error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent --> $DIR/iter_nth_zero.rs:30:22 | LL | let _unwrapped = iter2.nth(0).unwrap(); - | ^^^^^^^^^^^^ help: try calling: `iter2.next()` + | ^^^^^^^^^^^^ help: try calling .next() instead of .nth(0): `iter2.next()` error: aborting due to 3 previous errors From b4091032abbadf586ea8c77bc547ec2ac403ef0a Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Tue, 14 Jul 2020 08:08:13 +0900 Subject: [PATCH 287/526] Use `.is_some()` not `Some(_)` --- clippy_lints/src/repeat_once.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/repeat_once.rs b/clippy_lints/src/repeat_once.rs index 3a0b3b1c257..a3af369e41e 100644 --- a/clippy_lints/src/repeat_once.rs +++ b/clippy_lints/src/repeat_once.rs @@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce { format!("{}.to_string()", snippet(cx, args[0].span, r#""...""#)), Applicability::MachineApplicable, ); - } else if let Some(_) = ty.builtin_index() { + } else if ty.builtin_index().is_some() { span_lint_and_sugg( cx, REPEAT_ONCE, From d067d0352bfc5a6979f477bc96c969b040437618 Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Tue, 14 Jul 2020 08:18:15 +0200 Subject: [PATCH 288/526] Add test for `needless_range_loop` issue Closes #2277 This was fixed when we fixed #2542. --- tests/ui/needless_range_loop2.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/ui/needless_range_loop2.rs b/tests/ui/needless_range_loop2.rs index 2ed1b09bece..a82b1159161 100644 --- a/tests/ui/needless_range_loop2.rs +++ b/tests/ui/needless_range_loop2.rs @@ -83,3 +83,13 @@ fn main() { println!("{}", arr[i]); } } + +mod issue2277 { + pub fn example(list: &[[f64; 3]]) { + let mut x: [f64; 3] = [10.; 3]; + + for i in 0..3 { + x[i] = list.iter().map(|item| item[i]).sum::<f64>(); + } + } +} From 126790999a128a880ca276c49afd2927a66ffbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Mon, 30 Mar 2020 11:02:14 +0200 Subject: [PATCH 289/526] new lint: Returning unit from closures expecting Ord This lint catches cases where the last statement of a closure expecting an instance of Ord has a trailing semi-colon. It compiles since the closure ends up return () which also implements Ord but causes unexpected results in cases such as sort_by_key. Fixes #5080 reprise: rebase, update and address all concerns --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 + clippy_lints/src/unit_return_expecting_ord.rs | 177 ++++++++++++++++++ src/lintlist/mod.rs | 7 + tests/ui/unit_return_expecting_ord.rs | 36 ++++ tests/ui/unit_return_expecting_ord.stderr | 39 ++++ 6 files changed, 265 insertions(+) create mode 100644 clippy_lints/src/unit_return_expecting_ord.rs create mode 100644 tests/ui/unit_return_expecting_ord.rs create mode 100644 tests/ui/unit_return_expecting_ord.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d08b44ba40..1c927b5f83a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1679,6 +1679,7 @@ Released 2018-09-13 [`uninit_assumed_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init [`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg [`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp +[`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord [`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 32e79317f82..7a4ca3902b3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -300,6 +300,7 @@ mod trivially_copy_pass_by_ref; mod try_err; mod types; mod unicode; +mod unit_return_expecting_ord; mod unnamed_address; mod unnecessary_sort_by; mod unnested_or_patterns; @@ -826,6 +827,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &unicode::NON_ASCII_LITERAL, &unicode::UNICODE_NOT_NFC, &unicode::ZERO_WIDTH_SPACE, + &unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD, &unnamed_address::FN_ADDRESS_COMPARISONS, &unnamed_address::VTABLE_ADDRESS_COMPARISONS, &unnecessary_sort_by::UNNECESSARY_SORT_BY, @@ -891,6 +893,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box attrs::Attributes); store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions); store.register_late_pass(|| box unicode::Unicode); + store.register_late_pass(|| box unit_return_expecting_ord::UnitReturnExpectingOrd); store.register_late_pass(|| box strings::StringAdd); store.register_late_pass(|| box implicit_return::ImplicitReturn); store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub); @@ -1436,6 +1439,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::UNNECESSARY_CAST), LintId::of(&types::VEC_BOX), LintId::of(&unicode::ZERO_WIDTH_SPACE), + LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS), LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS), LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), @@ -1692,6 +1696,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::CAST_REF_TO_MUT), LintId::of(&types::UNIT_CMP), LintId::of(&unicode::ZERO_WIDTH_SPACE), + LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS), LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS), LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs new file mode 100644 index 00000000000..fceb885516b --- /dev/null +++ b/clippy_lints/src/unit_return_expecting_ord.rs @@ -0,0 +1,177 @@ +use crate::utils::{get_trait_def_id, paths, span_lint, span_lint_and_help}; +use if_chain::if_chain; +use rustc_hir::def_id::DefId; +use rustc_hir::{Expr, ExprKind, StmtKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_middle::ty::{GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{BytePos, Span}; + +declare_clippy_lint! { + /// **What it does:** Checks for functions that expect closures of type + /// Fn(...) -> Ord where the implemented closure returns the unit type. + /// The lint also suggests to remove the semi-colon at the end of the statement if present. + /// + /// **Why is this bad?** Likely, returning the unit type is unintentional, and + /// could simply be caused by an extra semi-colon. Since () implements Ord + /// it doesn't cause a compilation error. + /// This is the same reasoning behind the unit_cmp lint. + /// + /// **Known problems:** If returning unit is intentional, then there is no + /// way of specifying this without triggering needless_return lint + /// + /// **Example:** + /// + /// ```rust + /// let mut twins = vec!((1,1), (2,2)); + /// twins.sort_by_key(|x| { x.1; }); + /// ``` + pub UNIT_RETURN_EXPECTING_ORD, + correctness, + "fn arguments of type Fn(...) -> Ord returning the unit type ()." +} + +declare_lint_pass!(UnitReturnExpectingOrd => [UNIT_RETURN_EXPECTING_ORD]); + +fn get_trait_predicates_for_trait_id<'tcx>( + cx: &LateContext<'tcx>, + generics: GenericPredicates<'tcx>, + trait_id: Option<DefId>, +) -> Vec<TraitPredicate<'tcx>> { + let mut preds = Vec::new(); + for (pred, _) in generics.predicates { + if_chain! { + if let PredicateKind::Trait(poly_trait_pred, _) = pred.kind(); + let trait_pred = cx.tcx.erase_late_bound_regions(&poly_trait_pred); + if let Some(trait_def_id) = trait_id; + if trait_def_id == trait_pred.trait_ref.def_id; + then { + preds.push(trait_pred); + } + } + } + preds +} + +fn get_projection_pred<'tcx>( + cx: &LateContext<'tcx>, + generics: GenericPredicates<'tcx>, + pred: TraitPredicate<'tcx>, +) -> Option<ProjectionPredicate<'tcx>> { + generics.predicates.iter().find_map(|(proj_pred, _)| { + if let PredicateKind::Projection(proj_pred) = proj_pred.kind() { + let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred); + if projection_pred.projection_ty.substs == pred.trait_ref.substs { + return Some(projection_pred); + } + } + None + }) +} + +fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Vec<(usize, String)> { + let mut args_to_check = Vec::new(); + if let Some(def_id) = cx.tables().type_dependent_def_id(expr.hir_id) { + let fn_sig = cx.tcx.fn_sig(def_id); + let generics = cx.tcx.predicates_of(def_id); + let fn_mut_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().fn_mut_trait()); + let ord_preds = get_trait_predicates_for_trait_id(cx, generics, get_trait_def_id(cx, &paths::ORD)); + let partial_ord_preds = + get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().partial_ord_trait()); + // Trying to call erase_late_bound_regions on fn_sig.inputs() gives the following error + // The trait `rustc::ty::TypeFoldable<'_>` is not implemented for `&[&rustc::ty::TyS<'_>]` + let inputs_output = cx.tcx.erase_late_bound_regions(&fn_sig.inputs_and_output()); + inputs_output + .iter() + .rev() + .skip(1) + .rev() + .enumerate() + .for_each(|(i, inp)| { + for trait_pred in &fn_mut_preds { + if_chain! { + if trait_pred.self_ty() == inp; + if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred); + then { + if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.ty) { + args_to_check.push((i, "Ord".to_string())); + } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.ty) { + args_to_check.push((i, "PartialOrd".to_string())); + } + } + } + } + }); + } + args_to_check +} + +fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Span, Option<Span>)> { + if_chain! { + if let ExprKind::Closure(_, _fn_decl, body_id, span, _) = arg.kind; + if let ty::Closure(_def_id, substs) = &cx.tables().node_type(arg.hir_id).kind; + let ret_ty = substs.as_closure().sig().output(); + let ty = cx.tcx.erase_late_bound_regions(&ret_ty); + if ty.is_unit(); + then { + if_chain! { + let body = cx.tcx.hir().body(body_id); + if let ExprKind::Block(block, _) = body.value.kind; + if block.expr.is_none(); + if let Some(stmt) = block.stmts.last(); + if let StmtKind::Semi(_) = stmt.kind; + then { + let data = stmt.span.data(); + // Make a span out of the semicolon for the help message + Some((span, Some(Span::new(data.hi-BytePos(1), data.hi, data.ctxt)))) + } else { + Some((span, None)) + } + } + } else { + None + } + } +} + +impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if let ExprKind::MethodCall(_, _, ref args, _) = expr.kind { + let arg_indices = get_args_to_check(cx, expr); + for (i, trait_name) in arg_indices { + if i < args.len() { + match check_arg(cx, &args[i]) { + Some((span, None)) => { + span_lint( + cx, + UNIT_RETURN_EXPECTING_ORD, + span, + &format!( + "this closure returns \ + the unit type which also implements {}", + trait_name + ), + ); + }, + Some((span, Some(last_semi))) => { + span_lint_and_help( + cx, + UNIT_RETURN_EXPECTING_ORD, + span, + &format!( + "this closure returns \ + the unit type which also implements {}", + trait_name + ), + Some(last_semi), + &"probably caused by this trailing semicolon".to_string(), + ); + }, + None => {}, + } + } + } + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index b89a8712862..96b004904aa 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2292,6 +2292,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "types", }, + Lint { + name: "unit_return_expecting_ord", + group: "correctness", + desc: "fn arguments of type Fn(...) -> Ord returning the unit type ().", + deprecation: None, + module: "unit_return_expecting_ord", + }, Lint { name: "unknown_clippy_lints", group: "style", diff --git a/tests/ui/unit_return_expecting_ord.rs b/tests/ui/unit_return_expecting_ord.rs new file mode 100644 index 00000000000..bdb4710cc69 --- /dev/null +++ b/tests/ui/unit_return_expecting_ord.rs @@ -0,0 +1,36 @@ +#![warn(clippy::unit_return_expecting_ord)] +#![allow(clippy::needless_return)] +#![allow(clippy::unused_unit)] +#![feature(is_sorted)] + +struct Struct { + field: isize, +} + +fn double(i: isize) -> isize { + i * 2 +} + +fn unit(_i: isize) {} + +fn main() { + let mut structs = vec![Struct { field: 2 }, Struct { field: 1 }]; + structs.sort_by_key(|s| { + double(s.field); + }); + structs.sort_by_key(|s| double(s.field)); + structs.is_sorted_by_key(|s| { + double(s.field); + }); + structs.is_sorted_by_key(|s| { + if s.field > 0 { + () + } else { + return (); + } + }); + structs.sort_by_key(|s| { + return double(s.field); + }); + structs.sort_by_key(|s| unit(s.field)); +} diff --git a/tests/ui/unit_return_expecting_ord.stderr b/tests/ui/unit_return_expecting_ord.stderr new file mode 100644 index 00000000000..e63d5874609 --- /dev/null +++ b/tests/ui/unit_return_expecting_ord.stderr @@ -0,0 +1,39 @@ +error: this closure returns the unit type which also implements Ord + --> $DIR/unit_return_expecting_ord.rs:18:25 + | +LL | structs.sort_by_key(|s| { + | ^^^ + | + = note: `-D clippy::unit-return-expecting-ord` implied by `-D warnings` +help: probably caused by this trailing semicolon + --> $DIR/unit_return_expecting_ord.rs:19:24 + | +LL | double(s.field); + | ^ + +error: this closure returns the unit type which also implements PartialOrd + --> $DIR/unit_return_expecting_ord.rs:22:30 + | +LL | structs.is_sorted_by_key(|s| { + | ^^^ + | +help: probably caused by this trailing semicolon + --> $DIR/unit_return_expecting_ord.rs:23:24 + | +LL | double(s.field); + | ^ + +error: this closure returns the unit type which also implements PartialOrd + --> $DIR/unit_return_expecting_ord.rs:25:30 + | +LL | structs.is_sorted_by_key(|s| { + | ^^^ + +error: this closure returns the unit type which also implements Ord + --> $DIR/unit_return_expecting_ord.rs:35:25 + | +LL | structs.sort_by_key(|s| unit(s.field)); + | ^^^ + +error: aborting due to 4 previous errors + From e83b3eb9930ab527451edaaa6f524acd26c1bf1c Mon Sep 17 00:00:00 2001 From: Brian Warner <warner@lothar.com> Date: Tue, 14 Jul 2020 09:20:19 -0700 Subject: [PATCH 290/526] formatting nits --- clippy_lints/src/methods/mod.rs | 2 +- tests/ui/iter_nth_zero.stderr | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 565a08f1292..69e985cc0a4 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2349,7 +2349,7 @@ fn lint_iter_nth_zero<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_ar ITER_NTH_ZERO, expr.span, "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent", - "try calling .next() instead of .nth(0)", + "try calling `.next()` instead of `.nth(0)`", format!("{}.next()", snippet_with_applicability(cx, nth_args[0].span, "..", &mut applicability)), applicability, ); diff --git a/tests/ui/iter_nth_zero.stderr b/tests/ui/iter_nth_zero.stderr index 6c4200a7905..29c56f3a94f 100644 --- a/tests/ui/iter_nth_zero.stderr +++ b/tests/ui/iter_nth_zero.stderr @@ -2,7 +2,7 @@ error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent --> $DIR/iter_nth_zero.rs:20:14 | LL | let _x = s.iter().nth(0); - | ^^^^^^^^^^^^^^^ help: try calling .next() instead of .nth(0): `s.iter().next()` + | ^^^^^^^^^^^^^^^ help: try calling `.next()` instead of `.nth(0)`: `s.iter().next()` | = note: `-D clippy::iter-nth-zero` implied by `-D warnings` @@ -10,13 +10,13 @@ error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent --> $DIR/iter_nth_zero.rs:25:14 | LL | let _y = iter.nth(0); - | ^^^^^^^^^^^ help: try calling .next() instead of .nth(0): `iter.next()` + | ^^^^^^^^^^^ help: try calling `.next()` instead of `.nth(0)`: `iter.next()` error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent --> $DIR/iter_nth_zero.rs:30:22 | LL | let _unwrapped = iter2.nth(0).unwrap(); - | ^^^^^^^^^^^^ help: try calling .next() instead of .nth(0): `iter2.next()` + | ^^^^^^^^^^^^ help: try calling `.next()` instead of `.nth(0)`: `iter2.next()` error: aborting due to 3 previous errors From a0640457a912720a5473d7feff40576a2f97df1e Mon Sep 17 00:00:00 2001 From: Leo Meira Vital <leo.vital@nubank.com.br> Date: Mon, 13 Jul 2020 01:57:19 -0300 Subject: [PATCH 291/526] Removing snippet from SHADOW_UNRELATED message. --- clippy_lints/src/shadow.rs | 6 +----- tests/ui/shadow.stderr | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 194786c5c41..fab13c8c124 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -295,11 +295,7 @@ fn lint_shadow<'tcx>( cx, SHADOW_UNRELATED, pattern_span, - &format!( - "`{}` is shadowed by `{}`", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..") - ), + &format!("`{}` is being shadowed", snippet(cx, pattern_span, "_")), |diag| { diag.span_note(expr.span, "initialization happens here"); diag.span_note(prev_span, "previous binding is here"); diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 7fa58cf7649..8a831375b41 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -104,7 +104,7 @@ note: previous binding is here LL | let x = (1, x); | ^ -error: `x` is shadowed by `y` +error: `x` is being shadowed --> $DIR/shadow.rs:34:9 | LL | let x = y; From ef896faa0153d0d96b6d6eafe7dd53b178525a25 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Thu, 16 Jul 2020 13:44:58 +0200 Subject: [PATCH 292/526] Fix deploy script for beta deployment Since the beta/ directory already exists, we can't copy the complete master dir --- .github/deploy.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/deploy.sh b/.github/deploy.sh index 3f425e5b725..e0a95fb9f36 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -19,7 +19,7 @@ fi if [[ $BETA = "true" ]]; then echo "Update documentation for the beta release" - cp -r out/master out/beta + cp -r out/master/* out/beta fi # Generate version index that is shown as root index page @@ -33,12 +33,11 @@ cd out git config user.name "GHA CI" git config user.email "gha@ci.invalid" -if git diff --exit-code --quiet; then - echo "No changes to the output on this push; exiting." - exit 0 -fi - if [[ -n $TAG_NAME ]]; then + if git diff --exit-code --quiet -- $TAG_NAME/; then + echo "No changes to the output on this push; exiting." + exit 0 + fi # Add the new dir git add "$TAG_NAME" # Update the symlink @@ -47,9 +46,17 @@ if [[ -n $TAG_NAME ]]; then git add versions.json git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}" elif [[ $BETA = "true" ]]; then + if git diff --exit-code --quiet -- beta/; then + echo "No changes to the output on this push; exiting." + exit 0 + fi git add beta git commit -m "Automatic deploy to GitHub Pages (beta): ${SHA}" else + if git diff --exit-code --quiet; then + echo "No changes to the output on this push; exiting." + exit 0 + fi git add . git commit -m "Automatic deploy to GitHub Pages: ${SHA}" fi From c65eb4d66314d22d85cf2e58ff20ec1ca7404751 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Thu, 16 Jul 2020 14:42:13 +0200 Subject: [PATCH 293/526] Track tag files, before checking for the diff --- .github/deploy.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/deploy.sh b/.github/deploy.sh index e0a95fb9f36..e85e8874ba6 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -34,6 +34,8 @@ git config user.name "GHA CI" git config user.email "gha@ci.invalid" if [[ -n $TAG_NAME ]]; then + # track files, so that the following check works + git add --intent-to-add "$TAG_NAME" if git diff --exit-code --quiet -- $TAG_NAME/; then echo "No changes to the output on this push; exiting." exit 0 From cf383cf48aa1bc09c50ae7d3599254c82b7dc0bf Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Thu, 16 Jul 2020 15:34:41 +0200 Subject: [PATCH 294/526] Update changelog to beta-1.46 --- CHANGELOG.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c927b5f83a..b9d0a15b755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,73 @@ document. ## Unreleased / In Rust Nightly -[7ea7cd1...master](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...master) +[c2c07fa...master](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...master) + +## Rust 1.46 + +Current beta, release 2020-08-27 + +[7ea7cd1...c2c07fa](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...master) + +### New lints + +* [`unnested_or_patterns`] [#5378](https://github.com/rust-lang/rust-clippy/pull/5378) +* [`iter_next_slice`] [#5597](https://github.com/rust-lang/rust-clippy/pull/5597) +* [`unnecessary_sort_by`] [#5623](https://github.com/rust-lang/rust-clippy/pull/5623) +* [`vec_resize_to_zero`] [#5637](https://github.com/rust-lang/rust-clippy/pull/5637) + +### Moves and Deprecations + +* Move [`cast_ptr_alignment`] to pedantic [#5667](https://github.com/rust-lang/rust-clippy/pull/5667) + +### Enhancements + +* Improve [`mem_replace_with_uninit`] lint [#5695](https://github.com/rust-lang/rust-clippy/pull/5695) + +### False Positive Fixes + +* [`len_zero`]: Avoid linting ranges when the `range_is_empty` feature is not enabled + [#5656](https://github.com/rust-lang/rust-clippy/pull/5656) +* [`let_and_return`]: Don't lint if a temporary borrow is involved + [#5680](https://github.com/rust-lang/rust-clippy/pull/5680) +* [`reversed_empty_ranges`]: Avoid linting `N..N` in for loop arguments in + [#5692](https://github.com/rust-lang/rust-clippy/pull/5692) +* [`if_same_then_else`]: Don't assume multiplication is always commutative + [#5702](https://github.com/rust-lang/rust-clippy/pull/5702) +* [`blacklisted_name`]: Remove `bar` from the default configuration + [#5712](https://github.com/rust-lang/rust-clippy/pull/5712) +* [`redundant_pattern_matching`]: Avoid suggesting non-`const fn` calls in const contexts + [#5724](https://github.com/rust-lang/rust-clippy/pull/5724) + +### Suggestion Fixes/Improvements + +* Fix suggestion of [`unit_arg`] lint, so that it suggest semantic equivalent code + [#4455](https://github.com/rust-lang/rust-clippy/pull/4455) +* Add auto applicable suggestion to [`macro_use_imports`] + [#5279](https://github.com/rust-lang/rust-clippy/pull/5279) + +### ICE Fixes + +* Fix ICE in the `consts` module of Clippy [#5709](https://github.com/rust-lang/rust-clippy/pull/5709) + +### Documentation Improvements + +* Improve code examples across multiple lints [#5664](https://github.com/rust-lang/rust-clippy/pull/5664) + +### Others + +* Introduce a `--rustc` flag to `clippy-driver`, which turns `clippy-driver` + into `rustc` and passes all the given arguments to `rustc`. This is especially + useful for tools that need the `rustc` version Clippy was compiled with, + instead of the Clippy version. E.g. `clippy-driver --rustc --version` will + print the output of `rustc --version`. + [#5178](https://github.com/rust-lang/rust-clippy/pull/5178) +* New issue templates now make it easier to complain if Clippy is too annoying + or not annoying enough! [#5735](https://github.com/rust-lang/rust-clippy/pull/5735) ## Rust 1.45 -Current beta, release 2020-07-16 +Current stable, released 2020-07-16 [891e1a8...7ea7cd1](https://github.com/rust-lang/rust-clippy/compare/891e1a8...7ea7cd1) @@ -87,7 +149,7 @@ and [`similar_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/565 ## Rust 1.44 -Current stable, released 2020-06-04 +Released 2020-06-04 [204bb9b...891e1a8](https://github.com/rust-lang/rust-clippy/compare/204bb9b...891e1a8) From aba0d244d419261f94b3d942953412e35c3e857e Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Thu, 16 Jul 2020 15:40:13 +0200 Subject: [PATCH 295/526] Typo: Change Log -> Changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9d0a15b755..776b04295f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Change Log +# Changelog All notable changes to this project will be documented in this file. See [Changelog Update](doc/changelog_update.md) if you want to update this From 70a41a92815a79c88dd9a2e8aa02503a3b95eae8 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 16 Jul 2020 16:51:12 -0700 Subject: [PATCH 296/526] Enable detecting multiple-argument panics --- clippy_lints/src/panic_unimplemented.rs | 9 ++-- tests/ui/panicking_macros.rs | 8 ++++ tests/ui/panicking_macros.stderr | 62 +++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 10f4694640e..9944b4096ba 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -96,23 +96,20 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { if_chain! { if let ExprKind::Block(ref block, _) = expr.kind; if let Some(ref ex) = block.expr; - if let Some(params) = match_function_call(cx, ex, &paths::BEGIN_PANIC); - if params.len() == 1; + if let Some(params) = match_function_call(cx, ex, &paths::BEGIN_PANIC) + .or(match_function_call(cx, ex, &paths::BEGIN_PANIC_FMT)); then { + let span = get_outer_span(expr); if is_expn_of(expr.span, "unimplemented").is_some() { - let span = get_outer_span(expr); span_lint(cx, UNIMPLEMENTED, span, "`unimplemented` should not be present in production code"); } else if is_expn_of(expr.span, "todo").is_some() { - let span = get_outer_span(expr); span_lint(cx, TODO, span, "`todo` should not be present in production code"); } else if is_expn_of(expr.span, "unreachable").is_some() { - let span = get_outer_span(expr); span_lint(cx, UNREACHABLE, span, "`unreachable` should not be present in production code"); } else if is_expn_of(expr.span, "panic").is_some() { - let span = get_outer_span(expr); span_lint(cx, PANIC, span, "`panic` should not be present in production code"); match_panic(params, expr, cx); diff --git a/tests/ui/panicking_macros.rs b/tests/ui/panicking_macros.rs index dabb695368d..f91ccfaed74 100644 --- a/tests/ui/panicking_macros.rs +++ b/tests/ui/panicking_macros.rs @@ -4,24 +4,32 @@ fn panic() { let a = 2; panic!(); + panic!("message"); + panic!("{} {}", "panic with", "multiple arguments"); let b = a + 2; } fn todo() { let a = 2; todo!(); + todo!("message"); + todo!("{} {}", "panic with", "multiple arguments"); let b = a + 2; } fn unimplemented() { let a = 2; unimplemented!(); + unimplemented!("message"); + unimplemented!("{} {}", "panic with", "multiple arguments"); let b = a + 2; } fn unreachable() { let a = 2; unreachable!(); + unreachable!("message"); + unreachable!("{} {}", "panic with", "multiple arguments"); let b = a + 2; } diff --git a/tests/ui/panicking_macros.stderr b/tests/ui/panicking_macros.stderr index 72319bc7e45..37c11d72a57 100644 --- a/tests/ui/panicking_macros.stderr +++ b/tests/ui/panicking_macros.stderr @@ -6,29 +6,83 @@ LL | panic!(); | = note: `-D clippy::panic` implied by `-D warnings` +error: `panic` should not be present in production code + --> $DIR/panicking_macros.rs:7:5 + | +LL | panic!("message"); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `panic` should not be present in production code + --> $DIR/panicking_macros.rs:8:5 + | +LL | panic!("{} {}", "panic with", "multiple arguments"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + error: `todo` should not be present in production code - --> $DIR/panicking_macros.rs:12:5 + --> $DIR/panicking_macros.rs:14:5 | LL | todo!(); | ^^^^^^^^ | = note: `-D clippy::todo` implied by `-D warnings` +error: `todo` should not be present in production code + --> $DIR/panicking_macros.rs:15:5 + | +LL | todo!("message"); + | ^^^^^^^^^^^^^^^^^ + +error: `todo` should not be present in production code + --> $DIR/panicking_macros.rs:16:5 + | +LL | todo!("{} {}", "panic with", "multiple arguments"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: `unimplemented` should not be present in production code - --> $DIR/panicking_macros.rs:18:5 + --> $DIR/panicking_macros.rs:22:5 | LL | unimplemented!(); | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unimplemented` implied by `-D warnings` -error: `unreachable` should not be present in production code +error: `unimplemented` should not be present in production code + --> $DIR/panicking_macros.rs:23:5 + | +LL | unimplemented!("message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `unimplemented` should not be present in production code --> $DIR/panicking_macros.rs:24:5 | +LL | unimplemented!("{} {}", "panic with", "multiple arguments"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `unreachable` should not be present in production code + --> $DIR/panicking_macros.rs:30:5 + | LL | unreachable!(); | ^^^^^^^^^^^^^^^ | = note: `-D clippy::unreachable` implied by `-D warnings` -error: aborting due to 4 previous errors +error: `unreachable` should not be present in production code + --> $DIR/panicking_macros.rs:31:5 + | +LL | unreachable!("message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `unreachable` should not be present in production code + --> $DIR/panicking_macros.rs:32:5 + | +LL | unreachable!("{} {}", "panic with", "multiple arguments"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors From 07867fde592babd74ee9934726c4c7010dee149b Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 16 Jul 2020 16:58:21 -0700 Subject: [PATCH 297/526] Clean up dogfood fallout --- clippy_lints/src/panic_unimplemented.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 9944b4096ba..6379dffd22e 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { if let ExprKind::Block(ref block, _) = expr.kind; if let Some(ref ex) = block.expr; if let Some(params) = match_function_call(cx, ex, &paths::BEGIN_PANIC) - .or(match_function_call(cx, ex, &paths::BEGIN_PANIC_FMT)); + .or_else(|| match_function_call(cx, ex, &paths::BEGIN_PANIC_FMT)); then { let span = get_outer_span(expr); if is_expn_of(expr.span, "unimplemented").is_some() { From 3618b97f59d9696c3e5ef83948269d0d7abfdc5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Fri, 17 Jul 2020 01:58:41 +0200 Subject: [PATCH 298/526] fix typos (found by codespell) --- clippy_lints/src/deprecated_lints.rs | 2 +- clippy_lints/src/dereference.rs | 2 +- clippy_lints/src/inherent_impl.rs | 2 +- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/missing_const_for_fn.rs | 2 +- clippy_lints/src/modulo_arithmetic.rs | 2 +- clippy_lints/src/option_if_let_else.rs | 2 +- clippy_lints/src/utils/numeric_literal.rs | 2 +- tests/ui/manual_async_fn.fixed | 2 +- tests/ui/manual_async_fn.rs | 2 +- tests/ui/manual_async_fn.stderr | 2 +- tests/ui/never_loop.rs | 2 +- tests/ui/precedence.fixed | 2 +- tests/ui/precedence.rs | 2 +- tests/ui/vec_resize_to_zero.rs | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 818d8188a78..c17a0e83330 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -153,7 +153,7 @@ declare_deprecated_lint! { /// /// **Deprecation reason:** Associated-constants are now preferred. pub REPLACE_CONSTS, - "associated-constants `MIN`/`MAX` of integers are prefered to `{min,max}_value()` and module constants" + "associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants" } declare_deprecated_lint! { diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 323cad7fa1a..7a3f35aca0a 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -10,7 +10,7 @@ use rustc_span::source_map::Span; declare_clippy_lint! { /// **What it does:** Checks for explicit `deref()` or `deref_mut()` method calls. /// - /// **Why is this bad?** Derefencing by `&*x` or `&mut *x` is clearer and more concise, + /// **Why is this bad?** Dereferencing by `&*x` or `&mut *x` is clearer and more concise, /// when not part of a method chain. /// /// **Example:** diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index bd7ca038839..9fb10c7f627 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { .. } = item.kind { - // Remember for each inherent implementation encoutered its span and generics + // Remember for each inherent implementation encountered its span and generics // but filter out implementations that have generic params (type or lifetime) // or are derived from a macro if !in_macro(item.span) && generics.params.is_empty() { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7a4ca3902b3..823afdfd289 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -463,7 +463,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ); store.register_removed( "clippy::replace_consts", - "associated-constants `MIN`/`MAX` of integers are prefered to `{min,max}_value()` and module constants", + "associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants", ); store.register_removed( "clippy::regex_macro", diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index bdce1bf1521..1ad184dfc46 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { /// Returns true if any of the method parameters is a type that implements `Drop`. The method /// can't be made const then, because `drop` can't be const-evaluated. fn method_accepts_dropable(cx: &LateContext<'_>, param_tys: &[hir::Ty<'_>]) -> bool { - // If any of the params are dropable, return true + // If any of the params are droppable, return true param_tys.iter().any(|hir_ty| { let ty_ty = hir_ty_to_ty(cx.tcx, hir_ty); has_drop(cx, ty_ty) diff --git a/clippy_lints/src/modulo_arithmetic.rs b/clippy_lints/src/modulo_arithmetic.rs index 59ccc6333fd..5041af750ce 100644 --- a/clippy_lints/src/modulo_arithmetic.rs +++ b/clippy_lints/src/modulo_arithmetic.rs @@ -8,7 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::fmt::Display; declare_clippy_lint! { - /// **What it does:** Checks for modulo arithemtic. + /// **What it does:** Checks for modulo arithmetic. /// /// **Why is this bad?** The results of modulo (%) operation might differ /// depending on the language, when negative numbers are involved. diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index 8dbe58763bf..9922d906118 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -78,7 +78,7 @@ fn is_result_ok(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool { } } -/// A struct containing information about occurences of the +/// A struct containing information about occurrences of the /// `if let Some(..) = .. else` construct that this lint detects. struct OptionIfLetElseOccurence { option: String, diff --git a/clippy_lints/src/utils/numeric_literal.rs b/clippy_lints/src/utils/numeric_literal.rs index 87cb454f654..5e8800d38eb 100644 --- a/clippy_lints/src/utils/numeric_literal.rs +++ b/clippy_lints/src/utils/numeric_literal.rs @@ -36,7 +36,7 @@ pub struct NumericLiteral<'a> { pub integer: &'a str, /// The fraction part of the number. pub fraction: Option<&'a str>, - /// The character used as exponent seperator (b'e' or b'E') and the exponent part. + /// The character used as exponent separator (b'e' or b'E') and the exponent part. pub exponent: Option<(char, &'a str)>, /// The type suffix, including preceding underscore if present. diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed index 6bb1032a172..27222cc0869 100644 --- a/tests/ui/manual_async_fn.fixed +++ b/tests/ui/manual_async_fn.fixed @@ -30,7 +30,7 @@ async fn already_async() -> impl Future<Output = i32> { struct S {} impl S { async fn inh_fut() -> i32 { - // NOTE: this code is here just to check that the identation is correct in the suggested fix + // NOTE: this code is here just to check that the indentation is correct in the suggested fix let a = 42; let b = 21; if a < b { diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs index d50c919188b..6a0f1b26c88 100644 --- a/tests/ui/manual_async_fn.rs +++ b/tests/ui/manual_async_fn.rs @@ -37,7 +37,7 @@ struct S {} impl S { fn inh_fut() -> impl Future<Output = i32> { async { - // NOTE: this code is here just to check that the identation is correct in the suggested fix + // NOTE: this code is here just to check that the indentation is correct in the suggested fix let a = 42; let b = 21; if a < b { diff --git a/tests/ui/manual_async_fn.stderr b/tests/ui/manual_async_fn.stderr index f278ee41aa3..a1904c904d0 100644 --- a/tests/ui/manual_async_fn.stderr +++ b/tests/ui/manual_async_fn.stderr @@ -57,7 +57,7 @@ LL | async fn inh_fut() -> i32 { help: move the body of the async block to the enclosing function | LL | fn inh_fut() -> impl Future<Output = i32> { -LL | // NOTE: this code is here just to check that the identation is correct in the suggested fix +LL | // NOTE: this code is here just to check that the indentation is correct in the suggested fix LL | let a = 42; LL | let b = 21; LL | if a < b { diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index cbc4ca39161..2770eb2b2ab 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -166,7 +166,7 @@ pub fn test14() { } } -// Issue #1991: the outter loop should not warn. +// Issue #1991: the outer loop should not warn. pub fn test15() { 'label: loop { while false { diff --git a/tests/ui/precedence.fixed b/tests/ui/precedence.fixed index 17b1f1bd0bf..4d284ae1319 100644 --- a/tests/ui/precedence.fixed +++ b/tests/ui/precedence.fixed @@ -32,7 +32,7 @@ fn main() { let _ = -(1i32.abs()); let _ = -(1f32.abs()); - // Odd functions shoud not trigger an error + // Odd functions should not trigger an error let _ = -1f64.asin(); let _ = -1f64.asinh(); let _ = -1f64.atan(); diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index 2d0891fd3c2..2d08e82f349 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -32,7 +32,7 @@ fn main() { let _ = -(1i32.abs()); let _ = -(1f32.abs()); - // Odd functions shoud not trigger an error + // Odd functions should not trigger an error let _ = -1f64.asin(); let _ = -1f64.asinh(); let _ = -1f64.atan(); diff --git a/tests/ui/vec_resize_to_zero.rs b/tests/ui/vec_resize_to_zero.rs index 0263e2f5f20..7ed27439ec6 100644 --- a/tests/ui/vec_resize_to_zero.rs +++ b/tests/ui/vec_resize_to_zero.rs @@ -7,7 +7,7 @@ fn main() { // not applicable vec![1, 2, 3, 4, 5].resize(2, 5); - // applicable here, but only implemented for integer litterals for now + // applicable here, but only implemented for integer literals for now vec!["foo", "bar", "baz"].resize(0, "bar"); // not applicable From e5105e82d31b254a81f38fbf38a8043ba41bee3a Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Fri, 17 Jul 2020 22:51:57 +0900 Subject: [PATCH 299/526] Fix typo --- clippy_lints/src/vec_resize_to_zero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/vec_resize_to_zero.rs b/clippy_lints/src/vec_resize_to_zero.rs index cc5e21a7ca6..7f90aedf161 100644 --- a/clippy_lints/src/vec_resize_to_zero.rs +++ b/clippy_lints/src/vec_resize_to_zero.rs @@ -11,7 +11,7 @@ use rustc_ast::ast::LitKind; use rustc_hir as hir; declare_clippy_lint! { - /// **What it does:** Finds occurences of `Vec::resize(0, an_int)` + /// **What it does:** Finds occurrences of `Vec::resize(0, an_int)` /// /// **Why is this bad?** This is probably an argument inversion mistake. /// From 7c5d4a41459abeb40eea734efaf08657602815cb Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Fri, 17 Jul 2020 09:27:43 -0700 Subject: [PATCH 300/526] Add test for correct behavior --- tests/ui/redundant_pattern_matching.fixed | 3 + tests/ui/redundant_pattern_matching.rs | 3 + tests/ui/redundant_pattern_matching.stderr | 68 ++++++++++++---------- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/tests/ui/redundant_pattern_matching.fixed b/tests/ui/redundant_pattern_matching.fixed index ce8582d2b22..adbff8af8d9 100644 --- a/tests/ui/redundant_pattern_matching.fixed +++ b/tests/ui/redundant_pattern_matching.fixed @@ -11,6 +11,9 @@ )] fn main() { + let result: Result<usize, usize> = Err(5); + if result.is_ok() {} + if Ok::<i32, i32>(42).is_ok() {} if Err::<i32, i32>(42).is_err() {} diff --git a/tests/ui/redundant_pattern_matching.rs b/tests/ui/redundant_pattern_matching.rs index a3a9aa40e3b..4c2870e7803 100644 --- a/tests/ui/redundant_pattern_matching.rs +++ b/tests/ui/redundant_pattern_matching.rs @@ -11,6 +11,9 @@ )] fn main() { + let result: Result<usize, usize> = Err(5); + if let Ok(_) = &result {} + if let Ok(_) = Ok::<i32, i32>(42) {} if let Err(_) = Err::<i32, i32>(42) {} diff --git a/tests/ui/redundant_pattern_matching.stderr b/tests/ui/redundant_pattern_matching.stderr index 25d1476062e..d3c9ceaa3d7 100644 --- a/tests/ui/redundant_pattern_matching.stderr +++ b/tests/ui/redundant_pattern_matching.stderr @@ -1,73 +1,79 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:14:12 + --> $DIR/redundant_pattern_matching.rs:15:12 | -LL | if let Ok(_) = Ok::<i32, i32>(42) {} - | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()` +LL | if let Ok(_) = &result {} + | -------^^^^^---------- help: try this: `if result.is_ok()` | = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching.rs:17:12 + | +LL | if let Ok(_) = Ok::<i32, i32>(42) {} + | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()` + error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:16:12 + --> $DIR/redundant_pattern_matching.rs:19:12 | LL | if let Err(_) = Err::<i32, i32>(42) {} | -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:18:12 + --> $DIR/redundant_pattern_matching.rs:21:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:20:12 + --> $DIR/redundant_pattern_matching.rs:23:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:22:12 + --> $DIR/redundant_pattern_matching.rs:25:12 | LL | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:28:15 + --> $DIR/redundant_pattern_matching.rs:31:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:30:15 + --> $DIR/redundant_pattern_matching.rs:33:15 | LL | while let None = Some(42) {} | ----------^^^^----------- help: try this: `while Some(42).is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:32:15 + --> $DIR/redundant_pattern_matching.rs:35:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try this: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:34:15 + --> $DIR/redundant_pattern_matching.rs:37:15 | LL | while let Ok(_) = Ok::<i32, i32>(10) {} | ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:36:15 + --> $DIR/redundant_pattern_matching.rs:39:15 | LL | while let Err(_) = Ok::<i32, i32>(10) {} | ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:39:15 + --> $DIR/redundant_pattern_matching.rs:42:15 | LL | while let Some(_) = v.pop() { | ----------^^^^^^^---------- help: try this: `while v.pop().is_some()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:55:5 + --> $DIR/redundant_pattern_matching.rs:58:5 | LL | / match Ok::<i32, i32>(42) { LL | | Ok(_) => true, @@ -76,7 +82,7 @@ LL | | }; | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:60:5 + --> $DIR/redundant_pattern_matching.rs:63:5 | LL | / match Ok::<i32, i32>(42) { LL | | Ok(_) => false, @@ -85,7 +91,7 @@ LL | | }; | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:65:5 + --> $DIR/redundant_pattern_matching.rs:68:5 | LL | / match Err::<i32, i32>(42) { LL | | Ok(_) => false, @@ -94,7 +100,7 @@ LL | | }; | |_____^ help: try this: `Err::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:70:5 + --> $DIR/redundant_pattern_matching.rs:73:5 | LL | / match Err::<i32, i32>(42) { LL | | Ok(_) => true, @@ -103,7 +109,7 @@ LL | | }; | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:75:5 + --> $DIR/redundant_pattern_matching.rs:78:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -112,7 +118,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:80:5 + --> $DIR/redundant_pattern_matching.rs:83:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -121,7 +127,7 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:85:13 + --> $DIR/redundant_pattern_matching.rs:88:13 | LL | let _ = match None::<()> { | _____________^ @@ -131,64 +137,64 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:90:20 + --> $DIR/redundant_pattern_matching.rs:93:20 | LL | let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false }; | -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:93:20 + --> $DIR/redundant_pattern_matching.rs:96:20 | LL | let x = if let Some(_) = opt { true } else { false }; | -------^^^^^^^------ help: try this: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:99:20 + --> $DIR/redundant_pattern_matching.rs:102:20 | LL | let _ = if let Some(_) = gen_opt() { | -------^^^^^^^------------ help: try this: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching.rs:101:19 + --> $DIR/redundant_pattern_matching.rs:104:19 | LL | } else if let None = gen_opt() { | -------^^^^------------ help: try this: `if gen_opt().is_none()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:103:19 + --> $DIR/redundant_pattern_matching.rs:106:19 | LL | } else if let Ok(_) = gen_res() { | -------^^^^^------------ help: try this: `if gen_res().is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:105:19 + --> $DIR/redundant_pattern_matching.rs:108:19 | LL | } else if let Err(_) = gen_res() { | -------^^^^^^------------ help: try this: `if gen_res().is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:138:19 + --> $DIR/redundant_pattern_matching.rs:141:19 | LL | while let Some(_) = r#try!(result_opt()) {} | ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:139:16 + --> $DIR/redundant_pattern_matching.rs:142:16 | LL | if let Some(_) = r#try!(result_opt()) {} | -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:145:12 + --> $DIR/redundant_pattern_matching.rs:148:12 | LL | if let Some(_) = m!() {} | -------^^^^^^^------- help: try this: `if m!().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:146:15 + --> $DIR/redundant_pattern_matching.rs:149:15 | LL | while let Some(_) = m!() {} | ----------^^^^^^^------- help: try this: `while m!().is_some()` -error: aborting due to 28 previous errors +error: aborting due to 29 previous errors From e85b590936863e88da4ccd73af9f5da0787b9609 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Fri, 17 Jul 2020 10:40:01 -0700 Subject: [PATCH 301/526] Fix bug in lint --- clippy_lints/src/matches.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index bd474c20807..fe00a48adef 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -1512,6 +1512,10 @@ mod redundant_pattern_match { } } + let result_expr = match &op.kind { + ExprKind::AddrOf(_, _, borrowed) => borrowed, + _ => op, + }; span_lint_and_then( cx, REDUNDANT_PATTERN_MATCHING, @@ -1524,7 +1528,7 @@ mod redundant_pattern_match { // while let ... = ... { ... } // ^^^ - let op_span = op.span.source_callsite(); + let op_span = result_expr.span.source_callsite(); // while let ... = ... { ... } // ^^^^^^^^^^^^^^^^^^^ @@ -1589,17 +1593,21 @@ mod redundant_pattern_match { }; if let Some(good_method) = found_good_method { + let span = expr.span.to(op.span); + let result_expr = match &op.kind { + ExprKind::AddrOf(_, _, borrowed) => borrowed, + _ => op, + }; span_lint_and_then( cx, REDUNDANT_PATTERN_MATCHING, expr.span, &format!("redundant pattern matching, consider using `{}`", good_method), |diag| { - let span = expr.span.to(op.span); diag.span_suggestion( span, "try this", - format!("{}.{}", snippet(cx, op.span, "_"), good_method), + format!("{}.{}", snippet(cx, result_expr.span, "_"), good_method), Applicability::MaybeIncorrect, // snippet ); }, From 3d3a13d8719893972e2146cde86672151e7d5476 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Fri, 17 Jul 2020 21:39:05 +0200 Subject: [PATCH 302/526] Fix sync fallout (fmt) --- clippy_lints/src/non_expressive_names.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 1d4772bb3d6..48ab98418e4 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -218,12 +218,16 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { let mut split_at = None; match existing_name.len.cmp(&count) { Ordering::Greater => { - if existing_name.len - count != 1 || levenstein_not_1(&interned_name, &existing_name.interned.as_str()) { + if existing_name.len - count != 1 + || levenstein_not_1(&interned_name, &existing_name.interned.as_str()) + { continue; } }, Ordering::Less => { - if count - existing_name.len != 1 || levenstein_not_1(&existing_name.interned.as_str(), &interned_name) { + if count - existing_name.len != 1 + || levenstein_not_1(&existing_name.interned.as_str(), &interned_name) + { continue; } }, From 442c8ae23b90874485468b3becfc011f8c9d40bb Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sat, 18 Jul 2020 23:59:34 +0200 Subject: [PATCH 303/526] Fix FP for `suspicious_arithmetic_impl` from `suspicious_trait_impl` lint --- clippy_lints/src/suspicious_trait_impl.rs | 37 +++++++++++------------ tests/ui/suspicious_arithmetic_impl.rs | 30 ++++++++++++++++++ 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 6d1d083fa8d..502fffc5e6c 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -64,26 +64,22 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { | hir::BinOpKind::Gt => return, _ => {}, } - // Check if the binary expression is part of another bi/unary expression - // or operator assignment as a child node - let mut parent_expr = cx.tcx.hir().get_parent_node(expr.hir_id); - while parent_expr != hir::CRATE_HIR_ID { - if let hir::Node::Expr(e) = cx.tcx.hir().get(parent_expr) { - match e.kind { - hir::ExprKind::Binary(..) - | hir::ExprKind::Unary(hir::UnOp::UnNot | hir::UnOp::UnNeg, _) - | hir::ExprKind::AssignOp(..) => return, - _ => {}, + + // Check for more than one binary operation in the implemented function + // Linting when multiple operations are involved can result in false positives + if_chain! { + let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id); + if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get(parent_fn); + if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind; + let body = cx.tcx.hir().body(body_id); + let mut visitor = BinaryExprVisitor { nb_binops: 0 }; + + then { + walk_expr(&mut visitor, &body.value); + if visitor.nb_binops > 1 { + return; } } - parent_expr = cx.tcx.hir().get_parent_node(parent_expr); - } - // as a parent node - let mut visitor = BinaryExprVisitor { in_binary_expr: false }; - walk_expr(&mut visitor, expr); - - if visitor.in_binary_expr { - return; } if let Some(impl_trait) = check_binop( @@ -181,7 +177,7 @@ fn check_binop( } struct BinaryExprVisitor { - in_binary_expr: bool, + nb_binops: u32, } impl<'tcx> Visitor<'tcx> for BinaryExprVisitor { @@ -191,12 +187,13 @@ impl<'tcx> Visitor<'tcx> for BinaryExprVisitor { match expr.kind { hir::ExprKind::Binary(..) | hir::ExprKind::Unary(hir::UnOp::UnNot | hir::UnOp::UnNeg, _) - | hir::ExprKind::AssignOp(..) => self.in_binary_expr = true, + | hir::ExprKind::AssignOp(..) => self.nb_binops += 1, _ => {}, } walk_expr(self, expr); } + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { NestedVisitorMap::None } diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index 1f5b9811887..60c2f3ec9b6 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -88,3 +88,33 @@ fn main() {} fn do_nothing(x: u32) -> u32 { x } + +struct MultipleBinops(u32); + +impl Add for MultipleBinops { + type Output = MultipleBinops; + + // OK: multiple Binops in `add` impl + fn add(self, other: Self) -> Self::Output { + let mut result = self.0 + other.0; + if result >= u32::max_value() { + result -= u32::max_value(); + } + MultipleBinops(result) + } +} + +impl Mul for MultipleBinops { + type Output = MultipleBinops; + + // OK: multiple Binops in `mul` impl + fn mul(self, other: Self) -> Self::Output { + let mut result: u32 = 0; + let size = std::cmp::max(self.0, other.0) as usize; + let mut v = vec![0; size + 1]; + for i in 0..size + 1 { + result *= i as u32; + } + MultipleBinops(result) + } +} From c720d823e1e633cccfd24e1df76cc04a628e83b0 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Tue, 14 Jul 2020 20:27:25 +0200 Subject: [PATCH 304/526] redundant_closure_call - don't lint when used more than once --- clippy_lints/src/misc_early.rs | 40 ++++++++++++++++++++------ tests/ui/redundant_closure_call.rs | 15 +++++++--- tests/ui/redundant_closure_call.stderr | 14 +++------ 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index b84a1a3fe24..125df226ceb 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -14,6 +14,7 @@ use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; +use rustc_span::symbol::Ident; declare_clippy_lint! { /// **What it does:** Checks for structure field patterns bound to wildcards. @@ -493,6 +494,29 @@ impl EarlyLintPass for MiscEarlyLints { } fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) { + fn count_closure_usage(block: &Block, ident: &Ident) -> usize { + struct ClosureUsageCount<'ast> { + ident: &'ast Ident, + count: usize, + }; + impl<'ast> Visitor<'ast> for ClosureUsageCount<'ast> { + fn visit_expr(&mut self, expr: &'ast Expr) { + if_chain! { + if let ExprKind::Call(ref closure, _) = expr.kind; + if let ExprKind::Path(_, ref path) = closure.kind; + if self.ident == &path.segments[0].ident; + then { + self.count += 1; + } + } + walk_expr(self, expr); + } + } + let mut closure_usage_count = ClosureUsageCount { ident, count: 0 }; + closure_usage_count.visit_block(block); + closure_usage_count.count + } + for w in block.stmts.windows(2) { if_chain! { if let StmtKind::Local(ref local) = w[0].kind; @@ -503,15 +527,15 @@ impl EarlyLintPass for MiscEarlyLints { if let ExprKind::Assign(_, ref call, _) = second.kind; if let ExprKind::Call(ref closure, _) = call.kind; if let ExprKind::Path(_, ref path) = closure.kind; + if ident == path.segments[0].ident; + if count_closure_usage(block, &ident) == 1; then { - if ident == path.segments[0].ident { - span_lint( - cx, - REDUNDANT_CLOSURE_CALL, - second.span, - "Closure called just once immediately after it was declared", - ); - } + span_lint( + cx, + REDUNDANT_CLOSURE_CALL, + second.span, + "Closure called just once immediately after it was declared", + ); } } } diff --git a/tests/ui/redundant_closure_call.rs b/tests/ui/redundant_closure_call.rs index bacd67db7c3..0f2ba4a075d 100644 --- a/tests/ui/redundant_closure_call.rs +++ b/tests/ui/redundant_closure_call.rs @@ -8,14 +8,21 @@ fn main() { k = (|a, b| a * b)(1, 5); - let closure = || 32; - i = closure(); - + // don't lint here, the closure is used more than once let closure = |i| i + 1; i = closure(3); - i = closure(4); + // lint here + let redun_closure = || 1; + i = redun_closure(); + + // the lint is applicable here but the lint doesn't support redefinition + let redefined_closure = || 1; + i = redefined_closure(); + let redefined_closure = || 2; + i = redefined_closure(); + #[allow(clippy::needless_return)] (|| return 2)(); (|| -> Option<i32> { None? })(); diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call.stderr index 68c1416bb6b..d5e0664319b 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call.stderr @@ -1,17 +1,11 @@ error: Closure called just once immediately after it was declared - --> $DIR/redundant_closure_call.rs:12:5 + --> $DIR/redundant_closure_call.rs:18:5 | -LL | i = closure(); - | ^^^^^^^^^^^^^ +LL | i = redun_closure(); + | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` -error: Closure called just once immediately after it was declared - --> $DIR/redundant_closure_call.rs:15:5 - | -LL | i = closure(3); - | ^^^^^^^^^^^^^^ - error: Try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call.rs:7:17 | @@ -24,5 +18,5 @@ error: Try not to call a closure in the expression where it is declared. LL | k = (|a, b| a * b)(1, 5); | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors From 0fecaf1abcbe8d4ba1a9c532b69aab6fab3097c8 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Sun, 19 Jul 2020 00:33:54 +0200 Subject: [PATCH 305/526] redundant_closure_call - extract lint from misc_early.rs, adapt to LatePass --- clippy_lints/src/lib.rs | 9 +- clippy_lints/src/misc_early.rs | 132 +-------------- clippy_lints/src/redundant_closure_call.rs | 151 ++++++++++++++++++ src/lintlist/mod.rs | 2 +- tests/ui/redundant_closure_call_early.rs | 19 +++ ...rr => redundant_closure_call_early.stderr} | 18 +-- ...call.rs => redundant_closure_call_late.rs} | 8 - tests/ui/redundant_closure_call_late.stderr | 10 ++ 8 files changed, 197 insertions(+), 152 deletions(-) create mode 100644 clippy_lints/src/redundant_closure_call.rs create mode 100644 tests/ui/redundant_closure_call_early.rs rename tests/ui/{redundant_closure_call.stderr => redundant_closure_call_early.stderr} (56%) rename tests/ui/{redundant_closure_call.rs => redundant_closure_call_late.rs} (72%) create mode 100644 tests/ui/redundant_closure_call_late.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 823afdfd289..f371942dbee 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -276,6 +276,7 @@ mod ptr_offset_with_cast; mod question_mark; mod ranges; mod redundant_clone; +mod redundant_closure_call; mod redundant_field_names; mod redundant_pub_crate; mod redundant_static_lifetimes; @@ -702,7 +703,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &misc_early::DOUBLE_NEG, &misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, &misc_early::MIXED_CASE_HEX_LITERALS, - &misc_early::REDUNDANT_CLOSURE_CALL, &misc_early::REDUNDANT_PATTERN, &misc_early::UNNEEDED_FIELD_PATTERN, &misc_early::UNNEEDED_WILDCARD_PATTERN, @@ -759,6 +759,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &ranges::RANGE_ZIP_WITH_LEN, &ranges::REVERSED_EMPTY_RANGES, &redundant_clone::REDUNDANT_CLONE, + &redundant_closure_call::REDUNDANT_CLOSURE_CALL, &redundant_field_names::REDUNDANT_FIELD_NAMES, &redundant_pub_crate::REDUNDANT_PUB_CRATE, &redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES, @@ -1018,6 +1019,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box int_plus_one::IntPlusOne); store.register_early_pass(|| box formatting::Formatting); store.register_early_pass(|| box misc_early::MiscEarlyLints); + store.register_early_pass(|| box redundant_closure_call::RedundantClosureCall); + store.register_late_pass(|| box redundant_closure_call::RedundantClosureCall); store.register_early_pass(|| box returns::Return); store.register_late_pass(|| box let_and_return::LetReturn); store.register_early_pass(|| box collapsible_if::CollapsibleIf); @@ -1359,7 +1362,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&misc_early::DOUBLE_NEG), LintId::of(&misc_early::DUPLICATE_UNDERSCORE_ARGUMENT), LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), - LintId::of(&misc_early::REDUNDANT_CLOSURE_CALL), LintId::of(&misc_early::REDUNDANT_PATTERN), LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN), LintId::of(&misc_early::ZERO_PREFIXED_LITERAL), @@ -1393,6 +1395,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ranges::RANGE_ZIP_WITH_LEN), LintId::of(&ranges::REVERSED_EMPTY_RANGES), LintId::of(&redundant_clone::REDUNDANT_CLONE), + LintId::of(&redundant_closure_call::REDUNDANT_CLOSURE_CALL), LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES), LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), LintId::of(&reference::DEREF_ADDROF), @@ -1593,7 +1596,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::UNNECESSARY_FILTER_MAP), LintId::of(&methods::USELESS_ASREF), LintId::of(&misc::SHORT_CIRCUIT_STATEMENT), - LintId::of(&misc_early::REDUNDANT_CLOSURE_CALL), LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN), LintId::of(&misc_early::ZERO_PREFIXED_LITERAL), LintId::of(&needless_bool::BOOL_COMPARISON), @@ -1608,6 +1610,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&precedence::PRECEDENCE), LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), LintId::of(&ranges::RANGE_ZIP_WITH_LEN), + LintId::of(&redundant_closure_call::REDUNDANT_CLOSURE_CALL), LintId::of(&reference::DEREF_ADDROF), LintId::of(&reference::REF_IN_DEREF), LintId::of(&repeat_once::REPEAT_ONCE), diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 125df226ceb..29aba7c1218 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -1,20 +1,15 @@ -use crate::utils::{ - constants, snippet_opt, snippet_with_applicability, span_lint, span_lint_and_help, span_lint_and_sugg, - span_lint_and_then, -}; -use if_chain::if_chain; +use crate::utils::{constants, snippet_opt, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use rustc_ast::ast::{ - BindingMode, Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, - NodeId, Pat, PatKind, StmtKind, UnOp, + BindingMode, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, + NodeId, Pat, PatKind, UnOp, }; -use rustc_ast::visit::{walk_expr, FnKind, Visitor}; +use rustc_ast::visit::FnKind; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::symbol::Ident; declare_clippy_lint! { /// **What it does:** Checks for structure field patterns bound to wildcards. @@ -71,28 +66,6 @@ declare_clippy_lint! { "function arguments having names which only differ by an underscore" } -declare_clippy_lint! { - /// **What it does:** Detects closures called in the same expression where they - /// are defined. - /// - /// **Why is this bad?** It is unnecessarily adding to the expression's - /// complexity. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust,ignore - /// // Bad - /// let a = (|| 42)() - /// - /// // Good - /// let a = 42 - /// ``` - pub REDUNDANT_CLOSURE_CALL, - complexity, - "throwaway closures called in the expression they are defined" -} - declare_clippy_lint! { /// **What it does:** Detects expressions of the form `--x`. /// @@ -279,7 +252,6 @@ declare_clippy_lint! { declare_lint_pass!(MiscEarlyLints => [ UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, - REDUNDANT_CLOSURE_CALL, DOUBLE_NEG, MIXED_CASE_HEX_LITERALS, UNSEPARATED_LITERAL_SUFFIX, @@ -289,30 +261,6 @@ declare_lint_pass!(MiscEarlyLints => [ UNNEEDED_WILDCARD_PATTERN, ]); -// Used to find `return` statements or equivalents e.g., `?` -struct ReturnVisitor { - found_return: bool, -} - -impl ReturnVisitor { - #[must_use] - fn new() -> Self { - Self { found_return: false } - } -} - -impl<'ast> Visitor<'ast> for ReturnVisitor { - fn visit_expr(&mut self, ex: &'ast Expr) { - if let ExprKind::Ret(_) = ex.kind { - self.found_return = true; - } else if let ExprKind::Try(_) = ex.kind { - self.found_return = true; - } - - walk_expr(self, ex) - } -} - impl EarlyLintPass for MiscEarlyLints { fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) { for param in &gen.params { @@ -454,30 +402,6 @@ impl EarlyLintPass for MiscEarlyLints { return; } match expr.kind { - ExprKind::Call(ref paren, _) => { - if let ExprKind::Paren(ref closure) = paren.kind { - if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.kind { - let mut visitor = ReturnVisitor::new(); - visitor.visit_expr(block); - if !visitor.found_return { - span_lint_and_then( - cx, - REDUNDANT_CLOSURE_CALL, - expr.span, - "Try not to call a closure in the expression where it is declared.", - |diag| { - if decl.inputs.is_empty() { - let mut app = Applicability::MachineApplicable; - let hint = - snippet_with_applicability(cx, block.span, "..", &mut app).into_owned(); - diag.span_suggestion(expr.span, "Try doing something like: ", hint, app); - } - }, - ); - } - } - } - }, ExprKind::Unary(UnOp::Neg, ref inner) => { if let ExprKind::Unary(UnOp::Neg, _) = inner.kind { span_lint( @@ -492,54 +416,6 @@ impl EarlyLintPass for MiscEarlyLints { _ => (), } } - - fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) { - fn count_closure_usage(block: &Block, ident: &Ident) -> usize { - struct ClosureUsageCount<'ast> { - ident: &'ast Ident, - count: usize, - }; - impl<'ast> Visitor<'ast> for ClosureUsageCount<'ast> { - fn visit_expr(&mut self, expr: &'ast Expr) { - if_chain! { - if let ExprKind::Call(ref closure, _) = expr.kind; - if let ExprKind::Path(_, ref path) = closure.kind; - if self.ident == &path.segments[0].ident; - then { - self.count += 1; - } - } - walk_expr(self, expr); - } - } - let mut closure_usage_count = ClosureUsageCount { ident, count: 0 }; - closure_usage_count.visit_block(block); - closure_usage_count.count - } - - for w in block.stmts.windows(2) { - if_chain! { - if let StmtKind::Local(ref local) = w[0].kind; - if let Option::Some(ref t) = local.init; - if let ExprKind::Closure(..) = t.kind; - if let PatKind::Ident(_, ident, _) = local.pat.kind; - if let StmtKind::Semi(ref second) = w[1].kind; - if let ExprKind::Assign(_, ref call, _) = second.kind; - if let ExprKind::Call(ref closure, _) = call.kind; - if let ExprKind::Path(_, ref path) = closure.kind; - if ident == path.segments[0].ident; - if count_closure_usage(block, &ident) == 1; - then { - span_lint( - cx, - REDUNDANT_CLOSURE_CALL, - second.span, - "Closure called just once immediately after it was declared", - ); - } - } - } - } } impl MiscEarlyLints { diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs new file mode 100644 index 00000000000..391d70af159 --- /dev/null +++ b/clippy_lints/src/redundant_closure_call.rs @@ -0,0 +1,151 @@ +use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_then}; +use if_chain::if_chain; +use rustc_ast::ast; +use rustc_ast::visit as ast_visit; +use rustc_ast::visit::Visitor as AstVisitor; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_hir::intravisit as hir_visit; +use rustc_hir::intravisit::Visitor as HirVisitor; +use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::Ident; + +declare_clippy_lint! { + /// **What it does:** Detects closures called in the same expression where they + /// are defined. + /// + /// **Why is this bad?** It is unnecessarily adding to the expression's + /// complexity. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust,ignore + /// // Bad + /// let a = (|| 42)() + /// + /// // Good + /// let a = 42 + /// ``` + pub REDUNDANT_CLOSURE_CALL, + complexity, + "throwaway closures called in the expression they are defined" +} + +declare_lint_pass!(RedundantClosureCall => [REDUNDANT_CLOSURE_CALL]); + +// Used to find `return` statements or equivalents e.g., `?` +struct ReturnVisitor { + found_return: bool, +} + +impl ReturnVisitor { + #[must_use] + fn new() -> Self { + Self { found_return: false } + } +} + +impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor { + fn visit_expr(&mut self, ex: &'ast ast::Expr) { + if let ast::ExprKind::Ret(_) = ex.kind { + self.found_return = true; + } else if let ast::ExprKind::Try(_) = ex.kind { + self.found_return = true; + } + + ast_visit::walk_expr(self, ex) + } +} + +impl EarlyLintPass for RedundantClosureCall { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { + if in_external_macro(cx.sess(), expr.span) { + return; + } + if_chain! { + if let ast::ExprKind::Call(ref paren, _) = expr.kind; + if let ast::ExprKind::Paren(ref closure) = paren.kind; + if let ast::ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.kind; + then { + let mut visitor = ReturnVisitor::new(); + visitor.visit_expr(block); + if !visitor.found_return { + span_lint_and_then( + cx, + REDUNDANT_CLOSURE_CALL, + expr.span, + "Try not to call a closure in the expression where it is declared.", + |diag| { + if decl.inputs.is_empty() { + let mut app = Applicability::MachineApplicable; + let hint = + snippet_with_applicability(cx, block.span, "..", &mut app).into_owned(); + diag.span_suggestion(expr.span, "Try doing something like: ", hint, app); + } + }, + ); + } + } + } + } +} + +impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { + fn count_closure_usage<'tcx>(block: &'tcx hir::Block<'_>, ident: &'tcx Ident) -> usize { + struct ClosureUsageCount<'tcx> { + ident: &'tcx Ident, + count: usize, + }; + impl<'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'tcx> { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { + if_chain! { + if let hir::ExprKind::Call(ref closure, _) = expr.kind; + if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind; + if self.ident == &path.segments[0].ident; + then { + self.count += 1; + } + } + hir_visit::walk_expr(self, expr); + } + + fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> { + hir_visit::NestedVisitorMap::None + } + }; + let mut closure_usage_count = ClosureUsageCount { ident, count: 0 }; + closure_usage_count.visit_block(block); + closure_usage_count.count + } + + for w in block.stmts.windows(2) { + if_chain! { + if let hir::StmtKind::Local(ref local) = w[0].kind; + if let Option::Some(ref t) = local.init; + if let hir::ExprKind::Closure(..) = t.kind; + if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind; + if let hir::StmtKind::Semi(ref second) = w[1].kind; + if let hir::ExprKind::Assign(_, ref call, _) = second.kind; + if let hir::ExprKind::Call(ref closure, _) = call.kind; + if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind; + if ident == path.segments[0].ident; + if count_closure_usage(block, &ident) == 1; + then { + span_lint( + cx, + REDUNDANT_CLOSURE_CALL, + second.span, + "Closure called just once immediately after it was declared", + ); + } + } + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 96b004904aa..1879aae77fb 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1835,7 +1835,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ group: "complexity", desc: "throwaway closures called in the expression they are defined", deprecation: None, - module: "misc_early", + module: "redundant_closure_call", }, Lint { name: "redundant_closure_for_method_calls", diff --git a/tests/ui/redundant_closure_call_early.rs b/tests/ui/redundant_closure_call_early.rs new file mode 100644 index 00000000000..3dd365620cc --- /dev/null +++ b/tests/ui/redundant_closure_call_early.rs @@ -0,0 +1,19 @@ +// non rustfixable, see redundant_closure_call_fixable.rs + +#![warn(clippy::redundant_closure_call)] + +fn main() { + let mut i = 1; + + // lint here + let mut k = (|m| m + 1)(i); + + // lint here + k = (|a, b| a * b)(1, 5); + + // don't lint these + #[allow(clippy::needless_return)] + (|| return 2)(); + (|| -> Option<i32> { None? })(); + (|| -> Result<i32, i32> { Err(2)? })(); +} diff --git a/tests/ui/redundant_closure_call.stderr b/tests/ui/redundant_closure_call_early.stderr similarity index 56% rename from tests/ui/redundant_closure_call.stderr rename to tests/ui/redundant_closure_call_early.stderr index d5e0664319b..0ac97ae25d0 100644 --- a/tests/ui/redundant_closure_call.stderr +++ b/tests/ui/redundant_closure_call_early.stderr @@ -1,22 +1,16 @@ -error: Closure called just once immediately after it was declared - --> $DIR/redundant_closure_call.rs:18:5 +error: Try not to call a closure in the expression where it is declared. + --> $DIR/redundant_closure_call_early.rs:9:17 | -LL | i = redun_closure(); - | ^^^^^^^^^^^^^^^^^^^ +LL | let mut k = (|m| m + 1)(i); + | ^^^^^^^^^^^^^^ | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:7:17 - | -LL | let mut k = (|m| m + 1)(i); - | ^^^^^^^^^^^^^^ - -error: Try not to call a closure in the expression where it is declared. - --> $DIR/redundant_closure_call.rs:9:9 + --> $DIR/redundant_closure_call_early.rs:12:9 | LL | k = (|a, b| a * b)(1, 5); | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/redundant_closure_call.rs b/tests/ui/redundant_closure_call_late.rs similarity index 72% rename from tests/ui/redundant_closure_call.rs rename to tests/ui/redundant_closure_call_late.rs index 0f2ba4a075d..21ee58e5b44 100644 --- a/tests/ui/redundant_closure_call.rs +++ b/tests/ui/redundant_closure_call_late.rs @@ -4,9 +4,6 @@ fn main() { let mut i = 1; - let mut k = (|m| m + 1)(i); - - k = (|a, b| a * b)(1, 5); // don't lint here, the closure is used more than once let closure = |i| i + 1; @@ -22,9 +19,4 @@ fn main() { i = redefined_closure(); let redefined_closure = || 2; i = redefined_closure(); - - #[allow(clippy::needless_return)] - (|| return 2)(); - (|| -> Option<i32> { None? })(); - (|| -> Result<i32, i32> { Err(2)? })(); } diff --git a/tests/ui/redundant_closure_call_late.stderr b/tests/ui/redundant_closure_call_late.stderr new file mode 100644 index 00000000000..0aebc3c419e --- /dev/null +++ b/tests/ui/redundant_closure_call_late.stderr @@ -0,0 +1,10 @@ +error: Closure called just once immediately after it was declared + --> $DIR/redundant_closure_call_late.rs:15:5 + | +LL | i = redun_closure(); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::redundant-closure-call` implied by `-D warnings` + +error: aborting due to previous error + From 9603d9652b9d172842c77f566121437768bc962f Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Sun, 19 Jul 2020 11:47:32 +0200 Subject: [PATCH 306/526] redundant_closure_call - add support for shadowed closures --- clippy_lints/src/redundant_closure_call.rs | 12 ++++++------ tests/ui/redundant_closure_call_late.rs | 15 ++++++++++----- tests/ui/redundant_closure_call_late.stderr | 14 +++++++++++++- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index 391d70af159..9477e79f567 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -11,7 +11,6 @@ use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintCon use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::symbol::Ident; declare_clippy_lint! { /// **What it does:** Detects closures called in the same expression where they @@ -96,9 +95,9 @@ impl EarlyLintPass for RedundantClosureCall { impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { - fn count_closure_usage<'tcx>(block: &'tcx hir::Block<'_>, ident: &'tcx Ident) -> usize { + fn count_closure_usage<'tcx>(block: &'tcx hir::Block<'_>, path: &'tcx hir::Path<'tcx>) -> usize { struct ClosureUsageCount<'tcx> { - ident: &'tcx Ident, + path: &'tcx hir::Path<'tcx>, count: usize, }; impl<'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'tcx> { @@ -108,7 +107,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { if_chain! { if let hir::ExprKind::Call(ref closure, _) = expr.kind; if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind; - if self.ident == &path.segments[0].ident; + if self.path.segments[0].ident == path.segments[0].ident + && self.path.res == path.res; then { self.count += 1; } @@ -120,7 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { hir_visit::NestedVisitorMap::None } }; - let mut closure_usage_count = ClosureUsageCount { ident, count: 0 }; + let mut closure_usage_count = ClosureUsageCount { path, count: 0 }; closure_usage_count.visit_block(block); closure_usage_count.count } @@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { if let hir::ExprKind::Call(ref closure, _) = call.kind; if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind; if ident == path.segments[0].ident; - if count_closure_usage(block, &ident) == 1; + if count_closure_usage(block, path) == 1; then { span_lint( cx, diff --git a/tests/ui/redundant_closure_call_late.rs b/tests/ui/redundant_closure_call_late.rs index 21ee58e5b44..e29a1dce0c7 100644 --- a/tests/ui/redundant_closure_call_late.rs +++ b/tests/ui/redundant_closure_call_late.rs @@ -14,9 +14,14 @@ fn main() { let redun_closure = || 1; i = redun_closure(); - // the lint is applicable here but the lint doesn't support redefinition - let redefined_closure = || 1; - i = redefined_closure(); - let redefined_closure = || 2; - i = redefined_closure(); + // shadowed closures are supported, lint here + let shadowed_closure = || 1; + i = shadowed_closure(); + let shadowed_closure = || 2; + i = shadowed_closure(); + + // don't lint here + let shadowed_closure = || 2; + i = shadowed_closure(); + i = shadowed_closure(); } diff --git a/tests/ui/redundant_closure_call_late.stderr b/tests/ui/redundant_closure_call_late.stderr index 0aebc3c419e..0e000fee85a 100644 --- a/tests/ui/redundant_closure_call_late.stderr +++ b/tests/ui/redundant_closure_call_late.stderr @@ -6,5 +6,17 @@ LL | i = redun_closure(); | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` -error: aborting due to previous error +error: Closure called just once immediately after it was declared + --> $DIR/redundant_closure_call_late.rs:19:5 + | +LL | i = shadowed_closure(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: Closure called just once immediately after it was declared + --> $DIR/redundant_closure_call_late.rs:21:5 + | +LL | i = shadowed_closure(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors From 1ac8b85c9fd38ff0a14061cae0b4d31e9bfafd56 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Mon, 20 Jul 2020 00:36:31 +0200 Subject: [PATCH 307/526] redundant_closure_call - pr review --- clippy_lints/src/redundant_closure_call.rs | 8 ++++---- tests/ui/redundant_closure_call_early.stderr | 4 ++-- tests/ui/redundant_closure_call_fixable.stderr | 4 ++-- tests/ui/redundant_closure_call_late.stderr | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index 9477e79f567..8aa478ea2d6 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -77,13 +77,13 @@ impl EarlyLintPass for RedundantClosureCall { cx, REDUNDANT_CLOSURE_CALL, expr.span, - "Try not to call a closure in the expression where it is declared.", + "try not to call a closure in the expression where it is declared.", |diag| { if decl.inputs.is_empty() { let mut app = Applicability::MachineApplicable; let hint = snippet_with_applicability(cx, block.span, "..", &mut app).into_owned(); - diag.span_suggestion(expr.span, "Try doing something like: ", hint, app); + diag.span_suggestion(expr.span, "try doing something like", hint, app); } }, ); @@ -136,13 +136,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { if let hir::ExprKind::Call(ref closure, _) = call.kind; if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind; if ident == path.segments[0].ident; - if count_closure_usage(block, path) == 1; + if count_closure_usage(block, path) == 1; then { span_lint( cx, REDUNDANT_CLOSURE_CALL, second.span, - "Closure called just once immediately after it was declared", + "closure called just once immediately after it was declared", ); } } diff --git a/tests/ui/redundant_closure_call_early.stderr b/tests/ui/redundant_closure_call_early.stderr index 0ac97ae25d0..79f27663461 100644 --- a/tests/ui/redundant_closure_call_early.stderr +++ b/tests/ui/redundant_closure_call_early.stderr @@ -1,4 +1,4 @@ -error: Try not to call a closure in the expression where it is declared. +error: try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call_early.rs:9:17 | LL | let mut k = (|m| m + 1)(i); @@ -6,7 +6,7 @@ LL | let mut k = (|m| m + 1)(i); | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` -error: Try not to call a closure in the expression where it is declared. +error: try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call_early.rs:12:9 | LL | k = (|a, b| a * b)(1, 5); diff --git a/tests/ui/redundant_closure_call_fixable.stderr b/tests/ui/redundant_closure_call_fixable.stderr index e7737f9dd85..644161d9f5d 100644 --- a/tests/ui/redundant_closure_call_fixable.stderr +++ b/tests/ui/redundant_closure_call_fixable.stderr @@ -1,8 +1,8 @@ -error: Try not to call a closure in the expression where it is declared. +error: try not to call a closure in the expression where it is declared. --> $DIR/redundant_closure_call_fixable.rs:7:13 | LL | let a = (|| 42)(); - | ^^^^^^^^^ help: Try doing something like: : `42` + | ^^^^^^^^^ help: try doing something like: `42` | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` diff --git a/tests/ui/redundant_closure_call_late.stderr b/tests/ui/redundant_closure_call_late.stderr index 0e000fee85a..7c8865f1bd3 100644 --- a/tests/ui/redundant_closure_call_late.stderr +++ b/tests/ui/redundant_closure_call_late.stderr @@ -1,4 +1,4 @@ -error: Closure called just once immediately after it was declared +error: closure called just once immediately after it was declared --> $DIR/redundant_closure_call_late.rs:15:5 | LL | i = redun_closure(); @@ -6,13 +6,13 @@ LL | i = redun_closure(); | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` -error: Closure called just once immediately after it was declared +error: closure called just once immediately after it was declared --> $DIR/redundant_closure_call_late.rs:19:5 | LL | i = shadowed_closure(); | ^^^^^^^^^^^^^^^^^^^^^^ -error: Closure called just once immediately after it was declared +error: closure called just once immediately after it was declared --> $DIR/redundant_closure_call_late.rs:21:5 | LL | i = shadowed_closure(); From a5cdd4aeb11fad6b0bf73d342398700a27c4484b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com> Date: Mon, 20 Jul 2020 00:00:00 +0000 Subject: [PATCH 308/526] Ignore not really redundant clones of ManuallyDrop "Redundant" clones of `ManuallyDrop` are sometimes used for the side effect of invoking the clone, without running the drop implementation of the inner type. In other words, they aren't really redundant. For example, futures-rs crate: ```rust #[allow(clippy::redundant_clone)] // The clone here isn't actually redundant. unsafe fn increase_refcount<T: ArcWake>(data: *const ()) { // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop let arc = mem::ManuallyDrop::new(Arc::<T>::from_raw(data as *const T)); // Now increase refcount, but don't drop new refcount either let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); } ``` Ignore redundant clone lint for ManuallyDrop. --- clippy_lints/src/redundant_clone.rs | 6 +++++ clippy_lints/src/utils/paths.rs | 1 + tests/ui/redundant_clone.fixed | 15 ++++++++++++ tests/ui/redundant_clone.rs | 15 ++++++++++++ tests/ui/redundant_clone.stderr | 38 ++++++++++++++--------------- 5 files changed, 56 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index fda7480194d..7932be0d4b1 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -124,6 +124,12 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { continue; } + if let ty::Adt(ref def, _) = arg_ty.kind { + if match_def_path(cx, def.did, &paths::MEM_MANUALLY_DROP) { + continue; + } + } + // `{ cloned = &arg; clone(move cloned); }` or `{ cloned = &arg; to_path_buf(cloned); }` let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(cx, mir, arg, from_borrow, bb)); diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 4c3462802e9..a515ee29c82 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -59,6 +59,7 @@ pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "Link pub const LINT: [&str; 3] = ["rustc_session", "lint", "Lint"]; pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"]; pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; +pub const MEM_MANUALLY_DROP: [&str; 4] = ["core", "mem", "manually_drop", "ManuallyDrop"]; pub const MEM_MAYBEUNINIT: [&str; 4] = ["core", "mem", "maybe_uninit", "MaybeUninit"]; pub const MEM_MAYBEUNINIT_UNINIT: [&str; 5] = ["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]; pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"]; diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 764c10a6d39..cdeefda4c23 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -52,6 +52,7 @@ fn main() { borrower_propagation(); not_consumed(); issue_5405(); + manually_drop(); } #[derive(Clone)] @@ -170,3 +171,17 @@ fn issue_5405() { let c: [usize; 2] = [2, 3]; let _d: usize = c[1].clone(); } + +fn manually_drop() { + use std::mem::ManuallyDrop; + use std::sync::Arc; + + let a = ManuallyDrop::new(Arc::new("Hello!".to_owned())); + let _ = a.clone(); // OK + + let p: *const String = Arc::into_raw(ManuallyDrop::into_inner(a)); + unsafe { + Arc::from_raw(p); + Arc::from_raw(p); + } +} diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index 839747b131d..acb7ffb305f 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -52,6 +52,7 @@ fn main() { borrower_propagation(); not_consumed(); issue_5405(); + manually_drop(); } #[derive(Clone)] @@ -170,3 +171,17 @@ fn issue_5405() { let c: [usize; 2] = [2, 3]; let _d: usize = c[1].clone(); } + +fn manually_drop() { + use std::mem::ManuallyDrop; + use std::sync::Arc; + + let a = ManuallyDrop::new(Arc::new("Hello!".to_owned())); + let _ = a.clone(); // OK + + let p: *const String = Arc::into_raw(ManuallyDrop::into_inner(a)); + unsafe { + Arc::from_raw(p); + Arc::from_raw(p); + } +} diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index eced198283c..89b39254299 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -108,61 +108,61 @@ LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:61:22 + --> $DIR/redundant_clone.rs:62:22 | LL | (a.clone(), a.clone()) | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:61:21 + --> $DIR/redundant_clone.rs:62:21 | LL | (a.clone(), a.clone()) | ^ -error: redundant clone - --> $DIR/redundant_clone.rs:121:15 - | -LL | let _s = s.clone(); - | ^^^^^^^^ help: remove this - | -note: this value is dropped without further use - --> $DIR/redundant_clone.rs:121:14 - | -LL | let _s = s.clone(); - | ^ - error: redundant clone --> $DIR/redundant_clone.rs:122:15 | -LL | let _t = t.clone(); +LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:122:14 | +LL | let _s = s.clone(); + | ^ + +error: redundant clone + --> $DIR/redundant_clone.rs:123:15 + | +LL | let _t = t.clone(); + | ^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:123:14 + | LL | let _t = t.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:132:19 + --> $DIR/redundant_clone.rs:133:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:132:18 + --> $DIR/redundant_clone.rs:133:18 | LL | let _f = f.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:144:14 + --> $DIR/redundant_clone.rs:145:14 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^ help: remove this | note: cloned value is neither consumed nor mutated - --> $DIR/redundant_clone.rs:144:13 + --> $DIR/redundant_clone.rs:145:13 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^^ From 142a273441d1cf2039bd2857ee57cfa402e2a3f7 Mon Sep 17 00:00:00 2001 From: Yuki Okushi <huyuumi.dev@gmail.com> Date: Wed, 22 Jul 2020 05:23:55 +0900 Subject: [PATCH 309/526] Use `(std::)f64::EPSILON` in the examples as suggested in the lints --- clippy_lints/src/misc.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index fc10e5077b8..26a1c32b6b3 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -99,7 +99,9 @@ declare_clippy_lint! { /// if y != x {} // where both are floats /// /// // Good - /// let error = 0.01f64; // Use an epsilon for comparison + /// let error = f64::EPSILON; // Use an epsilon for comparison + /// // Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead. + /// // let error = std::f64::EPSILON; /// if (y - 1.23f64).abs() < error { } /// if (y - x).abs() > error { } /// ``` @@ -237,10 +239,12 @@ declare_clippy_lint! { /// const ONE: f64 = 1.00; /// /// // Bad - /// if x == ONE { } // where both are floats + /// if x == ONE { } // where both are floats /// /// // Good - /// let error = 0.1f64; // Use an epsilon for comparison + /// let error = f64::EPSILON; // Use an epsilon for comparison + /// // Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead. + /// // let error = std::f64::EPSILON; /// if (x - ONE).abs() < error { } /// ``` pub FLOAT_CMP_CONST, From 51f2a6f8b6eea9ebefddff39e87a1ca16c59827c Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Wed, 22 Jul 2020 16:39:58 +0200 Subject: [PATCH 310/526] Add documentation for basic Clippy hacking --- CONTRIBUTING.md | 22 ++++----- doc/adding_lints.md | 7 +-- doc/basics.md | 106 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 16 deletions(-) create mode 100644 doc/basics.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 69a734e4ee4..dfc5cc077c3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,7 +32,7 @@ High level approach: 1. Find something to fix/improve 2. Change code (likely some file in `clippy_lints/src/`) -3. Follow the instructions in the [docs for writing lints](doc/adding_lints.md) such as running the `setup-toolchain.sh` script +3. Follow the instructions in the [Basics docs](doc/basics.md) such as running the `setup-toolchain.sh` script 4. Run `cargo test` in the root directory and wiggle code until it passes 5. Open a PR (also can be done after 2. if you run into problems) @@ -95,16 +95,16 @@ quick read. ## Getting code-completion for rustc internals to work -Unfortunately, [`rust-analyzer`][ra_homepage] does not (yet?) understand how Clippy uses compiler-internals -using `extern crate` and it also needs to be able to read the source files of the rustc-compiler which are not -available via a `rustup` component at the time of writing. -To work around this, you need to have a copy of the [rustc-repo][rustc_repo] available which can be obtained via -`git clone https://github.com/rust-lang/rust/`. -Then you can run a `cargo dev` command to automatically make Clippy use the rustc-repo via path-dependencies -which rust-analyzer will be able to understand. -Run `cargo dev ra-setup --repo-path <repo-path>` where `<repo-path>` is an absolute path to the rustc repo -you just cloned. -The command will add path-dependencies pointing towards rustc-crates inside the rustc repo to +Unfortunately, [`rust-analyzer`][ra_homepage] does not (yet?) understand how Clippy uses compiler-internals +using `extern crate` and it also needs to be able to read the source files of the rustc-compiler which are not +available via a `rustup` component at the time of writing. +To work around this, you need to have a copy of the [rustc-repo][rustc_repo] available which can be obtained via +`git clone https://github.com/rust-lang/rust/`. +Then you can run a `cargo dev` command to automatically make Clippy use the rustc-repo via path-dependencies +which rust-analyzer will be able to understand. +Run `cargo dev ra-setup --repo-path <repo-path>` where `<repo-path>` is an absolute path to the rustc repo +you just cloned. +The command will add path-dependencies pointing towards rustc-crates inside the rustc repo to Clippys `Cargo.toml`s and should allow rust-analyzer to understand most of the types that Clippy uses. Just make sure to remove the dependencies again before finally making a pull request! diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 8092be277cc..d5f4f5d5659 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -27,10 +27,7 @@ because that's clearly a non-descriptive name. ## Setup -When working on Clippy, you will need the current git master version of rustc, -which can change rapidly. Make sure you're working near rust-clippy's master, -and use the `setup-toolchain.sh` script to configure the appropriate toolchain -for the Clippy directory. +See the [Basics](basics.md#get-the-code) documentation. ## Getting Started @@ -113,7 +110,7 @@ For cargo lints, the process of testing differs in that we are interested in the `Cargo.toml` manifest file. We also need a minimal crate associated with that manifest. -If our new lint is named e.g. `foo_categories`, after running `cargo dev new_lint` +If our new lint is named e.g. `foo_categories`, after running `cargo dev new_lint` we will find by default two new crates, each with its manifest file: * `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the new lint to raise an error. diff --git a/doc/basics.md b/doc/basics.md new file mode 100644 index 00000000000..c1fd2fbcd1b --- /dev/null +++ b/doc/basics.md @@ -0,0 +1,106 @@ +# Basics for hacking on Clippy + +This document explains the basics for hacking on Clippy. Besides others, this +includes how to set-up the development environment, how to build and how to test +Clippy. For a more in depth description on the codebase take a look at [Adding +Lints] or [Common Tools]. + +[Adding Lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md +[Common Tools]: https://github.com/rust-lang/rust-clippy/blob/master/doc/common_tools_writing_lints.md + +- [Basics for hacking on Clippy](#basics-for-hacking-on-clippy) + - [Get the code](#get-the-code) + - [Setup](#setup) + - [Building and Testing](#building-and-testing) + - [`cargo dev`](#cargo-dev) + +## Get the Code + +First, make sure you have checked out the latest version of Clippy. If this is +your first time working on Clippy, create a fork of the repository and clone it +afterwards with the following command: + +```bash +git clone git@github.com:<your-username>/rust-clippy +``` + +If you've already cloned Clippy in the past, update it to the latest version: + +```bash +# upstream has to be the remote of the rust-lang/rust-clippy repo +git fetch upstream +# make sure that you are on the master branch +git checkout master +# rebase your master branch on the upstream master +git rebase upstream/master +# push to the master branch of your fork +git push +``` + +## Setup + +Next we need to setup the toolchain to compile Clippy. Since Clippy heavily +relies on compiler internals it is build with the latest rustc master. To get +this toolchain, you can just use the `setup-toolchain.sh` script or use +`rustup-toolchain-install-master`: + +```bash +sh setup-toolchain.sh +# OR +cargo install rustup-toolchain-install-master +rustup-toolchain-install-master -f -n master -c rustc-dev -c llvm-tools +rustup override set master +``` + +## Building and Testing + +Once the `master` toolchain is installed, you can build and test Clippy like +every other Rust project: + +```bash +cargo build # builds Clippy +cargo test # tests Clippy +``` + +Since Clippys test suite is pretty big, there are some commands that only run a +subset of Clippys tests: + +```bash +# only run UI tests +cargo uitest +# only run UI tests starting with `test_` +TESTNAME="test_" cargo uitest +# only run dogfood tests +cargo test --test dogfood +``` + +If the output of a UI test differs from the expected output, you can update the +reference file with: + +```bash +sh tests/ui/update-all-references.sh +``` + +For example, this is necessary, if you fix a typo in an error message of a lint +or if you modify a test file to add a test case. + +_Note:_ This command may update more files than you intended. In that case only +commit the files you wanted to update. + +## `cargo dev` + +Clippy has some dev tools to make working on Clippy more convenient. These tools +can be accessed through the `cargo dev` command. Available tools are listed +below. To get more information about these commands, just call them with +`--help`. + +```bash +# formats the whole Clippy codebase and all tests +cargo dev fmt +# register or update lint names/groups/... +cargo dev update_lints +# create a new lint and register it +cargo dev new_lint +# (experimental) Setup Clippy to work with rust-analyzer +cargo dev ra-setup +``` From bdc01c882e5f212c9a8a0384aef1b670122a4337 Mon Sep 17 00:00:00 2001 From: Philipp Krones <hello@philkrones.com> Date: Wed, 22 Jul 2020 18:07:33 +0200 Subject: [PATCH 311/526] Update Usage section of README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 222b81023a7..a2984d73641 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,8 @@ Table of contents: ## Usage -Since this is a tool for helping the developer of a library or application -write better code, it is recommended not to include Clippy as a hard dependency. -Options include using it as an optional dependency, as a cargo subcommand, or -as an included feature during build. These options are detailed below. +Below are instructions on how to use Clippy as a subcommand, compiled from source +or in Travis CI. ### As a cargo subcommand (`cargo clippy`) From 17903f6d7107c6d31ee15f4c46af29d1f4aa363f Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Fri, 24 Jul 2020 17:48:43 +0200 Subject: [PATCH 312/526] Mention lint naming guidelines earlier --- doc/adding_lints.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/adding_lints.md b/doc/adding_lints.md index d5f4f5d5659..168092f7329 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -35,12 +35,14 @@ There is a bit of boilerplate code that needs to be set up when creating a new lint. Fortunately, you can use the clippy dev tools to handle this for you. We are naming our new lint `foo_functions` (lints are generally written in snake case), and we don't need type information so it will have an early pass type -(more on this later on). To get started on this lint you can run -`cargo dev new_lint --name=foo_functions --pass=early --category=pedantic` -(category will default to nursery if not provided). This command will create -two files: `tests/ui/foo_functions.rs` and `clippy_lints/src/foo_functions.rs`, -as well as run `cargo dev update_lints` to register the new lint. For cargo lints, -two project hierarchies (fail/pass) will be created by default under `tests/ui-cargo`. +(more on this later on). If you're not sure if the name you chose fits the lint, +take a look at our [lint naming guidelines][lint_naming]. To get started on this +lint you can run `cargo dev new_lint --name=foo_functions --pass=early +--category=pedantic` (category will default to nursery if not provided). This +command will create two files: `tests/ui/foo_functions.rs` and +`clippy_lints/src/foo_functions.rs`, as well as run `cargo dev update_lints` to +register the new lint. For cargo lints, two project hierarchies (fail/pass) will +be created by default under `tests/ui-cargo`. Next, we'll open up these files and add our lint! From 3a4cc9f7f085e73fbfe57e8c896b90a5fe61c4f4 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Fri, 24 Jul 2020 23:17:52 +0200 Subject: [PATCH 313/526] Address review comments --- doc/basics.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/basics.md b/doc/basics.md index c1fd2fbcd1b..5c07d9b98a5 100644 --- a/doc/basics.md +++ b/doc/basics.md @@ -48,6 +48,7 @@ this toolchain, you can just use the `setup-toolchain.sh` script or use sh setup-toolchain.sh # OR cargo install rustup-toolchain-install-master +# For better IDE integration also add `-c rustfmt -c rust-src` (optional) rustup-toolchain-install-master -f -n master -c rustc-dev -c llvm-tools rustup override set master ``` @@ -62,8 +63,8 @@ cargo build # builds Clippy cargo test # tests Clippy ``` -Since Clippys test suite is pretty big, there are some commands that only run a -subset of Clippys tests: +Since Clippy's test suite is pretty big, there are some commands that only run a +subset of Clippy's tests: ```bash # only run UI tests @@ -74,7 +75,7 @@ TESTNAME="test_" cargo uitest cargo test --test dogfood ``` -If the output of a UI test differs from the expected output, you can update the +If the output of a [UI test] differs from the expected output, you can update the reference file with: ```bash @@ -87,6 +88,8 @@ or if you modify a test file to add a test case. _Note:_ This command may update more files than you intended. In that case only commit the files you wanted to update. +[UI test]: https://rustc-dev-guide.rust-lang.org/tests/adding.html#guide-to-the-ui-tests + ## `cargo dev` Clippy has some dev tools to make working on Clippy more convenient. These tools From b375f1dd20bf07175ec06d13e1e9dc8b20287cd3 Mon Sep 17 00:00:00 2001 From: Dmitry Murzin <diralik@yandex.ru> Date: Sat, 25 Jul 2020 17:09:44 +0300 Subject: [PATCH 314/526] Add suggestion for `iter_skip_next` lint --- clippy_lints/src/methods/mod.rs | 24 ++++++++++++++---------- tests/ui/iter_skip_next.fixed | 22 ++++++++++++++++++++++ tests/ui/iter_skip_next.rs | 8 ++++---- tests/ui/iter_skip_next.stderr | 23 ++++++++--------------- 4 files changed, 48 insertions(+), 29 deletions(-) create mode 100644 tests/ui/iter_skip_next.fixed diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 97cc58023f5..56686f6d24f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1408,7 +1408,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { ["nth", "iter_mut"] => lint_iter_nth(cx, expr, &arg_lists, true), ["nth", ..] => lint_iter_nth_zero(cx, expr, arg_lists[0]), ["step_by", ..] => lint_step_by(cx, expr, arg_lists[0]), - ["next", "skip"] => lint_iter_skip_next(cx, expr), + ["next", "skip"] => lint_iter_skip_next(cx, expr, arg_lists[1]), ["collect", "cloned"] => lint_iter_cloned_collect(cx, expr, arg_lists[1]), ["as_ref"] => lint_asref(cx, expr, "as_ref", arg_lists[0]), ["as_mut"] => lint_asref(cx, expr, "as_mut", arg_lists[0]), @@ -2436,17 +2436,21 @@ fn lint_get_unwrap<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args: ); } -fn lint_iter_skip_next(cx: &LateContext<'_>, expr: &hir::Expr<'_>) { +fn lint_iter_skip_next(cx: &LateContext<'_>, expr: &hir::Expr<'_>, skip_args: &[hir::Expr<'_>]) { // lint if caller of skip is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - span_lint_and_help( - cx, - ITER_SKIP_NEXT, - expr.span, - "called `skip(x).next()` on an iterator", - None, - "this is more succinctly expressed by calling `nth(x)`", - ); + if let [caller, n] = skip_args { + let hint = format!(".nth({})", snippet(cx, n.span, "..")); + span_lint_and_sugg( + cx, + ITER_SKIP_NEXT, + expr.span.trim_start(caller.span).unwrap(), + "called `skip(x).next()` on an iterator", + "use `nth` instead", + hint, + Applicability::MachineApplicable, + ); + } } } diff --git a/tests/ui/iter_skip_next.fixed b/tests/ui/iter_skip_next.fixed new file mode 100644 index 00000000000..928b6acb951 --- /dev/null +++ b/tests/ui/iter_skip_next.fixed @@ -0,0 +1,22 @@ +// run-rustfix +// aux-build:option_helpers.rs + +#![warn(clippy::iter_skip_next)] +#![allow(clippy::blacklisted_name)] +#![allow(clippy::iter_nth)] + +extern crate option_helpers; + +use option_helpers::IteratorFalsePositives; + +/// Checks implementation of `ITER_SKIP_NEXT` lint +fn main() { + let some_vec = vec![0, 1, 2, 3]; + let _ = some_vec.iter().nth(42); + let _ = some_vec.iter().cycle().nth(42); + let _ = (1..10).nth(10); + let _ = &some_vec[..].iter().nth(3); + let foo = IteratorFalsePositives { foo: 0 }; + let _ = foo.skip(42).next(); + let _ = foo.filter().skip(42).next(); +} diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs index a65ca3bbb13..7075e2598eb 100644 --- a/tests/ui/iter_skip_next.rs +++ b/tests/ui/iter_skip_next.rs @@ -1,15 +1,17 @@ +// run-rustfix // aux-build:option_helpers.rs #![warn(clippy::iter_skip_next)] #![allow(clippy::blacklisted_name)] +#![allow(clippy::iter_nth)] extern crate option_helpers; use option_helpers::IteratorFalsePositives; /// Checks implementation of `ITER_SKIP_NEXT` lint -fn iter_skip_next() { - let mut some_vec = vec![0, 1, 2, 3]; +fn main() { + let some_vec = vec![0, 1, 2, 3]; let _ = some_vec.iter().skip(42).next(); let _ = some_vec.iter().cycle().skip(42).next(); let _ = (1..10).skip(10).next(); @@ -18,5 +20,3 @@ fn iter_skip_next() { let _ = foo.skip(42).next(); let _ = foo.filter().skip(42).next(); } - -fn main() {} diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr index 5709f335529..feedc2f288a 100644 --- a/tests/ui/iter_skip_next.stderr +++ b/tests/ui/iter_skip_next.stderr @@ -1,35 +1,28 @@ error: called `skip(x).next()` on an iterator - --> $DIR/iter_skip_next.rs:13:13 + --> $DIR/iter_skip_next.rs:15:28 | LL | let _ = some_vec.iter().skip(42).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)` | = note: `-D clippy::iter-skip-next` implied by `-D warnings` - = help: this is more succinctly expressed by calling `nth(x)` error: called `skip(x).next()` on an iterator - --> $DIR/iter_skip_next.rs:14:13 + --> $DIR/iter_skip_next.rs:16:36 | LL | let _ = some_vec.iter().cycle().skip(42).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: this is more succinctly expressed by calling `nth(x)` + | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)` error: called `skip(x).next()` on an iterator - --> $DIR/iter_skip_next.rs:15:13 + --> $DIR/iter_skip_next.rs:17:20 | LL | let _ = (1..10).skip(10).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: this is more succinctly expressed by calling `nth(x)` + | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(10)` error: called `skip(x).next()` on an iterator - --> $DIR/iter_skip_next.rs:16:14 + --> $DIR/iter_skip_next.rs:18:33 | LL | let _ = &some_vec[..].iter().skip(3).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: this is more succinctly expressed by calling `nth(x)` + | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(3)` error: aborting due to 4 previous errors From c81bbd05b95ae03da9af4e7e25e3784edd039465 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Sat, 25 Jul 2020 23:58:22 +0900 Subject: [PATCH 315/526] Fix FP `useless_conversion` Fix #5833. --- clippy_lints/src/useless_conversion.rs | 11 +++++++++-- tests/ui/useless_conversion.fixed | 9 +++++++++ tests/ui/useless_conversion.rs | 9 +++++++++ tests/ui/useless_conversion.stderr | 14 +++++++------- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index a48ad3185e9..1bf37632e32 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -1,6 +1,6 @@ use crate::utils::{ - is_type_diagnostic_item, match_def_path, match_trait_method, paths, snippet, snippet_with_macro_callsite, - span_lint_and_help, span_lint_and_sugg, + get_parent_expr, is_type_diagnostic_item, match_def_path, match_trait_method, paths, snippet, + snippet_with_macro_callsite, span_lint_and_help, span_lint_and_sugg, }; use if_chain::if_chain; use rustc_errors::Applicability; @@ -79,6 +79,13 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } } if match_trait_method(cx, e, &paths::INTO_ITERATOR) && &*name.ident.as_str() == "into_iter" { + if let Some(parent_expr) = get_parent_expr(cx, e) { + if let ExprKind::MethodCall(ref parent_name, ..) = parent_expr.kind { + if &*parent_name.ident.as_str() != "into_iter" { + return; + } + } + } let a = cx.typeck_results().expr_ty(e); let b = cx.typeck_results().expr_ty(&args[0]); if TyS::same_type(a, b) { diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed index fdd4bc581f3..813cdaecaa9 100644 --- a/tests/ui/useless_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -32,11 +32,20 @@ fn test_issue_3913() -> Result<(), std::io::Error> { Ok(()) } +fn test_issue_5833() -> Result<(), ()> { + let text = "foo\r\nbar\n\nbaz\n"; + let lines = text.lines(); + if Some("ok") == lines.into_iter().next() {} + + Ok(()) +} + fn main() { test_generic(10i32); test_generic2::<i32, i32>(10i32); test_questionmark().unwrap(); test_issue_3913().unwrap(); + test_issue_5833().unwrap(); let _: String = "foo".into(); let _: String = From::from("foo"); diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs index 4cae745e7c0..540fea23b36 100644 --- a/tests/ui/useless_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -32,11 +32,20 @@ fn test_issue_3913() -> Result<(), std::io::Error> { Ok(()) } +fn test_issue_5833() -> Result<(), ()> { + let text = "foo\r\nbar\n\nbaz\n"; + let lines = text.lines(); + if Some("ok") == lines.into_iter().next() {} + + Ok(()) +} + fn main() { test_generic(10i32); test_generic2::<i32, i32>(10i32); test_questionmark().unwrap(); test_issue_3913().unwrap(); + test_issue_5833().unwrap(); let _: String = "foo".into(); let _: String = From::from("foo"); diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index 84ec5370278..b958b035452 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -23,43 +23,43 @@ LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: useless conversion to the same type - --> $DIR/useless_conversion.rs:51:21 + --> $DIR/useless_conversion.rs:60:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: useless conversion to the same type - --> $DIR/useless_conversion.rs:52:21 + --> $DIR/useless_conversion.rs:61:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: useless conversion to the same type - --> $DIR/useless_conversion.rs:53:13 + --> $DIR/useless_conversion.rs:62:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: useless conversion to the same type - --> $DIR/useless_conversion.rs:54:13 + --> $DIR/useless_conversion.rs:63:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: useless conversion to the same type - --> $DIR/useless_conversion.rs:55:13 + --> $DIR/useless_conversion.rs:64:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: useless conversion to the same type - --> $DIR/useless_conversion.rs:56:13 + --> $DIR/useless_conversion.rs:65:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: useless conversion to the same type - --> $DIR/useless_conversion.rs:57:21 + --> $DIR/useless_conversion.rs:66:21 | LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` From 5a644964fc05752a1283dab238b81de7583f7d03 Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Sun, 26 Jul 2020 20:40:57 -0600 Subject: [PATCH 316/526] run cargo dev new_lint specifically: cargo dev new_lint --name derive_ord_xor_partial_ord --category correctness --pass late --- CHANGELOG.md | 1 + .../src/derive_ord_xor_partial_ord.rs | 28 +++++++++++++++++++ clippy_lints/src/lib.rs | 4 +++ src/lintlist/mod.rs | 7 +++++ tests/ui/derive_ord_xor_partial_ord.rs | 5 ++++ 5 files changed, 45 insertions(+) create mode 100644 clippy_lints/src/derive_ord_xor_partial_ord.rs create mode 100644 tests/ui/derive_ord_xor_partial_ord.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 776b04295f9..a1780725044 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1454,6 +1454,7 @@ Released 2018-09-13 [`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver [`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof [`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq +[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown [`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons diff --git a/clippy_lints/src/derive_ord_xor_partial_ord.rs b/clippy_lints/src/derive_ord_xor_partial_ord.rs new file mode 100644 index 00000000000..7913aab6f24 --- /dev/null +++ b/clippy_lints/src/derive_ord_xor_partial_ord.rs @@ -0,0 +1,28 @@ +use rustc_lint::{LateLintPass, LateContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_hir::*; + +declare_clippy_lint! { + /// **What it does:** + /// + /// **Why is this bad?** + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + pub DERIVE_ORD_XOR_PARTIAL_ORD, + correctness, + "default lint description" +} + +declare_lint_pass!(DeriveOrdXorPartialOrd => [DERIVE_ORD_XOR_PARTIAL_ORD]); + +impl LateLintPass<'_, '_> for DeriveOrdXorPartialOrd {} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f371942dbee..6d6dd06cc21 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -173,6 +173,7 @@ mod dbg_macro; mod default_trait_access; mod dereference; mod derive; +mod derive_ord_xor_partial_ord; mod doc; mod double_comparison; mod double_parens; @@ -515,6 +516,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &derive::DERIVE_HASH_XOR_EQ, &derive::EXPL_IMPL_CLONE_ON_COPY, &derive::UNSAFE_DERIVE_DESERIALIZE, + &derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD, &doc::DOC_MARKDOWN, &doc::MISSING_ERRORS_DOC, &doc::MISSING_SAFETY_DOC, @@ -1230,6 +1232,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), + LintId::of(&derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD), LintId::of(&doc::MISSING_SAFETY_DOC), LintId::of(&doc::NEEDLESS_DOCTEST_MAIN), LintId::of(&double_comparison::DOUBLE_COMPARISONS), @@ -1648,6 +1651,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), + LintId::of(&derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD), LintId::of(&drop_bounds::DROP_BOUNDS), LintId::of(&drop_forget_ref::DROP_COPY), LintId::of(&drop_forget_ref::DROP_REF), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 1879aae77fb..00d3df8f94f 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -360,6 +360,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "derive", }, + Lint { + name: "derive_ord_xor_partial_ord", + group: "correctness", + desc: "default lint description", + deprecation: None, + module: "derive_ord_xor_partial_ord", + }, Lint { name: "diverging_sub_expression", group: "complexity", diff --git a/tests/ui/derive_ord_xor_partial_ord.rs b/tests/ui/derive_ord_xor_partial_ord.rs new file mode 100644 index 00000000000..63687e7b3db --- /dev/null +++ b/tests/ui/derive_ord_xor_partial_ord.rs @@ -0,0 +1,5 @@ +#![warn(clippy::derive_ord_xor_partial_ord)] + +fn main() { + // test code goes here +} From fc20ee63a105c0df78113126e8749f5958d7dc47 Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Sun, 26 Jul 2020 20:54:04 -0600 Subject: [PATCH 317/526] move derive_ord_xor_partial_ord into derive mod so we can reuse derive_hash_xor_partial_eq code later --- clippy_lints/src/derive.rs | 23 ++++++++++++++- .../src/derive_ord_xor_partial_ord.rs | 28 ------------------- clippy_lints/src/lib.rs | 7 ++--- src/lintlist/mod.rs | 2 +- 4 files changed, 26 insertions(+), 34 deletions(-) delete mode 100644 clippy_lints/src/derive_ord_xor_partial_ord.rs diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 59c62f1ae94..627475ee1d9 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -43,6 +43,27 @@ declare_clippy_lint! { "deriving `Hash` but implementing `PartialEq` explicitly" } +declare_clippy_lint! { + /// **What it does:** + /// + /// **Why is this bad?** + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + pub DERIVE_ORD_XOR_PARTIAL_ORD, + correctness, + "default lint description" +} + declare_clippy_lint! { /// **What it does:** Checks for explicit `Clone` implementations for `Copy` /// types. @@ -103,7 +124,7 @@ declare_clippy_lint! { "deriving `serde::Deserialize` on a type that has methods using `unsafe`" } -declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ, UNSAFE_DERIVE_DESERIALIZE]); +declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ, DERIVE_ORD_XOR_PARTIAL_ORD, UNSAFE_DERIVE_DESERIALIZE]); impl<'tcx> LateLintPass<'tcx> for Derive { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { diff --git a/clippy_lints/src/derive_ord_xor_partial_ord.rs b/clippy_lints/src/derive_ord_xor_partial_ord.rs deleted file mode 100644 index 7913aab6f24..00000000000 --- a/clippy_lints/src/derive_ord_xor_partial_ord.rs +++ /dev/null @@ -1,28 +0,0 @@ -use rustc_lint::{LateLintPass, LateContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_hir::*; - -declare_clippy_lint! { - /// **What it does:** - /// - /// **Why is this bad?** - /// - /// **Known problems:** None. - /// - /// **Example:** - /// - /// ```rust - /// // example code where clippy issues a warning - /// ``` - /// Use instead: - /// ```rust - /// // example code which does not raise clippy warning - /// ``` - pub DERIVE_ORD_XOR_PARTIAL_ORD, - correctness, - "default lint description" -} - -declare_lint_pass!(DeriveOrdXorPartialOrd => [DERIVE_ORD_XOR_PARTIAL_ORD]); - -impl LateLintPass<'_, '_> for DeriveOrdXorPartialOrd {} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6d6dd06cc21..996aad31d3e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -173,7 +173,6 @@ mod dbg_macro; mod default_trait_access; mod dereference; mod derive; -mod derive_ord_xor_partial_ord; mod doc; mod double_comparison; mod double_parens; @@ -514,9 +513,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &default_trait_access::DEFAULT_TRAIT_ACCESS, &dereference::EXPLICIT_DEREF_METHODS, &derive::DERIVE_HASH_XOR_EQ, + &derive::DERIVE_ORD_XOR_PARTIAL_ORD, &derive::EXPL_IMPL_CLONE_ON_COPY, &derive::UNSAFE_DERIVE_DESERIALIZE, - &derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD, &doc::DOC_MARKDOWN, &doc::MISSING_ERRORS_DOC, &doc::MISSING_SAFETY_DOC, @@ -1232,7 +1231,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), - LintId::of(&derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD), + LintId::of(&derive::DERIVE_ORD_XOR_PARTIAL_ORD), LintId::of(&doc::MISSING_SAFETY_DOC), LintId::of(&doc::NEEDLESS_DOCTEST_MAIN), LintId::of(&double_comparison::DOUBLE_COMPARISONS), @@ -1651,7 +1650,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), - LintId::of(&derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD), + LintId::of(&derive::DERIVE_ORD_XOR_PARTIAL_ORD), LintId::of(&drop_bounds::DROP_BOUNDS), LintId::of(&drop_forget_ref::DROP_COPY), LintId::of(&drop_forget_ref::DROP_REF), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 00d3df8f94f..011504710e1 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -365,7 +365,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ group: "correctness", desc: "default lint description", deprecation: None, - module: "derive_ord_xor_partial_ord", + module: "derive", }, Lint { name: "diverging_sub_expression", From 0722991b62fd6e4d7d7a51425274f3288bcc96bc Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Sun, 26 Jul 2020 21:36:50 -0600 Subject: [PATCH 318/526] add test for derive_ord_xor_partial_ord based on test for derive_hash_xor_partial_eq --- tests/ui/derive_ord_xor_partial_ord.rs | 67 +++++++++++++++++++++- tests/ui/derive_ord_xor_partial_ord.stderr | 1 + 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 tests/ui/derive_ord_xor_partial_ord.stderr diff --git a/tests/ui/derive_ord_xor_partial_ord.rs b/tests/ui/derive_ord_xor_partial_ord.rs index 63687e7b3db..15f66b7a9c5 100644 --- a/tests/ui/derive_ord_xor_partial_ord.rs +++ b/tests/ui/derive_ord_xor_partial_ord.rs @@ -1,5 +1,68 @@ #![warn(clippy::derive_ord_xor_partial_ord)] -fn main() { - // test code goes here +use std::cmp::Ordering; + +#[derive(PartialOrd, Ord, PartialEq, Eq)] +struct DeriveBoth; + +impl PartialEq<u64> for DeriveBoth { + fn eq(&self, _: &u64) -> bool { + true + } } + +impl PartialOrd<u64> for DeriveBoth { + fn partial_cmp(&self, _: &u64) -> Option<Ordering> { + Some(Ordering::Equal) + } +} + +#[derive(Ord, PartialEq, Eq)] +struct DeriveOrd; + +impl PartialOrd for DeriveOrd { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(other.cmp(self)) + } +} + +#[derive(Ord, PartialEq, Eq)] +struct DeriveOrdWithExplicitTypeVariable; + +impl PartialOrd<DeriveOrdWithExplicitTypeVariable> for DeriveOrdWithExplicitTypeVariable { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(other.cmp(self)) + } +} + +#[derive(PartialOrd, PartialEq, Eq)] +struct DerivePartialOrd; + +impl std::cmp::Ord for DerivePartialOrd { + fn cmp(&self, other: &Self) -> Ordering { + Ordering::Less + } +} + +#[derive(PartialOrd, PartialEq, Eq)] +struct ImplUserOrd; + +trait Ord {} + +// We don't want to lint on user-defined traits called `Ord` +impl Ord for ImplUserOrd {} + +mod use_ord { + use std::cmp::{Ord, Ordering}; + + #[derive(PartialOrd, PartialEq, Eq)] + struct DerivePartialOrdInUseOrd; + + impl Ord for DerivePartialOrdInUseOrd { + fn cmp(&self, other: &Self) -> Ordering { + Ordering::Less + } + } +} + +fn main() {} \ No newline at end of file diff --git a/tests/ui/derive_ord_xor_partial_ord.stderr b/tests/ui/derive_ord_xor_partial_ord.stderr new file mode 100644 index 00000000000..30404ce4c54 --- /dev/null +++ b/tests/ui/derive_ord_xor_partial_ord.stderr @@ -0,0 +1 @@ +TODO \ No newline at end of file From 068acbd27b19a4a7be3a9d00954ecfad8a0e6553 Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Sun, 26 Jul 2020 22:04:46 -0600 Subject: [PATCH 319/526] initial implementation based on code for `derive_hash_xor_partial_eq` which is showing one error when there should be four --- clippy_lints/src/derive.rs | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 627475ee1d9..4f69c2d7af7 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -137,6 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive { let is_automatically_derived = is_automatically_derived(&*item.attrs); check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); + check_ord_pord(cx, item.span, trait_ref, ty, is_automatically_derived); if is_automatically_derived { check_unsafe_derive_deserialize(cx, item, trait_ref, ty); @@ -201,6 +202,60 @@ fn check_hash_peq<'tcx>( } } +/// Implementation of the `DERIVE_ORD_XOR_PARTIAL_ORD` lint. +fn check_ord_pord<'tcx>( + cx: &LateContext<'tcx>, + span: Span, + trait_ref: &TraitRef<'_>, + ty: Ty<'tcx>, + ord_is_automatically_derived: bool, +) { + if_chain! { + if match_path(&trait_ref.path, &paths::ORD); + if let Some(pord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); + if let Some(def_id) = &trait_ref.trait_def_id(); + if !def_id.is_local(); + then { + // Look for the PartialOrd implementations for `ty` + cx.tcx.for_each_relevant_impl(pord_trait_def_id, ty, |impl_id| { + let pord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); + + if pord_is_automatically_derived == ord_is_automatically_derived { + return; + } + + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + + // Only care about `impl PartialOrd<Foo> for Foo` + // For `impl PartialOrd<B> for A, input_types is [A, B] + if trait_ref.substs.type_at(1) == ty { + let mess = if pord_is_automatically_derived { + "you are implementing `Ord` explicitly but have derived `PartialOrd`" + } else { + "you are deriving `Ord` but have implemented `PartialOrd` explicitly" + }; + + span_lint_and_then( + cx, + DERIVE_ORD_XOR_PARTIAL_ORD, + span, + mess, + |diag| { + if let Some(local_def_id) = impl_id.as_local() { + let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id); + diag.span_note( + cx.tcx.hir().span(hir_id), + "`PartialOrd` implemented here" + ); + } + } + ); + } + }); + } + } +} + /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) { if match_path(&trait_ref.path, &paths::CLONE_TRAIT) { From a8d6eda93049f0077c1515bec35fe0359ea43f96 Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Sun, 26 Jul 2020 23:04:04 -0600 Subject: [PATCH 320/526] use get_trait_def_id to check for Ord trait --- clippy_lints/src/derive.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 4f69c2d7af7..04395621e9e 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,6 +1,6 @@ use crate::utils::paths; use crate::utils::{ - is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, + get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, }; use if_chain::if_chain; use rustc_hir::def_id::DefId; @@ -211,9 +211,10 @@ fn check_ord_pord<'tcx>( ord_is_automatically_derived: bool, ) { if_chain! { - if match_path(&trait_ref.path, &paths::ORD); + if let Some(ord_trait_def_id) = get_trait_def_id(cx, &paths::ORD); if let Some(pord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); if let Some(def_id) = &trait_ref.trait_def_id(); + if *def_id == ord_trait_def_id; if !def_id.is_local(); then { // Look for the PartialOrd implementations for `ty` From 6c3e4591b87e6c690b31166867484675dcb1e48c Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Sun, 26 Jul 2020 23:04:25 -0600 Subject: [PATCH 321/526] update reference since we see the expected four errors --- tests/ui/derive_ord_xor_partial_ord.stderr | 72 +++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/tests/ui/derive_ord_xor_partial_ord.stderr b/tests/ui/derive_ord_xor_partial_ord.stderr index 30404ce4c54..66bc4d42ce8 100644 --- a/tests/ui/derive_ord_xor_partial_ord.stderr +++ b/tests/ui/derive_ord_xor_partial_ord.stderr @@ -1 +1,71 @@ -TODO \ No newline at end of file +error: you are deriving `Ord` but have implemented `PartialOrd` explicitly + --> $DIR/derive_ord_xor_partial_ord.rs:20:10 + | +LL | #[derive(Ord, PartialEq, Eq)] + | ^^^ + | + = note: `-D clippy::derive-ord-xor-partial-ord` implied by `-D warnings` +note: `PartialOrd` implemented here + --> $DIR/derive_ord_xor_partial_ord.rs:23:1 + | +LL | / impl PartialOrd for DeriveOrd { +LL | | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { +LL | | Some(other.cmp(self)) +LL | | } +LL | | } + | |_^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: you are deriving `Ord` but have implemented `PartialOrd` explicitly + --> $DIR/derive_ord_xor_partial_ord.rs:29:10 + | +LL | #[derive(Ord, PartialEq, Eq)] + | ^^^ + | +note: `PartialOrd` implemented here + --> $DIR/derive_ord_xor_partial_ord.rs:32:1 + | +LL | / impl PartialOrd<DeriveOrdWithExplicitTypeVariable> for DeriveOrdWithExplicitTypeVariable { +LL | | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { +LL | | Some(other.cmp(self)) +LL | | } +LL | | } + | |_^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: you are implementing `Ord` explicitly but have derived `PartialOrd` + --> $DIR/derive_ord_xor_partial_ord.rs:41:1 + | +LL | / impl std::cmp::Ord for DerivePartialOrd { +LL | | fn cmp(&self, other: &Self) -> Ordering { +LL | | Ordering::Less +LL | | } +LL | | } + | |_^ + | +note: `PartialOrd` implemented here + --> $DIR/derive_ord_xor_partial_ord.rs:38:10 + | +LL | #[derive(PartialOrd, PartialEq, Eq)] + | ^^^^^^^^^^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: you are implementing `Ord` explicitly but have derived `PartialOrd` + --> $DIR/derive_ord_xor_partial_ord.rs:61:5 + | +LL | / impl Ord for DerivePartialOrdInUseOrd { +LL | | fn cmp(&self, other: &Self) -> Ordering { +LL | | Ordering::Less +LL | | } +LL | | } + | |_____^ + | +note: `PartialOrd` implemented here + --> $DIR/derive_ord_xor_partial_ord.rs:58:14 + | +LL | #[derive(PartialOrd, PartialEq, Eq)] + | ^^^^^^^^^^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + From 7dc974815ec8736f026dc10a070137e0d4601d52 Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Sun, 26 Jul 2020 23:06:36 -0600 Subject: [PATCH 322/526] remove is_local check since getting the def_id directly makes it unnecessary --- clippy_lints/src/derive.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 04395621e9e..ab001f7773e 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -215,7 +215,6 @@ fn check_ord_pord<'tcx>( if let Some(pord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); if let Some(def_id) = &trait_ref.trait_def_id(); if *def_id == ord_trait_def_id; - if !def_id.is_local(); then { // Look for the PartialOrd implementations for `ty` cx.tcx.for_each_relevant_impl(pord_trait_def_id, ty, |impl_id| { From 431924ccf69bc4d4f0597f12749e8b1bcb285710 Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Sun, 26 Jul 2020 23:15:36 -0600 Subject: [PATCH 323/526] add description for derive_ord_xor_partial_ord --- clippy_lints/src/derive.rs | 42 ++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index ab001f7773e..84566252abd 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -44,20 +44,50 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** + /// **What it does:** Checks for deriving `Ord` but implementing `PartialOrd` + /// explicitly or vice versa. /// - /// **Why is this bad?** + /// **Why is this bad?** The implementation of these traits must agree (for + /// example for use with `sort`) so it’s probably a bad idea to use a + /// default-generated `Ord` implementation with an explicitly defined + /// `PartialOrd`. In particular, the following must hold for any type + /// implementing `Ord`: + /// + /// ```text + /// k1.cmp(&k2) == k1.partial_cmp(&k2).unwrap() + /// ``` /// /// **Known problems:** None. /// /// **Example:** /// - /// ```rust - /// // example code where clippy issues a warning + /// ```rust,ignore + /// #[derive(Ord, PartialEq, Eq)] + /// struct Foo; + /// + /// impl PartialOrd for Foo { + /// ... + /// } /// ``` /// Use instead: - /// ```rust - /// // example code which does not raise clippy warning + /// ```rust,ignore + /// #[derive(PartialEq, Eq)] + /// struct Foo; + /// + /// impl PartialOrd for Foo { + /// fn partial_cmp(&self, other: &Foo) -> Option<Ordering> { + /// Some(self.cmp(other)) + /// } + /// } + /// + /// impl Ord for Foo { + /// ... + /// } + /// ``` + /// or, if you don't need a custom ordering: + /// ```rust,ignore + /// #[derive(Ord, PartialOrd, PartialEq, Eq)] + /// struct Foo; /// ``` pub DERIVE_ORD_XOR_PARTIAL_ORD, correctness, From 668b7474b47791c8c9af10130356b681b3bf3a84 Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Sun, 26 Jul 2020 23:30:00 -0600 Subject: [PATCH 324/526] run cargo dev fmt and fix overly long line --- clippy_lints/src/derive.rs | 10 ++++++++-- tests/ui/derive_ord_xor_partial_ord.rs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 84566252abd..16a6f0c20e1 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,6 +1,7 @@ use crate::utils::paths; use crate::utils::{ - get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, + get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, + span_lint_and_then, }; use if_chain::if_chain; use rustc_hir::def_id::DefId; @@ -154,7 +155,12 @@ declare_clippy_lint! { "deriving `serde::Deserialize` on a type that has methods using `unsafe`" } -declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ, DERIVE_ORD_XOR_PARTIAL_ORD, UNSAFE_DERIVE_DESERIALIZE]); +declare_lint_pass!(Derive => [ + EXPL_IMPL_CLONE_ON_COPY, + DERIVE_HASH_XOR_EQ, + DERIVE_ORD_XOR_PARTIAL_ORD, + UNSAFE_DERIVE_DESERIALIZE +]); impl<'tcx> LateLintPass<'tcx> for Derive { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { diff --git a/tests/ui/derive_ord_xor_partial_ord.rs b/tests/ui/derive_ord_xor_partial_ord.rs index 15f66b7a9c5..b82dc518a3b 100644 --- a/tests/ui/derive_ord_xor_partial_ord.rs +++ b/tests/ui/derive_ord_xor_partial_ord.rs @@ -65,4 +65,4 @@ mod use_ord { } } -fn main() {} \ No newline at end of file +fn main() {} From ca03f2b650a022d06df6c02c8947a74944815381 Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Mon, 27 Jul 2020 00:21:11 -0600 Subject: [PATCH 325/526] s/pord/partial_ord/ to fix dogfood failure --- clippy_lints/src/derive.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 16a6f0c20e1..820ce85cff2 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -173,7 +173,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive { let is_automatically_derived = is_automatically_derived(&*item.attrs); check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); - check_ord_pord(cx, item.span, trait_ref, ty, is_automatically_derived); + check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived); if is_automatically_derived { check_unsafe_derive_deserialize(cx, item, trait_ref, ty); @@ -239,7 +239,7 @@ fn check_hash_peq<'tcx>( } /// Implementation of the `DERIVE_ORD_XOR_PARTIAL_ORD` lint. -fn check_ord_pord<'tcx>( +fn check_ord_partial_ord<'tcx>( cx: &LateContext<'tcx>, span: Span, trait_ref: &TraitRef<'_>, @@ -248,15 +248,15 @@ fn check_ord_pord<'tcx>( ) { if_chain! { if let Some(ord_trait_def_id) = get_trait_def_id(cx, &paths::ORD); - if let Some(pord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); + if let Some(partial_ord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); if let Some(def_id) = &trait_ref.trait_def_id(); if *def_id == ord_trait_def_id; then { // Look for the PartialOrd implementations for `ty` - cx.tcx.for_each_relevant_impl(pord_trait_def_id, ty, |impl_id| { - let pord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); + cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| { + let partial_ord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); - if pord_is_automatically_derived == ord_is_automatically_derived { + if partial_ord_is_automatically_derived == ord_is_automatically_derived { return; } @@ -265,7 +265,7 @@ fn check_ord_pord<'tcx>( // Only care about `impl PartialOrd<Foo> for Foo` // For `impl PartialOrd<B> for A, input_types is [A, B] if trait_ref.substs.type_at(1) == ty { - let mess = if pord_is_automatically_derived { + let mess = if partial_ord_is_automatically_derived { "you are implementing `Ord` explicitly but have derived `PartialOrd`" } else { "you are deriving `Ord` but have implemented `PartialOrd` explicitly" From 12a6eee045f30785a1eb7572a4cfea3c5cec8a4c Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Mon, 27 Jul 2020 00:22:39 -0600 Subject: [PATCH 326/526] fill in lint description for DERIVE_ORD_XOR_PARTIAL_ORD --- clippy_lints/src/derive.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 820ce85cff2..cdb748de0c0 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,7 +1,6 @@ use crate::utils::paths; use crate::utils::{ - get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, - span_lint_and_then, + get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, }; use if_chain::if_chain; use rustc_hir::def_id::DefId; @@ -92,7 +91,7 @@ declare_clippy_lint! { /// ``` pub DERIVE_ORD_XOR_PARTIAL_ORD, correctness, - "default lint description" + "deriving `Ord` but implementing `PartialOrd` explicitly" } declare_clippy_lint! { From 94b10a6e5ab003a03b6c7b60ffe5a3b366e0529a Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Mon, 27 Jul 2020 00:31:09 -0600 Subject: [PATCH 327/526] run cargo dev update_lints --- clippy_lints/src/derive.rs | 3 ++- src/lintlist/mod.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index cdb748de0c0..08d8100a885 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,6 +1,7 @@ use crate::utils::paths; use crate::utils::{ - get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, + get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, + span_lint_and_then, }; use if_chain::if_chain; use rustc_hir::def_id::DefId; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 011504710e1..119908b3cc4 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -363,7 +363,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ Lint { name: "derive_ord_xor_partial_ord", group: "correctness", - desc: "default lint description", + desc: "deriving `Ord` but implementing `PartialOrd` explicitly", deprecation: None, module: "derive", }, From 3a9ccffed8c5329e3fda67c2e310086ba261e15f Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Mon, 27 Jul 2020 22:27:54 +0900 Subject: [PATCH 328/526] `chmod` 644 `clippy_lints/src/utils/ast_utils.rs` --- clippy_lints/src/utils/ast_utils.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 clippy_lints/src/utils/ast_utils.rs diff --git a/clippy_lints/src/utils/ast_utils.rs b/clippy_lints/src/utils/ast_utils.rs old mode 100755 new mode 100644 From 94c50bc8c913ef58eba0f4f10b682dcf6d6e0991 Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Tue, 28 Jul 2020 16:23:47 +0200 Subject: [PATCH 329/526] Lint duplicate methods of trait bounds Fixes #5777 --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/trait_bounds.rs | 94 ++++++++++++++++++++- src/lintlist/mod.rs | 7 ++ tests/ui/trait_duplication_in_bounds.rs | 31 +++++++ tests/ui/trait_duplication_in_bounds.stderr | 23 +++++ 6 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 tests/ui/trait_duplication_in_bounds.rs create mode 100644 tests/ui/trait_duplication_in_bounds.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 776b04295f9..0ca4d88ed38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1723,6 +1723,7 @@ Released 2018-09-13 [`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments [`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines [`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg +[`trait_duplication_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#trait_duplication_in_bounds [`transmute_bytes_to_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_bytes_to_str [`transmute_float_to_int`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_float_to_int [`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f371942dbee..07ef087c2b0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -786,6 +786,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &tabs_in_doc_comments::TABS_IN_DOC_COMMENTS, &temporary_assignment::TEMPORARY_ASSIGNMENT, &to_digit_is_some::TO_DIGIT_IS_SOME, + &trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS, &trait_bounds::TYPE_REPETITION_IN_BOUNDS, &transmute::CROSSPOINTER_TRANSMUTE, &transmute::TRANSMUTE_BYTES_TO_STR, @@ -1174,6 +1175,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ranges::RANGE_PLUS_ONE), LintId::of(&shadow::SHADOW_UNRELATED), LintId::of(&strings::STRING_ADD_ASSIGN), + LintId::of(&trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS), LintId::of(&trait_bounds::TYPE_REPETITION_IN_BOUNDS), LintId::of(&trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF), LintId::of(&types::CAST_LOSSLESS), diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 0ef70311fb1..6bfdac37180 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -2,9 +2,10 @@ use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_ use if_chain::if_chain; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; -use rustc_hir::{GenericBound, Generics, WherePredicate}; +use rustc_hir::{def::Res, GenericBound, Generics, ParamName, Path, QPath, TyKind, WherePredicate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Span; declare_clippy_lint! { /// **What it does:** This lint warns about unnecessary type repetitions in trait bounds @@ -29,6 +30,35 @@ declare_clippy_lint! { "Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`" } +declare_clippy_lint! { + /// **What it does:** Checks for cases where generics are being used and multiple + /// syntax specifications for trait bounds are used simultaneously. + /// + /// **Why is this bad?** Duplicate bounds makes the code + /// less readable than specifing them only once. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// fn func<T: Clone + Default>(arg: T) where T: Clone + Default {} + /// ``` + /// + /// Could be written as: + /// + /// ```rust + /// fn func<T: Clone + Default>(arg: T) {} + /// ``` + /// or + /// /// + /// ```rust + /// fn func<T>(arg: T) where T: Clone + Default {} + /// ``` + pub TRAIT_DUPLICATION_IN_BOUNDS, + pedantic, + "Check if the same trait bounds are specifed twice during a function declaration" +} + #[derive(Copy, Clone)] pub struct TraitBounds { max_trait_bounds: u64, @@ -41,10 +71,25 @@ impl TraitBounds { } } -impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS]); +impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS, TRAIT_DUPLICATION_IN_BOUNDS]); impl<'tcx> LateLintPass<'tcx> for TraitBounds { fn check_generics(&mut self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) { + self.check_type_repetition(cx, gen); + check_trait_bound_duplication(cx, gen); + } +} + +fn get_trait_res_span_from_bound(bound: &GenericBound<'_>) -> Option<(Res, Span)> { + if let GenericBound::Trait(t, _) = bound { + Some((t.trait_ref.path.res, t.span)) + } else { + None + } +} + +impl TraitBounds { + fn check_type_repetition(self, cx: &LateContext<'_>, gen: &'_ Generics<'_>) { if in_macro(gen.span) { return; } @@ -101,3 +146,48 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { } } } + +fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) { + if in_macro(gen.span) { + return; + } + + let mut map = FxHashMap::default(); + for param in gen.params { + if let ParamName::Plain(ref ident) = param.name { + let res = param + .bounds + .iter() + .filter_map(get_trait_res_span_from_bound) + .collect::<Vec<_>>(); + map.insert(*ident, res); + } + } + + for predicate in gen.where_clause.predicates { + if_chain! { + if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate; + if !in_macro(bound_predicate.span); + if let TyKind::Path(ref path) = bound_predicate.bounded_ty.kind; + if let QPath::Resolved(_, Path { ref segments, .. }) = path; + if let Some(segment) = segments.first(); + if let Some(trait_resolutions_direct) = map.get(&segment.ident); + then { + for (res_where, _) in bound_predicate.bounds.iter().filter_map(get_trait_res_span_from_bound) { + if let Some((_, span_direct)) = trait_resolutions_direct + .iter() + .find(|(res_direct, _)| *res_direct == res_where) { + span_lint_and_help( + cx, + TRAIT_DUPLICATION_IN_BOUNDS, + *span_direct, + "this trait bound is already specified in the where clause", + None, + "consider removing this trait bound", + ); + } + } + } + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 1879aae77fb..9fb3dfc96ec 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2166,6 +2166,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "misc", }, + Lint { + name: "trait_duplication_in_bounds", + group: "pedantic", + desc: "Check if the same trait bounds are specifed twice during a function declaration", + deprecation: None, + module: "trait_bounds", + }, Lint { name: "transmute_bytes_to_str", group: "complexity", diff --git a/tests/ui/trait_duplication_in_bounds.rs b/tests/ui/trait_duplication_in_bounds.rs new file mode 100644 index 00000000000..cb2b0054e35 --- /dev/null +++ b/tests/ui/trait_duplication_in_bounds.rs @@ -0,0 +1,31 @@ +#![deny(clippy::trait_duplication_in_bounds)] + +use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; + +fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z) +where + T: Clone, + T: Default, +{ + unimplemented!(); +} + +fn good_bar<T: Clone + Default>(arg: T) { + unimplemented!(); +} + +fn good_foo<T>(arg: T) +where + T: Clone + Default, +{ + unimplemented!(); +} + +fn good_foobar<T: Default>(arg: T) +where + T: Clone, +{ + unimplemented!(); +} + +fn main() {} diff --git a/tests/ui/trait_duplication_in_bounds.stderr b/tests/ui/trait_duplication_in_bounds.stderr new file mode 100644 index 00000000000..027e1c75204 --- /dev/null +++ b/tests/ui/trait_duplication_in_bounds.stderr @@ -0,0 +1,23 @@ +error: this trait bound is already specified in the where clause + --> $DIR/trait_duplication_in_bounds.rs:5:15 + | +LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z) + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/trait_duplication_in_bounds.rs:1:9 + | +LL | #![deny(clippy::trait_duplication_in_bounds)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: consider removing this trait bound + +error: this trait bound is already specified in the where clause + --> $DIR/trait_duplication_in_bounds.rs:5:23 + | +LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z) + | ^^^^^^^ + | + = help: consider removing this trait bound + +error: aborting due to 2 previous errors + From 2b7fde6a4b18ee837342f5b50a4c4941e919177f Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Wed, 29 Jul 2020 16:10:15 +0200 Subject: [PATCH 330/526] typo fix --- clippy_lints/src/trait_bounds.rs | 2 +- src/lintlist/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 6bfdac37180..10811374875 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -56,7 +56,7 @@ declare_clippy_lint! { /// ``` pub TRAIT_DUPLICATION_IN_BOUNDS, pedantic, - "Check if the same trait bounds are specifed twice during a function declaration" + "Check if the same trait bounds are specified twice during a function declaration" } #[derive(Copy, Clone)] diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 9fb3dfc96ec..197eab759f1 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2169,7 +2169,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ Lint { name: "trait_duplication_in_bounds", group: "pedantic", - desc: "Check if the same trait bounds are specifed twice during a function declaration", + desc: "Check if the same trait bounds are specified twice during a function declaration", deprecation: None, module: "trait_bounds", }, From a427c99f3d2a0b2c55d19af73bcad81f1dc761ab Mon Sep 17 00:00:00 2001 From: Dmitry Murzin <diralik@yandex.ru> Date: Sat, 25 Jul 2020 20:04:59 +0300 Subject: [PATCH 331/526] Handle mapping to Option in `map_flatten` lint --- clippy_lints/src/methods/mod.rs | 26 ++++++++++++++++++++++---- tests/ui/map_flatten.fixed | 1 + tests/ui/map_flatten.rs | 1 + tests/ui/map_flatten.stderr | 16 +++++++++++----- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 9edcdd979ff..3f62a3cab1c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2569,17 +2569,35 @@ fn lint_ok_expect(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ok_args: &[hir::Ex fn lint_map_flatten<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map_args: &'tcx [hir::Expr<'_>]) { // lint if caller of `.map().flatten()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `map(..).flatten()` on an `Iterator`. \ - This is more succinctly expressed by calling `.flat_map(..)`"; + let map_closure_ty = cx.typeck_results().expr_ty(&map_args[1]); + let is_map_to_option = if let ty::Closure(_def_id, substs) = map_closure_ty.kind { + let map_closure_return_ty = cx.tcx.erase_late_bound_regions(&substs.as_closure().sig().output()); + is_type_diagnostic_item(cx, map_closure_return_ty, sym!(option_type)) + } else { + false + }; + + let method_to_use = if is_map_to_option { + // `(...).map(...)` has type `impl Iterator<Item=Option<...>> + "filter_map" + } else { + // `(...).map(...)` has type `impl Iterator<Item=impl Iterator<...>> + "flat_map" + }; + let msg = &format!( + "called `map(..).flatten()` on an `Iterator`. \ + This is more succinctly expressed by calling `.{}(..)`", + method_to_use + ); let self_snippet = snippet(cx, map_args[0].span, ".."); let func_snippet = snippet(cx, map_args[1].span, ".."); - let hint = format!("{0}.flat_map({1})", self_snippet, func_snippet); + let hint = format!("{0}.{1}({2})", self_snippet, method_to_use, func_snippet); span_lint_and_sugg( cx, MAP_FLATTEN, expr.span, msg, - "try using `flat_map` instead", + &format!("try using `{}` instead", method_to_use), hint, Applicability::MachineApplicable, ); diff --git a/tests/ui/map_flatten.fixed b/tests/ui/map_flatten.fixed index 4171d80f48a..684a28aebcb 100644 --- a/tests/ui/map_flatten.fixed +++ b/tests/ui/map_flatten.fixed @@ -5,6 +5,7 @@ #![allow(clippy::map_identity)] fn main() { + let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(|x| x.checked_add(1)).collect(); let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect(); let _: Option<_> = (Some(Some(1))).and_then(|x| x); } diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index 16a0fd090ad..05789ee5232 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -5,6 +5,7 @@ #![allow(clippy::map_identity)] fn main() { + let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect(); let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); let _: Option<_> = (Some(Some(1))).map(|x| x).flatten(); } diff --git a/tests/ui/map_flatten.stderr b/tests/ui/map_flatten.stderr index 00bc41c15e9..d2d15362a6c 100644 --- a/tests/ui/map_flatten.stderr +++ b/tests/ui/map_flatten.stderr @@ -1,16 +1,22 @@ -error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` +error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.filter_map(..)` --> $DIR/map_flatten.rs:8:21 | -LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)` +LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `vec![5_i8; 6].into_iter().filter_map(|x| x.checked_add(1))` | = note: `-D clippy::map-flatten` implied by `-D warnings` +error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` + --> $DIR/map_flatten.rs:9:21 + | +LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)` + error: called `map(..).flatten()` on an `Option`. This is more succinctly expressed by calling `.and_then(..)` - --> $DIR/map_flatten.rs:9:24 + --> $DIR/map_flatten.rs:10:24 | LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `(Some(Some(1))).and_then(|x| x)` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors From d4ba561aafb501972f581c1f8e6d1885959f9306 Mon Sep 17 00:00:00 2001 From: Dmitry Murzin <diralik@yandex.ru> Date: Thu, 30 Jul 2020 22:20:31 +0300 Subject: [PATCH 332/526] Review fixes --- clippy_lints/src/methods/mod.rs | 36 +++++++++++++---------------- tests/ui/map_flatten.fixed | 13 +++++++++++ tests/ui/map_flatten.rs | 13 +++++++++++ tests/ui/map_flatten.stderr | 40 ++++++++++++++++++++++++--------- 4 files changed, 71 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 3f62a3cab1c..9217324b18c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2570,11 +2570,16 @@ fn lint_map_flatten<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map // lint if caller of `.map().flatten()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let map_closure_ty = cx.typeck_results().expr_ty(&map_args[1]); - let is_map_to_option = if let ty::Closure(_def_id, substs) = map_closure_ty.kind { - let map_closure_return_ty = cx.tcx.erase_late_bound_regions(&substs.as_closure().sig().output()); - is_type_diagnostic_item(cx, map_closure_return_ty, sym!(option_type)) - } else { - false + let is_map_to_option = match map_closure_ty.kind { + ty::Closure(_, _) | ty::FnDef(_, _) | ty::FnPtr(_) => { + let map_closure_sig = match map_closure_ty.kind { + ty::Closure(_, substs) => substs.as_closure().sig(), + _ => map_closure_ty.fn_sig(cx.tcx), + }; + let map_closure_return_ty = cx.tcx.erase_late_bound_regions(&map_closure_sig.output()); + is_type_diagnostic_item(cx, map_closure_return_ty, sym!(option_type)) + }, + _ => false, }; let method_to_use = if is_map_to_option { @@ -2584,19 +2589,13 @@ fn lint_map_flatten<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map // `(...).map(...)` has type `impl Iterator<Item=impl Iterator<...>> "flat_map" }; - let msg = &format!( - "called `map(..).flatten()` on an `Iterator`. \ - This is more succinctly expressed by calling `.{}(..)`", - method_to_use - ); - let self_snippet = snippet(cx, map_args[0].span, ".."); let func_snippet = snippet(cx, map_args[1].span, ".."); - let hint = format!("{0}.{1}({2})", self_snippet, method_to_use, func_snippet); + let hint = format!(".{0}({1})", method_to_use, func_snippet); span_lint_and_sugg( cx, MAP_FLATTEN, - expr.span, - msg, + expr.span.with_lo(map_args[0].span.hi()), + "called `map(..).flatten()` on an `Iterator`", &format!("try using `{}` instead", method_to_use), hint, Applicability::MachineApplicable, @@ -2605,16 +2604,13 @@ fn lint_map_flatten<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map // lint if caller of `.map().flatten()` is an Option if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym!(option_type)) { - let msg = "called `map(..).flatten()` on an `Option`. \ - This is more succinctly expressed by calling `.and_then(..)`"; - let self_snippet = snippet(cx, map_args[0].span, ".."); let func_snippet = snippet(cx, map_args[1].span, ".."); - let hint = format!("{0}.and_then({1})", self_snippet, func_snippet); + let hint = format!(".and_then({})", func_snippet); span_lint_and_sugg( cx, MAP_FLATTEN, - expr.span, - msg, + expr.span.with_lo(map_args[0].span.hi()), + "called `map(..).flatten()` on an `Option`", "try using `and_then` instead", hint, Applicability::MachineApplicable, diff --git a/tests/ui/map_flatten.fixed b/tests/ui/map_flatten.fixed index 684a28aebcb..a5fdf7df613 100644 --- a/tests/ui/map_flatten.fixed +++ b/tests/ui/map_flatten.fixed @@ -5,7 +5,20 @@ #![allow(clippy::map_identity)] fn main() { + // mapping to Option on Iterator + fn option_id(x: i8) -> Option<i8> { + Some(x) + } + let option_id_ref: fn(i8) -> Option<i8> = option_id; + let option_id_closure = |x| Some(x); + let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id).collect(); + let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id_ref).collect(); + let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id_closure).collect(); let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(|x| x.checked_add(1)).collect(); + + // mapping to Iterator on Iterator let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect(); + + // mapping to Option on Option let _: Option<_> = (Some(Some(1))).and_then(|x| x); } diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index 05789ee5232..abbc4e16e56 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -5,7 +5,20 @@ #![allow(clippy::map_identity)] fn main() { + // mapping to Option on Iterator + fn option_id(x: i8) -> Option<i8> { + Some(x) + } + let option_id_ref: fn(i8) -> Option<i8> = option_id; + let option_id_closure = |x| Some(x); + let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect(); + let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect(); + let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect(); let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect(); + + // mapping to Iterator on Iterator let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); + + // mapping to Option on Option let _: Option<_> = (Some(Some(1))).map(|x| x).flatten(); } diff --git a/tests/ui/map_flatten.stderr b/tests/ui/map_flatten.stderr index d2d15362a6c..b6479cd69ea 100644 --- a/tests/ui/map_flatten.stderr +++ b/tests/ui/map_flatten.stderr @@ -1,22 +1,40 @@ -error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.filter_map(..)` - --> $DIR/map_flatten.rs:8:21 +error: called `map(..).flatten()` on an `Iterator` + --> $DIR/map_flatten.rs:14:46 | -LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `vec![5_i8; 6].into_iter().filter_map(|x| x.checked_add(1))` +LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id)` | = note: `-D clippy::map-flatten` implied by `-D warnings` -error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)` - --> $DIR/map_flatten.rs:9:21 +error: called `map(..).flatten()` on an `Iterator` + --> $DIR/map_flatten.rs:15:46 + | +LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id_ref)` + +error: called `map(..).flatten()` on an `Iterator` + --> $DIR/map_flatten.rs:16:46 + | +LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id_closure)` + +error: called `map(..).flatten()` on an `Iterator` + --> $DIR/map_flatten.rs:17:46 + | +LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(|x| x.checked_add(1))` + +error: called `map(..).flatten()` on an `Iterator` + --> $DIR/map_flatten.rs:20:46 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `.flat_map(|x| 0..x)` -error: called `map(..).flatten()` on an `Option`. This is more succinctly expressed by calling `.and_then(..)` - --> $DIR/map_flatten.rs:10:24 +error: called `map(..).flatten()` on an `Option` + --> $DIR/map_flatten.rs:23:39 | LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `(Some(Some(1))).and_then(|x| x)` + | ^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `.and_then(|x| x)` -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors From cb00cdf0d77e6a21cd64558f1e373e696f31d301 Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Sun, 2 Aug 2020 11:25:03 +0200 Subject: [PATCH 333/526] Remove old Symbol reexport I couldn't really tell what it was meant to improve. It seems more clear without the renaming to `Name`? --- clippy_lints/src/attrs.rs | 3 +-- clippy_lints/src/lib.rs | 4 ---- clippy_lints/src/lifetimes.rs | 7 +++---- clippy_lints/src/loops.rs | 17 ++++++++--------- clippy_lints/src/shadow.rs | 18 +++++++++--------- clippy_lints/src/utils/mod.rs | 15 +++++++-------- 6 files changed, 28 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index c29432bf933..ed02763397a 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,6 +1,5 @@ //! checks for attributes -use crate::reexport::Name; use crate::utils::{ first_line_of_span, is_present_in_source, match_def_path, paths, snippet_opt, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, without_block_comments, @@ -514,7 +513,7 @@ fn is_relevant_expr(cx: &LateContext<'_>, tables: &ty::TypeckTables<'_>, expr: & } } -fn check_attrs(cx: &LateContext<'_>, span: Span, name: Name, attrs: &[Attribute]) { +fn check_attrs(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribute]) { if span.from_expansion() { return; } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7a4ca3902b3..b336de37c61 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -321,10 +321,6 @@ mod zero_div_zero; pub use crate::utils::conf::Conf; -mod reexport { - pub use rustc_span::Symbol as Name; -} - /// Register all pre expansion lints /// /// Pre-expansion lints run before any macro expansion has happened. diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 168f9f953e4..1b3639a02a0 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -13,9 +13,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::symbol::kw; +use rustc_span::symbol::{Symbol, kw}; -use crate::reexport::Name; use crate::utils::{in_macro, last_path_segment, span_lint, trait_ref_of_method}; declare_clippy_lint! { @@ -113,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { enum RefLt { Unnamed, Static, - Named(Name), + Named(Symbol), } fn check_fn_inner<'tcx>( @@ -456,7 +455,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, where_clause: &'tcx WhereCl } struct LifetimeChecker { - map: FxHashMap<Name, Span>, + map: FxHashMap<Symbol, Span>, } impl<'tcx> Visitor<'tcx> for LifetimeChecker { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 396bb659109..d0d6c2e04a0 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,5 +1,4 @@ use crate::consts::constant; -use crate::reexport::Name; use crate::utils::paths; use crate::utils::usage::{is_unused, mutated_variables}; use crate::utils::{ @@ -1184,7 +1183,7 @@ fn check_for_loop_range<'tcx>( } } -fn is_len_call(expr: &Expr<'_>, var: Name) -> bool { +fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool { if_chain! { if let ExprKind::MethodCall(ref method, _, ref len_args, _) = expr.kind; if len_args.len() == 1; @@ -1632,15 +1631,15 @@ struct VarVisitor<'a, 'tcx> { /// var name to look for as index var: HirId, /// indexed variables that are used mutably - indexed_mut: FxHashSet<Name>, + indexed_mut: FxHashSet<Symbol>, /// indirectly indexed variables (`v[(i + 4) % N]`), the extend is `None` for global - indexed_indirectly: FxHashMap<Name, Option<region::Scope>>, + indexed_indirectly: FxHashMap<Symbol, Option<region::Scope>>, /// subset of `indexed` of vars that are indexed directly: `v[i]` /// this will not contain cases like `v[calc_index(i)]` or `v[(i + 4) % N]` - indexed_directly: FxHashMap<Name, (Option<region::Scope>, Ty<'tcx>)>, + indexed_directly: FxHashMap<Symbol, (Option<region::Scope>, Ty<'tcx>)>, /// Any names that are used outside an index operation. /// Used to detect things like `&mut vec` used together with `vec[i]` - referenced: FxHashSet<Name>, + referenced: FxHashSet<Symbol>, /// has the loop variable been used in expressions other than the index of /// an index op? nonindex: bool, @@ -1996,7 +1995,7 @@ struct InitializeVisitor<'a, 'tcx> { end_expr: &'tcx Expr<'tcx>, // the for loop. Stop scanning here. var_id: HirId, state: VarState, - name: Option<Name>, + name: Option<Symbol>, depth: u32, // depth of conditional expressions past_loop: bool, } @@ -2159,7 +2158,7 @@ use self::Nesting::{LookFurther, RuledOut, Unknown}; struct LoopNestVisitor { hir_id: HirId, - iterator: Name, + iterator: Symbol, nesting: Nesting, } @@ -2210,7 +2209,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { } } -fn path_name(e: &Expr<'_>) -> Option<Name> { +fn path_name(e: &Expr<'_>) -> Option<Symbol> { if let ExprKind::Path(QPath::Resolved(_, ref path)) = e.kind { let segments = &path.segments; if segments.len() == 1 { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index fab13c8c124..97bd52e517c 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,4 +1,3 @@ -use crate::reexport::Name; use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then}; use rustc_hir::intravisit::FnKind; use rustc_hir::{ @@ -10,6 +9,7 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; +use rustc_span::symbol::Symbol; declare_clippy_lint! { /// **What it does:** Checks for bindings that shadow other bindings already in @@ -123,7 +123,7 @@ fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Bo check_expr(cx, &body.value, &mut bindings); } -fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Name, Span)>) { +fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Symbol, Span)>) { let len = bindings.len(); for stmt in block.stmts { match stmt.kind { @@ -138,7 +138,7 @@ fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: & bindings.truncate(len); } -fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Name, Span)>) { +fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Symbol, Span)>) { if in_external_macro(cx.sess(), local.span) { return; } @@ -173,7 +173,7 @@ fn check_pat<'tcx>( pat: &'tcx Pat<'_>, init: Option<&'tcx Expr<'_>>, span: Span, - bindings: &mut Vec<(Name, Span)>, + bindings: &mut Vec<(Symbol, Span)>, ) { // TODO: match more stuff / destructuring match pat.kind { @@ -254,7 +254,7 @@ fn check_pat<'tcx>( fn lint_shadow<'tcx>( cx: &LateContext<'tcx>, - name: Name, + name: Symbol, span: Span, pattern_span: Span, init: Option<&'tcx Expr<'_>>, @@ -315,7 +315,7 @@ fn lint_shadow<'tcx>( } } -fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Name, Span)>) { +fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Symbol, Span)>) { if in_external_macro(cx.sess(), expr.span) { return; } @@ -351,7 +351,7 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut } } -fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Name, Span)>) { +fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) { match ty.kind { TyKind::Slice(ref sty) => check_ty(cx, sty, bindings), TyKind::Array(ref fty, ref anon_const) => { @@ -371,7 +371,7 @@ fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<( } } -fn is_self_shadow(name: Name, expr: &Expr<'_>) -> bool { +fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool { match expr.kind { ExprKind::Box(ref inner) | ExprKind::AddrOf(_, _, ref inner) => is_self_shadow(name, inner), ExprKind::Block(ref block, _) => { @@ -383,6 +383,6 @@ fn is_self_shadow(name: Name, expr: &Expr<'_>) -> bool { } } -fn path_eq_name(name: Name, path: &Path<'_>) -> bool { +fn path_eq_name(name: Symbol, path: &Path<'_>) -> bool { !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.as_str() == name.as_str() } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 4b7a1c2b537..39317ecc82e 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -52,7 +52,6 @@ use rustc_trait_selection::traits::query::normalize::AtExt; use smallvec::SmallVec; use crate::consts::{constant, Constant}; -use crate::reexport::Name; /// Returns `true` if the two spans come from differing expansions (i.e., one is /// from a macro and one isn't). @@ -150,7 +149,7 @@ pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) } /// Checks if an expression references a variable of the given name. -pub fn match_var(expr: &Expr<'_>, var: Name) -> bool { +pub fn match_var(expr: &Expr<'_>, var: Symbol) -> bool { if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind { if let [p] = path.segments { return p.ident.name == var; @@ -422,7 +421,7 @@ pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool { } /// Gets the name of the item the expression is in, if available. -pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Name> { +pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> { let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id); match cx.tcx.hir().find(parent_id) { Some( @@ -435,7 +434,7 @@ pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Name> { } /// Gets the name of a `Pat`, if any. -pub fn get_pat_name(pat: &Pat<'_>) -> Option<Name> { +pub fn get_pat_name(pat: &Pat<'_>) -> Option<Symbol> { match pat.kind { PatKind::Binding(.., ref spname, _) => Some(spname.name), PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name), @@ -445,14 +444,14 @@ pub fn get_pat_name(pat: &Pat<'_>) -> Option<Name> { } struct ContainsName { - name: Name, + name: Symbol, result: bool, } impl<'tcx> Visitor<'tcx> for ContainsName { type Map = Map<'tcx>; - fn visit_name(&mut self, _: Span, name: Name) { + fn visit_name(&mut self, _: Span, name: Symbol) { if self.name == name { self.result = true; } @@ -463,7 +462,7 @@ impl<'tcx> Visitor<'tcx> for ContainsName { } /// Checks if an `Expr` contains a certain name. -pub fn contains_name(name: Name, expr: &Expr<'_>) -> bool { +pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool { let mut cn = ContainsName { name, result: false }; cn.visit_expr(expr); cn.result @@ -1029,7 +1028,7 @@ pub fn is_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow } -pub fn get_arg_name(pat: &Pat<'_>) -> Option<Name> { +pub fn get_arg_name(pat: &Pat<'_>) -> Option<Symbol> { match pat.kind { PatKind::Binding(.., ident, None) => Some(ident.name), PatKind::Ref(ref subpat, _) => get_arg_name(subpat), From bb6e857980748b000ba3b88d125c6b29aced0693 Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Sun, 2 Aug 2020 14:22:54 +0200 Subject: [PATCH 334/526] fmt --- clippy_lints/src/lifetimes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 1b3639a02a0..4df6827d77f 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -13,7 +13,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::symbol::{Symbol, kw}; +use rustc_span::symbol::{kw, Symbol}; use crate::utils::{in_macro, last_path_segment, span_lint, trait_ref_of_method}; From e336fe80d2f991a170b98190683039035b53c6ba Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 3 Aug 2020 00:36:28 +0200 Subject: [PATCH 335/526] manual_async_fn: take input lifetimes into account The anonymous future returned from an `async fn` captures all input lifetimes. This was not being taken into account. See https://github.com/rust-lang/rfcs/blob/master/text/2394-async_await.md#lifetime-capture-in-the-anonymous-future --- clippy_lints/src/manual_async_fn.rs | 63 ++++++++++++++++++++++++----- tests/ui/await_holding_lock.rs | 1 + tests/ui/await_holding_lock.stderr | 4 +- tests/ui/manual_async_fn.fixed | 40 ++++++++++++++++-- tests/ui/manual_async_fn.rs | 48 ++++++++++++++++++---- tests/ui/manual_async_fn.stderr | 30 +++++++------- 6 files changed, 146 insertions(+), 40 deletions(-) diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs index c19fb148cda..864d1ea87f5 100644 --- a/clippy_lints/src/manual_async_fn.rs +++ b/clippy_lints/src/manual_async_fn.rs @@ -4,8 +4,8 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericBound, HirId, IsAsync, - ItemKind, TraitRef, Ty, TyKind, TypeBindingKind, + AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId, + IsAsync, ItemKind, LifetimeName, TraitRef, Ty, TyKind, TypeBindingKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -27,8 +27,6 @@ declare_clippy_lint! { /// ``` /// Use instead: /// ```rust - /// use std::future::Future; - /// /// async fn foo() -> i32 { 42 } /// ``` pub MANUAL_ASYNC_FN, @@ -53,8 +51,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { if let IsAsync::NotAsync = header.asyncness; // Check that this function returns `impl Future` if let FnRetTy::Return(ret_ty) = decl.output; - if let Some(trait_ref) = future_trait_ref(cx, ret_ty); + if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty); if let Some(output) = future_output_ty(trait_ref); + if captures_all_lifetimes(decl.inputs, &output_lifetimes); // Check that the body of the function consists of one async block if let ExprKind::Block(block, _) = body.value.kind; if block.stmts.is_empty(); @@ -97,16 +96,35 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { } } -fn future_trait_ref<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) -> Option<&'tcx TraitRef<'tcx>> { +fn future_trait_ref<'tcx>( + cx: &LateContext<'tcx>, + ty: &'tcx Ty<'tcx>, +) -> Option<(&'tcx TraitRef<'tcx>, Vec<LifetimeName>)> { if_chain! { - if let TyKind::OpaqueDef(item_id, _) = ty.kind; + if let TyKind::OpaqueDef(item_id, bounds) = ty.kind; let item = cx.tcx.hir().item(item_id.id); if let ItemKind::OpaqueTy(opaque) = &item.kind; - if opaque.bounds.len() == 1; - if let GenericBound::Trait(poly, _) = &opaque.bounds[0]; - if poly.trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait(); + if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { + if let GenericBound::Trait(poly, _) = bound { + Some(&poly.trait_ref) + } else { + None + } + }); + if trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait(); then { - return Some(&poly.trait_ref); + let output_lifetimes = bounds + .iter() + .filter_map(|bound| { + if let GenericArg::Lifetime(lt) = bound { + Some(lt.name) + } else { + None + } + }) + .collect(); + + return Some((trait_ref, output_lifetimes)); } } @@ -129,6 +147,29 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t None } +fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName]) -> bool { + let input_lifetimes: Vec<LifetimeName> = inputs + .iter() + .filter_map(|ty| { + if let TyKind::Rptr(lt, _) = ty.kind { + Some(lt.name) + } else { + None + } + }) + .collect(); + + // The lint should trigger in one of these cases: + // - There are no input lifetimes + // - There's only one output lifetime bound using `+ '_` + // - All input lifetimes are explicitly bound to the output + input_lifetimes.is_empty() + || (output_lifetimes.len() == 1 && matches!(output_lifetimes[0], LifetimeName::Underscore)) + || input_lifetimes + .iter() + .all(|in_lt| output_lifetimes.iter().any(|out_lt| in_lt == out_lt)) +} + fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> { if_chain! { if let Some(block_expr) = block.expr; diff --git a/tests/ui/await_holding_lock.rs b/tests/ui/await_holding_lock.rs index 5c1fdd83efb..0458950edee 100644 --- a/tests/ui/await_holding_lock.rs +++ b/tests/ui/await_holding_lock.rs @@ -47,6 +47,7 @@ async fn not_good(x: &Mutex<u32>) -> u32 { first + second + third } +#[allow(clippy::manual_async_fn)] fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ { async move { let guard = x.lock().unwrap(); diff --git a/tests/ui/await_holding_lock.stderr b/tests/ui/await_holding_lock.stderr index 8c47cb37d8c..21bf49d16f0 100644 --- a/tests/ui/await_holding_lock.stderr +++ b/tests/ui/await_holding_lock.stderr @@ -46,13 +46,13 @@ LL | | }; | |_____^ error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await. - --> $DIR/await_holding_lock.rs:52:13 + --> $DIR/await_holding_lock.rs:53:13 | LL | let guard = x.lock().unwrap(); | ^^^^^ | note: these are all the await points this lock is held through - --> $DIR/await_holding_lock.rs:52:9 + --> $DIR/await_holding_lock.rs:53:9 | LL | / let guard = x.lock().unwrap(); LL | | baz().await diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed index 27222cc0869..4f551690c43 100644 --- a/tests/ui/manual_async_fn.fixed +++ b/tests/ui/manual_async_fn.fixed @@ -43,10 +43,6 @@ impl S { 42 } - async fn meth_fut(&self) -> i32 { 42 } - - async fn empty_fut(&self) {} - // should be ignored fn not_fut(&self) -> i32 { 42 @@ -64,4 +60,40 @@ impl S { } } +// Tests related to lifetime capture + +async fn elided(_: &i32) -> i32 { 42 } + +// should be ignored +fn elided_not_bound(_: &i32) -> impl Future<Output = i32> { + async { 42 } +} + +async fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> i32 { 42 } + +// should be ignored +#[allow(clippy::needless_lifetimes)] +fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> { + async { 42 } +} + +// should be ignored +mod issue_5765 { + use std::future::Future; + + struct A; + impl A { + fn f(&self) -> impl Future<Output = ()> { + async {} + } + } + + fn test() { + let _future = { + let a = A; + a.f() + }; + } +} + fn main() {} diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs index 6a0f1b26c88..6ed60309947 100644 --- a/tests/ui/manual_async_fn.rs +++ b/tests/ui/manual_async_fn.rs @@ -51,14 +51,6 @@ impl S { } } - fn meth_fut(&self) -> impl Future<Output = i32> { - async { 42 } - } - - fn empty_fut(&self) -> impl Future<Output = ()> { - async {} - } - // should be ignored fn not_fut(&self) -> i32 { 42 @@ -76,4 +68,44 @@ impl S { } } +// Tests related to lifetime capture + +fn elided(_: &i32) -> impl Future<Output = i32> + '_ { + async { 42 } +} + +// should be ignored +fn elided_not_bound(_: &i32) -> impl Future<Output = i32> { + async { 42 } +} + +fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b { + async { 42 } +} + +// should be ignored +#[allow(clippy::needless_lifetimes)] +fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> { + async { 42 } +} + +// should be ignored +mod issue_5765 { + use std::future::Future; + + struct A; + impl A { + fn f(&self) -> impl Future<Output = ()> { + async {} + } + } + + fn test() { + let _future = { + let a = A; + a.f() + }; + } +} + fn main() {} diff --git a/tests/ui/manual_async_fn.stderr b/tests/ui/manual_async_fn.stderr index a1904c904d0..ccd82867427 100644 --- a/tests/ui/manual_async_fn.stderr +++ b/tests/ui/manual_async_fn.stderr @@ -65,34 +65,34 @@ LL | let c = 21; ... error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:54:5 + --> $DIR/manual_async_fn.rs:73:1 | -LL | fn meth_fut(&self) -> impl Future<Output = i32> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: make the function `async` and return the output of the future directly | -LL | async fn meth_fut(&self) -> i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | async fn elided(_: &i32) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: move the body of the async block to the enclosing function | -LL | fn meth_fut(&self) -> impl Future<Output = i32> { 42 } - | ^^^^^^ +LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ { 42 } + | ^^^^^^ error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:58:5 + --> $DIR/manual_async_fn.rs:82:1 | -LL | fn empty_fut(&self) -> impl Future<Output = ()> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: make the function `async` and remove the return type +help: make the function `async` and return the output of the future directly | -LL | async fn empty_fut(&self) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | async fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: move the body of the async block to the enclosing function | -LL | fn empty_fut(&self) -> impl Future<Output = ()> {} - | ^^ +LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b { 42 } + | ^^^^^^ error: aborting due to 6 previous errors From 05bb6e6bdb1894de5803f729339a631a9222499f Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Mon, 20 Jul 2020 08:58:55 -0700 Subject: [PATCH 336/526] Create test for wanted behavior --- tests/ui/needless_collect.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 7ee603afeb0..1577e7a46ed 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -8,6 +8,9 @@ use std::collections::{BTreeSet, HashMap, HashSet}; #[allow(unused_variables, clippy::iter_cloned_collect)] fn main() { let sample = [1; 5]; + let indirect_with_into_iter = sample.iter().collect::<Vec<_>>(); + let indirect_with_iter = sample.iter().collect::<Vec<_>>();; + let indirect_negative = sample.iter().collect::<Vec<_>>();; let len = sample.iter().collect::<Vec<_>>().len(); if sample.iter().collect::<Vec<_>>().is_empty() { // Empty @@ -18,4 +21,8 @@ fn main() { sample.iter().collect::<HashSet<_>>().len(); // Neither should this sample.iter().collect::<BTreeSet<_>>().len(); + indirect_with_into_iter.into_iter().map(|x| (x, x+1)).collect::<HashMap<_, _>>(); + indirect_with_iter.iter().map(|x| (x, x+1)).collect::<HashMap<_, _>>(); + indirect_negative.iter().map(|x| (x, x+1)).collect::<HashMap<_, _>>(); + indirect_negative.iter().map(|x| (x, x+1)).collect::<HashMap<_, _>>(); } From 3ee61373fe056efb46b6b1b243b31cec0d7e6099 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Wed, 22 Jul 2020 22:46:23 -0700 Subject: [PATCH 337/526] Write the lint and write tests --- clippy_lints/src/loops.rs | 107 +++++++++++++++++++++++++++++-- tests/ui/needless_collect.fixed | 11 ++++ tests/ui/needless_collect.rs | 18 ++++-- tests/ui/needless_collect.stderr | 17 ++++- 4 files changed, 137 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7e3876ff49b..231c440463d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,14 +1,15 @@ use crate::consts::constant; use crate::reexport::Name; use crate::utils::paths; +use crate::utils::sugg::Sugg; use crate::utils::usage::{is_unused, mutated_variables}; use crate::utils::{ get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, - is_integer_const, is_no_std_crate, is_refutable, last_path_segment, match_trait_method, match_type, match_var, - multispan_sugg, snippet, snippet_opt, snippet_with_applicability, span_lint, span_lint_and_help, - span_lint_and_sugg, span_lint_and_then, SpanlessEq, + is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, last_path_segment, match_path, + match_trait_method, match_type, match_var, multispan_sugg, qpath_res, snippet, snippet_opt, + snippet_with_applicability, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, + SpanlessEq, }; -use crate::utils::{is_type_diagnostic_item, qpath_res, sugg}; use if_chain::if_chain; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -17,7 +18,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc_hir::{ def_id, BinOpKind, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, GenericArg, HirId, InlineAsmOperand, - LoopSource, MatchSource, Mutability, Node, Pat, PatKind, QPath, Stmt, StmtKind, + Local, LoopSource, MatchSource, Mutability, Node, Pat, PatKind, QPath, Stmt, StmtKind, }; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -27,7 +28,7 @@ use rustc_middle::middle::region; use rustc_middle::ty::{self, Ty, TyS}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{Ident, Symbol}; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use std::iter::{once, Iterator}; use std::mem; @@ -2358,6 +2359,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed"; fn check_needless_collect<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { + // Check for direct, immediate usage if_chain! { if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind; if let ExprKind::MethodCall(ref chain_method, _, _, _) = args[0].kind; @@ -2423,6 +2425,99 @@ fn check_needless_collect<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { } } } + // Check for collecting it and then turning it back into an iterator later + if let ExprKind::Block(ref block, _) = expr.kind { + for ref stmt in block.stmts { + if_chain! { + // TODO also work for assignments to an existing variable + if let StmtKind::Local( + Local { pat: Pat { kind: PatKind::Binding(_, _, ident, .. ), .. }, + init: Some(ref init_expr), .. } + ) = stmt.kind; + if let ExprKind::MethodCall(ref method_name, _, &[ref iter_source], ..) = init_expr.kind; + if method_name.ident.name == sym!(collect) && match_trait_method(cx, &init_expr, &paths::ITERATOR); + if let Some(ref generic_args) = method_name.args; + if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0); + if let ty = cx.typeck_results().node_type(ty.hir_id); + if is_type_diagnostic_item(cx, ty, sym!(vec_type)) || + is_type_diagnostic_item(cx, ty, sym!(vecdeque_type)) || + match_type(cx, ty, &paths::LINKED_LIST); + if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident); + if iter_calls.len() == 1; + then { + // Suggest replacing iter_call with iter_replacement, and removing stmt + span_lint_and_then( + cx, + NEEDLESS_COLLECT, + stmt.span, + NEEDLESS_COLLECT_MSG, + |diag| { + let iter_replacement = Sugg::hir(cx, iter_source, "..").to_string(); + diag.multipart_suggestion( + "Use the original Iterator instead of collecting it and then producing a new one", + vec![ + (stmt.span, String::new()), + (iter_calls[0].span, iter_replacement) + ], + Applicability::MaybeIncorrect, + ); + }, + ); + } + } + } + } +} + +struct IntoIterVisitor<'tcx> { + iters: Vec<&'tcx Expr<'tcx>>, + seen_other: bool, + target: String, +} +impl<'tcx> Visitor<'tcx> for IntoIterVisitor<'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { + match &expr.kind { + ExprKind::MethodCall( + method_name, + _, + &[Expr { + kind: ExprKind::Path(QPath::Resolved(_, ref path)), + .. + }], + _, + ) if match_path(path, &[&self.target]) => { + // TODO Check what method is being called, if it's called on target, and act + // accordingly + if method_name.ident.name == sym!(into_iter) { + self.iters.push(expr); + } else { + self.seen_other = true; + } + }, + _ => walk_expr(self, expr), + } + } + + type Map = Map<'tcx>; + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } +} + +/// Detect the occurences of calls to `iter` or `into_iter` for the +/// given identifier +fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<&'tcx Expr<'tcx>>> { + let mut visitor = IntoIterVisitor { + iters: Vec::new(), + target: identifier.name.to_ident_string(), + seen_other: false, + }; + visitor.visit_block(block); + if visitor.seen_other { + None + } else { + Some(visitor.iters) + } } fn shorten_span(expr: &Expr<'_>, target_fn_name: Symbol) -> Span { diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index be37dc16b9a..60a3e206283 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -18,4 +18,15 @@ fn main() { sample.iter().collect::<HashSet<_>>().len(); // Neither should this sample.iter().collect::<BTreeSet<_>>().len(); + let indirect_positive = sample.iter().collect::<Vec<_>>(); + indirect_positive + .into_iter() + .map(|x| (x, x + 1)) + .collect::<HashMap<_, _>>(); + let indirect_negative = sample.iter().collect::<Vec<_>>(); + indirect_negative.len(); + indirect_negative + .iter() + .map(|x| (*x, *x + 1)) + .collect::<HashMap<_, _>>(); } diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 1577e7a46ed..33a1ea36095 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -8,9 +8,6 @@ use std::collections::{BTreeSet, HashMap, HashSet}; #[allow(unused_variables, clippy::iter_cloned_collect)] fn main() { let sample = [1; 5]; - let indirect_with_into_iter = sample.iter().collect::<Vec<_>>(); - let indirect_with_iter = sample.iter().collect::<Vec<_>>();; - let indirect_negative = sample.iter().collect::<Vec<_>>();; let len = sample.iter().collect::<Vec<_>>().len(); if sample.iter().collect::<Vec<_>>().is_empty() { // Empty @@ -21,8 +18,15 @@ fn main() { sample.iter().collect::<HashSet<_>>().len(); // Neither should this sample.iter().collect::<BTreeSet<_>>().len(); - indirect_with_into_iter.into_iter().map(|x| (x, x+1)).collect::<HashMap<_, _>>(); - indirect_with_iter.iter().map(|x| (x, x+1)).collect::<HashMap<_, _>>(); - indirect_negative.iter().map(|x| (x, x+1)).collect::<HashMap<_, _>>(); - indirect_negative.iter().map(|x| (x, x+1)).collect::<HashMap<_, _>>(); + let indirect_positive = sample.iter().collect::<Vec<_>>(); + indirect_positive + .into_iter() + .map(|x| (x, x + 1)) + .collect::<HashMap<_, _>>(); + let indirect_negative = sample.iter().collect::<Vec<_>>(); + indirect_negative.len(); + indirect_negative + .iter() + .map(|x| (*x, *x + 1)) + .collect::<HashMap<_, _>>(); } diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index 9113aad90dd..bb67bfa83e9 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,10 +1,21 @@ +error: avoid using `collect()` when not needed + --> $DIR/needless_collect.rs:21:5 + | +LL | let indirect_positive = sample.iter().collect::<Vec<_>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::needless-collect` implied by `-D warnings` +help: Use the original Iterator instead of collecting it and then producing a new one + | +LL | +LL | sample.iter() + | + error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:11:29 | LL | let len = sample.iter().collect::<Vec<_>>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` - | - = note: `-D clippy::needless-collect` implied by `-D warnings` error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:12:15 @@ -24,5 +35,5 @@ error: avoid using `collect()` when not needed LL | sample.iter().map(|x| (x, x)).collect::<HashMap<_, _>>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors From 3657c92ac978f69667b9c8bb46e51bc602b3d7ee Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 23 Jul 2020 09:14:10 -0700 Subject: [PATCH 338/526] Check for other things which can be used indirectly --- clippy_lints/src/loops.rs | 94 ++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 231c440463d..11a9b1e531c 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2429,7 +2429,6 @@ fn check_needless_collect<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { if let ExprKind::Block(ref block, _) = expr.kind { for ref stmt in block.stmts { if_chain! { - // TODO also work for assignments to an existing variable if let StmtKind::Local( Local { pat: Pat { kind: PatKind::Binding(_, _, ident, .. ), .. }, init: Some(ref init_expr), .. } @@ -2446,21 +2445,22 @@ fn check_needless_collect<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { if iter_calls.len() == 1; then { // Suggest replacing iter_call with iter_replacement, and removing stmt + let iter_call = &iter_calls[0]; span_lint_and_then( cx, NEEDLESS_COLLECT, - stmt.span, + stmt.span.until(iter_call.span), NEEDLESS_COLLECT_MSG, |diag| { - let iter_replacement = Sugg::hir(cx, iter_source, "..").to_string(); + let iter_replacement = format!("{}{}", Sugg::hir(cx, iter_source, ".."), iter_call.get_iter_method(cx)); diag.multipart_suggestion( - "Use the original Iterator instead of collecting it and then producing a new one", + iter_call.get_suggestion_text(), vec![ (stmt.span, String::new()), - (iter_calls[0].span, iter_replacement) + (iter_call.span, iter_replacement) ], - Applicability::MaybeIncorrect, - ); + Applicability::MachineApplicable,// MaybeIncorrect, + ).emit(); }, ); } @@ -2469,32 +2469,62 @@ fn check_needless_collect<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { } } -struct IntoIterVisitor<'tcx> { - iters: Vec<&'tcx Expr<'tcx>>, +struct IterFunction { + func: IterFunctionKind, + span: Span, +} +impl IterFunction { + fn get_iter_method(&self, cx: &LateContext<'_>) -> String { + match &self.func { + IterFunctionKind::IntoIter => String::new(), + IterFunctionKind::Len => String::from(".count()"), + IterFunctionKind::IsEmpty => String::from(".next().is_none()"), + IterFunctionKind::Contains(span) => format!(".any(|x| x == {})", snippet(cx, *span, "..")), + } + } + fn get_suggestion_text(&self) -> &'static str { + match &self.func { + IterFunctionKind::IntoIter => "Use the original Iterator instead of collecting it and then producing a new one", + IterFunctionKind::Len => "Take the original Iterator's count instead of collecting it and finding the length", + IterFunctionKind::IsEmpty => "Check if the original Iterator has anything instead of collecting it and seeing if it's empty", + IterFunctionKind::Contains(_) => "Check if the original Iterator contains an element instead of collecting then checking", + } + } +} +enum IterFunctionKind { + IntoIter, + Len, + IsEmpty, + Contains(Span), +} + +struct IterFunctionVisitor { + uses: Vec<IterFunction>, seen_other: bool, target: String, } -impl<'tcx> Visitor<'tcx> for IntoIterVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for IterFunctionVisitor { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - match &expr.kind { - ExprKind::MethodCall( - method_name, - _, - &[Expr { - kind: ExprKind::Path(QPath::Resolved(_, ref path)), - .. - }], - _, - ) if match_path(path, &[&self.target]) => { - // TODO Check what method is being called, if it's called on target, and act - // accordingly - if method_name.ident.name == sym!(into_iter) { - self.iters.push(expr); - } else { - self.seen_other = true; + if_chain! { + if let ExprKind::MethodCall(method_name, _, ref args, _) = &expr.kind; + if let Some(Expr { kind: ExprKind::Path(QPath::Resolved(_, ref path)), .. }) = args.get(0); + if match_path(path, &[&self.target]); + then { + let into_iter = sym!(into_iter); + let len = sym!(len); + let is_empty = sym!(is_empty); + let contains = sym!(contains); + match method_name.ident.name { + name if name == into_iter => self.uses.push(IterFunction { func: IterFunctionKind::IntoIter, span: expr.span }), + name if name == len => self.uses.push(IterFunction { func: IterFunctionKind::Len, span: expr.span }), + name if name == is_empty => self.uses.push(IterFunction { func: IterFunctionKind::IsEmpty, span: expr.span }), + name if name == contains => self.uses.push(IterFunction { func: IterFunctionKind::Contains(args[1].span), span: expr.span }), + _ => self.seen_other = true, } - }, - _ => walk_expr(self, expr), + } + else { + walk_expr(self, expr); + } } } @@ -2506,9 +2536,9 @@ impl<'tcx> Visitor<'tcx> for IntoIterVisitor<'tcx> { /// Detect the occurences of calls to `iter` or `into_iter` for the /// given identifier -fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<&'tcx Expr<'tcx>>> { - let mut visitor = IntoIterVisitor { - iters: Vec::new(), +fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<IterFunction>> { + let mut visitor = IterFunctionVisitor { + uses: Vec::new(), target: identifier.name.to_ident_string(), seen_other: false, }; @@ -2516,7 +2546,7 @@ fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) if visitor.seen_other { None } else { - Some(visitor.iters) + Some(visitor.uses) } } From c86f4109fdd83fef1ea69c0f3c878ace0aa7c56f Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 23 Jul 2020 09:15:16 -0700 Subject: [PATCH 339/526] Split indirect collects into their own test case --- tests/ui/needless_collect.fixed | 11 ----- tests/ui/needless_collect.rs | 11 ----- tests/ui/needless_collect.stderr | 17 ++----- tests/ui/needless_collect_indirect.fixed | 26 +++++++++++ tests/ui/needless_collect_indirect.rs | 26 +++++++++++ tests/ui/needless_collect_indirect.stderr | 55 +++++++++++++++++++++++ 6 files changed, 110 insertions(+), 36 deletions(-) create mode 100644 tests/ui/needless_collect_indirect.fixed create mode 100644 tests/ui/needless_collect_indirect.rs create mode 100644 tests/ui/needless_collect_indirect.stderr diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index 60a3e206283..be37dc16b9a 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -18,15 +18,4 @@ fn main() { sample.iter().collect::<HashSet<_>>().len(); // Neither should this sample.iter().collect::<BTreeSet<_>>().len(); - let indirect_positive = sample.iter().collect::<Vec<_>>(); - indirect_positive - .into_iter() - .map(|x| (x, x + 1)) - .collect::<HashMap<_, _>>(); - let indirect_negative = sample.iter().collect::<Vec<_>>(); - indirect_negative.len(); - indirect_negative - .iter() - .map(|x| (*x, *x + 1)) - .collect::<HashMap<_, _>>(); } diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 33a1ea36095..7ee603afeb0 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -18,15 +18,4 @@ fn main() { sample.iter().collect::<HashSet<_>>().len(); // Neither should this sample.iter().collect::<BTreeSet<_>>().len(); - let indirect_positive = sample.iter().collect::<Vec<_>>(); - indirect_positive - .into_iter() - .map(|x| (x, x + 1)) - .collect::<HashMap<_, _>>(); - let indirect_negative = sample.iter().collect::<Vec<_>>(); - indirect_negative.len(); - indirect_negative - .iter() - .map(|x| (*x, *x + 1)) - .collect::<HashMap<_, _>>(); } diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index bb67bfa83e9..9113aad90dd 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,21 +1,10 @@ -error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:21:5 - | -LL | let indirect_positive = sample.iter().collect::<Vec<_>>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::needless-collect` implied by `-D warnings` -help: Use the original Iterator instead of collecting it and then producing a new one - | -LL | -LL | sample.iter() - | - error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:11:29 | LL | let len = sample.iter().collect::<Vec<_>>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` + | + = note: `-D clippy::needless-collect` implied by `-D warnings` error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:12:15 @@ -35,5 +24,5 @@ error: avoid using `collect()` when not needed LL | sample.iter().map(|x| (x, x)).collect::<HashMap<_, _>>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/needless_collect_indirect.fixed b/tests/ui/needless_collect_indirect.fixed new file mode 100644 index 00000000000..136af42a9fe --- /dev/null +++ b/tests/ui/needless_collect_indirect.fixed @@ -0,0 +1,26 @@ +// run-rustfix + +#[allow(unused)] + +use std::collections::{HashMap, VecDeque}; + +fn main() { + let sample = [1; 5]; + let indirect_iter = sample.iter().collect::<Vec<_>>(); + indirect_iter + .into_iter() + .map(|x| (x, x + 1)) + .collect::<HashMap<_, _>>(); + let indirect_len = sample.iter().collect::<VecDeque<_>>(); + indirect_len.len(); + let indirect_empty = sample.iter().collect::<VecDeque<_>>(); + indirect_empty.is_empty(); + let indirect_contains = sample.iter().collect::<VecDeque<_>>(); + indirect_contains.contains(&&5); + let indirect_negative = sample.iter().collect::<Vec<_>>(); + indirect_negative.len(); + indirect_negative + .into_iter() + .map(|x| (*x, *x + 1)) + .collect::<HashMap<_, _>>(); +} diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs new file mode 100644 index 00000000000..136af42a9fe --- /dev/null +++ b/tests/ui/needless_collect_indirect.rs @@ -0,0 +1,26 @@ +// run-rustfix + +#[allow(unused)] + +use std::collections::{HashMap, VecDeque}; + +fn main() { + let sample = [1; 5]; + let indirect_iter = sample.iter().collect::<Vec<_>>(); + indirect_iter + .into_iter() + .map(|x| (x, x + 1)) + .collect::<HashMap<_, _>>(); + let indirect_len = sample.iter().collect::<VecDeque<_>>(); + indirect_len.len(); + let indirect_empty = sample.iter().collect::<VecDeque<_>>(); + indirect_empty.is_empty(); + let indirect_contains = sample.iter().collect::<VecDeque<_>>(); + indirect_contains.contains(&&5); + let indirect_negative = sample.iter().collect::<Vec<_>>(); + indirect_negative.len(); + indirect_negative + .into_iter() + .map(|x| (*x, *x + 1)) + .collect::<HashMap<_, _>>(); +} diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr new file mode 100644 index 00000000000..5058c171ac2 --- /dev/null +++ b/tests/ui/needless_collect_indirect.stderr @@ -0,0 +1,55 @@ +error: avoid using `collect()` when not needed + --> $DIR/needless_collect_indirect.rs:9:5 + | +LL | / let indirect_iter = sample.iter().collect::<Vec<_>>(); +LL | | indirect_iter + | |____^ + | + = note: `-D clippy::needless-collect` implied by `-D warnings` +help: Use the original Iterator instead of collecting it and then producing a new one + | +LL | +LL | sample.iter() + | + +error: avoid using `collect()` when not needed + --> $DIR/needless_collect_indirect.rs:14:5 + | +LL | / let indirect_len = sample.iter().collect::<VecDeque<_>>(); +LL | | indirect_len.len(); + | |____^ + | +help: Take the original Iterator's count instead of collecting it and finding the length + | +LL | +LL | sample.iter().count(); + | + +error: avoid using `collect()` when not needed + --> $DIR/needless_collect_indirect.rs:16:5 + | +LL | / let indirect_empty = sample.iter().collect::<VecDeque<_>>(); +LL | | indirect_empty.is_empty(); + | |____^ + | +help: Check if the original Iterator has anything instead of collecting it and seeing if it's empty + | +LL | +LL | sample.iter().next().is_none(); + | + +error: avoid using `collect()` when not needed + --> $DIR/needless_collect_indirect.rs:18:5 + | +LL | / let indirect_contains = sample.iter().collect::<VecDeque<_>>(); +LL | | indirect_contains.contains(&&5); + | |____^ + | +help: Check if the original Iterator contains an element instead of collecting then checking + | +LL | +LL | sample.iter().any(|x| x == &&5); + | + +error: aborting due to 4 previous errors + From a84948329459e650af4eb2f8cff8f55282316ea5 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 23 Jul 2020 09:44:44 -0700 Subject: [PATCH 340/526] Fix formatting and dogfood fallout --- clippy_lints/src/loops.rs | 43 +++++++++++++++++------ tests/ui/needless_collect_indirect.fixed | 6 +--- tests/ui/needless_collect_indirect.rs | 6 +--- tests/ui/needless_collect_indirect.stderr | 12 +++---- 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 11a9b1e531c..2181304f006 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2359,7 +2359,10 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed"; fn check_needless_collect<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { - // Check for direct, immediate usage + check_needless_collect_direct_usage(expr, cx); + check_needless_collect_indirect_usage(expr, cx); +} +fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { if_chain! { if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind; if let ExprKind::MethodCall(ref chain_method, _, _, _) = args[0].kind; @@ -2425,7 +2428,9 @@ fn check_needless_collect<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { } } } - // Check for collecting it and then turning it back into an iterator later +} + +fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { if let ExprKind::Block(ref block, _) = expr.kind { for ref stmt in block.stmts { if_chain! { @@ -2484,10 +2489,18 @@ impl IterFunction { } fn get_suggestion_text(&self) -> &'static str { match &self.func { - IterFunctionKind::IntoIter => "Use the original Iterator instead of collecting it and then producing a new one", - IterFunctionKind::Len => "Take the original Iterator's count instead of collecting it and finding the length", - IterFunctionKind::IsEmpty => "Check if the original Iterator has anything instead of collecting it and seeing if it's empty", - IterFunctionKind::Contains(_) => "Check if the original Iterator contains an element instead of collecting then checking", + IterFunctionKind::IntoIter => { + "Use the original Iterator instead of collecting it and then producing a new one" + }, + IterFunctionKind::Len => { + "Take the original Iterator's count instead of collecting it and finding the length" + }, + IterFunctionKind::IsEmpty => { + "Check if the original Iterator has anything instead of collecting it and seeing if it's empty" + }, + IterFunctionKind::Contains(_) => { + "Check if the original Iterator contains an element instead of collecting then checking" + }, } } } @@ -2505,6 +2518,8 @@ struct IterFunctionVisitor { } impl<'tcx> Visitor<'tcx> for IterFunctionVisitor { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { + // TODO Check if the target identifier is being used in something other + // than a function call if_chain! { if let ExprKind::MethodCall(method_name, _, ref args, _) = &expr.kind; if let Some(Expr { kind: ExprKind::Path(QPath::Resolved(_, ref path)), .. }) = args.get(0); @@ -2515,10 +2530,18 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor { let is_empty = sym!(is_empty); let contains = sym!(contains); match method_name.ident.name { - name if name == into_iter => self.uses.push(IterFunction { func: IterFunctionKind::IntoIter, span: expr.span }), - name if name == len => self.uses.push(IterFunction { func: IterFunctionKind::Len, span: expr.span }), - name if name == is_empty => self.uses.push(IterFunction { func: IterFunctionKind::IsEmpty, span: expr.span }), - name if name == contains => self.uses.push(IterFunction { func: IterFunctionKind::Contains(args[1].span), span: expr.span }), + name if name == into_iter => self.uses.push( + IterFunction { func: IterFunctionKind::IntoIter, span: expr.span } + ), + name if name == len => self.uses.push( + IterFunction { func: IterFunctionKind::Len, span: expr.span } + ), + name if name == is_empty => self.uses.push( + IterFunction { func: IterFunctionKind::IsEmpty, span: expr.span } + ), + name if name == contains => self.uses.push( + IterFunction { func: IterFunctionKind::Contains(args[1].span), span: expr.span } + ), _ => self.seen_other = true, } } diff --git a/tests/ui/needless_collect_indirect.fixed b/tests/ui/needless_collect_indirect.fixed index 136af42a9fe..163eaf965dd 100644 --- a/tests/ui/needless_collect_indirect.fixed +++ b/tests/ui/needless_collect_indirect.fixed @@ -1,16 +1,12 @@ // run-rustfix #[allow(unused)] - use std::collections::{HashMap, VecDeque}; fn main() { let sample = [1; 5]; let indirect_iter = sample.iter().collect::<Vec<_>>(); - indirect_iter - .into_iter() - .map(|x| (x, x + 1)) - .collect::<HashMap<_, _>>(); + indirect_iter.into_iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); let indirect_len = sample.iter().collect::<VecDeque<_>>(); indirect_len.len(); let indirect_empty = sample.iter().collect::<VecDeque<_>>(); diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs index 136af42a9fe..163eaf965dd 100644 --- a/tests/ui/needless_collect_indirect.rs +++ b/tests/ui/needless_collect_indirect.rs @@ -1,16 +1,12 @@ // run-rustfix #[allow(unused)] - use std::collections::{HashMap, VecDeque}; fn main() { let sample = [1; 5]; let indirect_iter = sample.iter().collect::<Vec<_>>(); - indirect_iter - .into_iter() - .map(|x| (x, x + 1)) - .collect::<HashMap<_, _>>(); + indirect_iter.into_iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); let indirect_len = sample.iter().collect::<VecDeque<_>>(); indirect_len.len(); let indirect_empty = sample.iter().collect::<VecDeque<_>>(); diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr index 5058c171ac2..700c73b0b22 100644 --- a/tests/ui/needless_collect_indirect.stderr +++ b/tests/ui/needless_collect_indirect.stderr @@ -1,19 +1,19 @@ error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:9:5 + --> $DIR/needless_collect_indirect.rs:8:5 | LL | / let indirect_iter = sample.iter().collect::<Vec<_>>(); -LL | | indirect_iter +LL | | indirect_iter.into_iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); | |____^ | = note: `-D clippy::needless-collect` implied by `-D warnings` help: Use the original Iterator instead of collecting it and then producing a new one | LL | -LL | sample.iter() +LL | sample.iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:14:5 + --> $DIR/needless_collect_indirect.rs:10:5 | LL | / let indirect_len = sample.iter().collect::<VecDeque<_>>(); LL | | indirect_len.len(); @@ -26,7 +26,7 @@ LL | sample.iter().count(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:16:5 + --> $DIR/needless_collect_indirect.rs:12:5 | LL | / let indirect_empty = sample.iter().collect::<VecDeque<_>>(); LL | | indirect_empty.is_empty(); @@ -39,7 +39,7 @@ LL | sample.iter().next().is_none(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:18:5 + --> $DIR/needless_collect_indirect.rs:14:5 | LL | / let indirect_contains = sample.iter().collect::<VecDeque<_>>(); LL | | indirect_contains.contains(&&5); From bb2c14e92b5a0eafe9c9f43f3a02e33b544b3f91 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Thu, 23 Jul 2020 10:07:51 -0700 Subject: [PATCH 341/526] Fix a bug causing it to be too trigger-happy --- clippy_lints/src/loops.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2181304f006..c931c212735 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -5,10 +5,9 @@ use crate::utils::sugg::Sugg; use crate::utils::usage::{is_unused, mutated_variables}; use crate::utils::{ get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, - is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, last_path_segment, match_path, - match_trait_method, match_type, match_var, multispan_sugg, qpath_res, snippet, snippet_opt, - snippet_with_applicability, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, - SpanlessEq, + is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, last_path_segment, match_trait_method, + match_type, match_var, multispan_sugg, qpath_res, snippet, snippet_opt, snippet_with_applicability, span_lint, + span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, SpanlessEq, }; use if_chain::if_chain; use rustc_ast::ast; @@ -2514,16 +2513,16 @@ enum IterFunctionKind { struct IterFunctionVisitor { uses: Vec<IterFunction>, seen_other: bool, - target: String, + target: Ident, } impl<'tcx> Visitor<'tcx> for IterFunctionVisitor { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - // TODO Check if the target identifier is being used in something other - // than a function call + // Check function calls on our collection if_chain! { if let ExprKind::MethodCall(method_name, _, ref args, _) = &expr.kind; if let Some(Expr { kind: ExprKind::Path(QPath::Resolved(_, ref path)), .. }) = args.get(0); - if match_path(path, &[&self.target]); + if let &[name] = &path.segments; + if name.ident == self.target; then { let into_iter = sym!(into_iter); let len = sym!(len); @@ -2544,8 +2543,17 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor { ), _ => self.seen_other = true, } + return } - else { + } + // Check if the collection is used for anything else + if_chain! { + if let Expr { kind: ExprKind::Path(QPath::Resolved(_, ref path)), .. } = expr; + if let &[name] = &path.segments; + if name.ident == self.target; + then { + self.seen_other = true; + } else { walk_expr(self, expr); } } @@ -2562,7 +2570,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor { fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<IterFunction>> { let mut visitor = IterFunctionVisitor { uses: Vec::new(), - target: identifier.name.to_ident_string(), + target: identifier, seen_other: false, }; visitor.visit_block(block); From 5e10b039a3f215b48a54ce7dd38f95115f92e55a Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Sun, 2 Aug 2020 21:46:18 -0700 Subject: [PATCH 342/526] Implement review suggestions --- clippy_lints/src/loops.rs | 7 +++---- tests/ui/needless_collect_indirect.fixed | 22 ---------------------- tests/ui/needless_collect_indirect.rs | 3 --- tests/ui/needless_collect_indirect.stderr | 8 ++++---- 4 files changed, 7 insertions(+), 33 deletions(-) delete mode 100644 tests/ui/needless_collect_indirect.fixed diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index c931c212735..e9ce804320f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -27,7 +27,7 @@ use rustc_middle::middle::region; use rustc_middle::ty::{self, Ty, TyS}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use std::iter::{once, Iterator}; use std::mem; @@ -2442,7 +2442,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo if let Some(ref generic_args) = method_name.args; if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0); if let ty = cx.typeck_results().node_type(ty.hir_id); - if is_type_diagnostic_item(cx, ty, sym!(vec_type)) || + if is_type_diagnostic_item(cx, ty, sym::vec_type) || is_type_diagnostic_item(cx, ty, sym!(vecdeque_type)) || match_type(cx, ty, &paths::LINKED_LIST); if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident); @@ -2524,12 +2524,11 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor { if let &[name] = &path.segments; if name.ident == self.target; then { - let into_iter = sym!(into_iter); let len = sym!(len); let is_empty = sym!(is_empty); let contains = sym!(contains); match method_name.ident.name { - name if name == into_iter => self.uses.push( + sym::into_iter => self.uses.push( IterFunction { func: IterFunctionKind::IntoIter, span: expr.span } ), name if name == len => self.uses.push( diff --git a/tests/ui/needless_collect_indirect.fixed b/tests/ui/needless_collect_indirect.fixed deleted file mode 100644 index 163eaf965dd..00000000000 --- a/tests/ui/needless_collect_indirect.fixed +++ /dev/null @@ -1,22 +0,0 @@ -// run-rustfix - -#[allow(unused)] -use std::collections::{HashMap, VecDeque}; - -fn main() { - let sample = [1; 5]; - let indirect_iter = sample.iter().collect::<Vec<_>>(); - indirect_iter.into_iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); - let indirect_len = sample.iter().collect::<VecDeque<_>>(); - indirect_len.len(); - let indirect_empty = sample.iter().collect::<VecDeque<_>>(); - indirect_empty.is_empty(); - let indirect_contains = sample.iter().collect::<VecDeque<_>>(); - indirect_contains.contains(&&5); - let indirect_negative = sample.iter().collect::<Vec<_>>(); - indirect_negative.len(); - indirect_negative - .into_iter() - .map(|x| (*x, *x + 1)) - .collect::<HashMap<_, _>>(); -} diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs index 163eaf965dd..4cf03e82035 100644 --- a/tests/ui/needless_collect_indirect.rs +++ b/tests/ui/needless_collect_indirect.rs @@ -1,6 +1,3 @@ -// run-rustfix - -#[allow(unused)] use std::collections::{HashMap, VecDeque}; fn main() { diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr index 700c73b0b22..0c1e61d7496 100644 --- a/tests/ui/needless_collect_indirect.stderr +++ b/tests/ui/needless_collect_indirect.stderr @@ -1,5 +1,5 @@ error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:8:5 + --> $DIR/needless_collect_indirect.rs:5:5 | LL | / let indirect_iter = sample.iter().collect::<Vec<_>>(); LL | | indirect_iter.into_iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); @@ -13,7 +13,7 @@ LL | sample.iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:10:5 + --> $DIR/needless_collect_indirect.rs:7:5 | LL | / let indirect_len = sample.iter().collect::<VecDeque<_>>(); LL | | indirect_len.len(); @@ -26,7 +26,7 @@ LL | sample.iter().count(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:12:5 + --> $DIR/needless_collect_indirect.rs:9:5 | LL | / let indirect_empty = sample.iter().collect::<VecDeque<_>>(); LL | | indirect_empty.is_empty(); @@ -39,7 +39,7 @@ LL | sample.iter().next().is_none(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:14:5 + --> $DIR/needless_collect_indirect.rs:11:5 | LL | / let indirect_contains = sample.iter().collect::<VecDeque<_>>(); LL | | indirect_contains.contains(&&5); From e521c67e5f29ddd84e0ce744dfc27a836d349514 Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Mon, 3 Aug 2020 12:32:23 +0200 Subject: [PATCH 343/526] early return on empty parameters/where clause --- clippy_lints/src/trait_bounds.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 10811374875..06631f89f27 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -148,7 +148,7 @@ impl TraitBounds { } fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) { - if in_macro(gen.span) { + if in_macro(gen.span) || gen.params.is_empty() || gen.where_clause.predicates.is_empty() { return; } From 0e44ed5ca9b1436c245a4660b04e76fd99be7420 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Mon, 3 Aug 2020 17:22:47 +0200 Subject: [PATCH 344/526] Fix ui-cargo tests in CI --- tests/compile-test.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index eb6d495acbe..911da40d27b 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -3,7 +3,7 @@ use compiletest_rs as compiletest; use compiletest_rs::common::Mode as TestMode; -use std::env::{self, set_var}; +use std::env::{self, set_var, var}; use std::ffi::OsStr; use std::fs; use std::io; @@ -136,7 +136,9 @@ fn run_ui_toml(config: &mut compiletest::Config) { let tests = compiletest::make_tests(&config); + let manifest_dir = var("CARGO_MANIFEST_DIR").unwrap_or_default(); let res = run_tests(&config, tests); + set_var("CARGO_MANIFEST_DIR", &manifest_dir); match res { Ok(true) => {}, Ok(false) => panic!("Some tests failed"), From 25abd7ae76e2a708dda5487119c20af3be64edb7 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Wed, 8 Jul 2020 20:29:56 -0700 Subject: [PATCH 345/526] Create stable_sort_primitive lint --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 + clippy_lints/src/stable_sort_primitive.rs | 130 ++++++++++++++++++++++ clippy_lints/src/utils/mod.rs | 30 +++++ src/lintlist/mod.rs | 7 ++ tests/ui/stable_sort_primitive.fixed | 32 ++++++ tests/ui/stable_sort_primitive.rs | 32 ++++++ tests/ui/stable_sort_primitive.stderr | 46 ++++++++ tests/ui/unnecessary_sort_by.fixed | 2 + tests/ui/unnecessary_sort_by.rs | 2 + tests/ui/unnecessary_sort_by.stderr | 14 +-- 11 files changed, 294 insertions(+), 7 deletions(-) create mode 100644 clippy_lints/src/stable_sort_primitive.rs create mode 100644 tests/ui/stable_sort_primitive.fixed create mode 100644 tests/ui/stable_sort_primitive.rs create mode 100644 tests/ui/stable_sort_primitive.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 776b04295f9..43a32e828d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1701,6 +1701,7 @@ Released 2018-09-13 [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next [`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization +[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive [`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string [`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add [`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f371942dbee..9fc07e07fd3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -288,6 +288,7 @@ mod serde_api; mod shadow; mod single_component_path_imports; mod slow_vector_initialization; +mod stable_sort_primitive; mod strings; mod suspicious_trait_impl; mod swap; @@ -776,6 +777,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &shadow::SHADOW_UNRELATED, &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, + &stable_sort_primitive::STABLE_SORT_PRIMITIVE, &strings::STRING_ADD, &strings::STRING_ADD_ASSIGN, &strings::STRING_LIT_AS_BYTES, @@ -1078,6 +1080,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box macro_use::MacroUseImports::default()); store.register_late_pass(|| box map_identity::MapIdentity); store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch); + store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive); store.register_late_pass(|| box repeat_once::RepeatOnce); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ @@ -1408,6 +1411,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), + LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), @@ -1723,6 +1727,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&mutex_atomic::MUTEX_ATOMIC), LintId::of(&redundant_clone::REDUNDANT_CLONE), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), + LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE), LintId::of(&types::BOX_VEC), LintId::of(&types::REDUNDANT_ALLOCATION), LintId::of(&vec::USELESS_VEC), diff --git a/clippy_lints/src/stable_sort_primitive.rs b/clippy_lints/src/stable_sort_primitive.rs new file mode 100644 index 00000000000..c48da004a60 --- /dev/null +++ b/clippy_lints/src/stable_sort_primitive.rs @@ -0,0 +1,130 @@ +use crate::utils::{is_slice_of_primitives, span_lint_and_sugg, sugg::Sugg}; + +use if_chain::if_chain; + +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** + /// When sorting primitive values (integers, bools, chars, as well + /// as arrays, slices, and tuples of such items), it is better to + /// use an unstable sort than a stable sort. + /// + /// **Why is this bad?** + /// Using a stable sort consumes more memory and cpu cycles. Because + /// values which compare equal are identical, preserving their + /// relative order (the guarantee that a stable sort provides) means + /// nothing, while the extra costs still apply. + /// + /// **Known problems:** + /// None + /// + /// **Example:** + /// + /// ```rust + /// let mut vec = vec![2, 1, 3]; + /// vec.sort(); + /// ``` + /// Use instead: + /// ```rust + /// let mut vec = vec![2, 1, 3]; + /// vec.sort_unstable(); + /// ``` + pub STABLE_SORT_PRIMITIVE, + perf, + "use of sort() when sort_unstable() is equivalent" +} + +declare_lint_pass!(StableSortPrimitive => [STABLE_SORT_PRIMITIVE]); + +/// The three "kinds" of sorts +enum SortingKind { + Vanilla, + // The other kinds of lint are currently commented out because they + // can map distinct values to equal ones. If the key function is + // provably one-to-one, or if the Cmp function conserves equality, + // then they could be linted on, but I don't know if we can check + // for that. + + // ByKey, + // ByCmp, +} +impl SortingKind { + /// The name of the stable version of this kind of sort + fn stable_name(&self) -> &str { + match self { + SortingKind::Vanilla => "sort", + // SortingKind::ByKey => "sort_by_key", + // SortingKind::ByCmp => "sort_by", + } + } + /// The name of the unstable version of this kind of sort + fn unstable_name(&self) -> &str { + match self { + SortingKind::Vanilla => "sort_unstable", + // SortingKind::ByKey => "sort_unstable_by_key", + // SortingKind::ByCmp => "sort_unstable_by", + } + } + /// Takes the name of a function call and returns the kind of sort + /// that corresponds to that function name (or None if it isn't) + fn from_stable_name(name: &str) -> Option<SortingKind> { + match name { + "sort" => Some(SortingKind::Vanilla), + // "sort_by" => Some(SortingKind::ByCmp), + // "sort_by_key" => Some(SortingKind::ByKey), + _ => None, + } + } +} + +/// A detected instance of this lint +struct LintDetection { + slice_name: String, + method: SortingKind, + method_args: String, +} + +fn detect_stable_sort_primitive(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintDetection> { + if_chain! { + if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind; + if let Some(slice) = &args.get(0); + if let Some(method) = SortingKind::from_stable_name(&method_name.ident.name.as_str()); + if is_slice_of_primitives(cx, slice); + then { + let args_str = args.iter().skip(1).map(|arg| Sugg::hir(cx, arg, "..").to_string()).collect::<Vec<String>>().join(", "); + Some(LintDetection { slice_name: Sugg::hir(cx, slice, "..").to_string(), method, method_args: args_str }) + } else { + None + } + } +} + +impl LateLintPass<'_> for StableSortPrimitive { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if let Some(detection) = detect_stable_sort_primitive(cx, expr) { + span_lint_and_sugg( + cx, + STABLE_SORT_PRIMITIVE, + expr.span, + format!( + "Use {} instead of {}", + detection.method.unstable_name(), + detection.method.stable_name() + ) + .as_str(), + "try", + format!( + "{}.{}({})", + detection.slice_name, + detection.method.unstable_name(), + detection.method_args + ), + Applicability::MachineApplicable, + ); + } + } +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 655b1133cf7..c75f8042907 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1378,6 +1378,36 @@ pub fn run_lints(cx: &LateContext<'_>, lints: &[&'static Lint], id: HirId) -> bo }) } +/// Returns true iff the given type is a primitive (a bool or char, any integer or floating-point +/// number type, a str, or an array, slice, or tuple of those types). +pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool { + match ty.kind { + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true, + ty::Ref(_, inner, _) if inner.kind == ty::Str => true, + ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type), + ty::Tuple(inner_types) => inner_types.types().all(is_recursively_primitive_type), + _ => false, + } +} + +/// Returns true iff the given expression is a slice of primitives (as defined in the +/// `is_recursively_primitive_type` function). +pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + let expr_type = cx.typeck_results().expr_ty_adjusted(expr); + match expr_type.kind { + ty::Slice(ref element_type) + | ty::Ref( + _, + ty::TyS { + kind: ty::Slice(ref element_type), + .. + }, + _, + ) => is_recursively_primitive_type(element_type), + _ => false, + } +} + #[macro_export] macro_rules! unwrap_cargo_metadata { ($cx: ident, $lint: ident, $deps: expr) => {{ diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 1879aae77fb..41d06a67881 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2026,6 +2026,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "slow_vector_initialization", }, + Lint { + name: "stable_sort_primitive", + group: "perf", + desc: "use of sort() when sort_unstable() is equivalent", + deprecation: None, + module: "stable_sort_primitive", + }, Lint { name: "string_add", group: "restriction", diff --git a/tests/ui/stable_sort_primitive.fixed b/tests/ui/stable_sort_primitive.fixed new file mode 100644 index 00000000000..8f8f5665931 --- /dev/null +++ b/tests/ui/stable_sort_primitive.fixed @@ -0,0 +1,32 @@ +// run-rustfix +#![warn(clippy::stable_sort_primitive)] + +fn main() { + // positive examples + let mut vec = vec![1, 3, 2]; + vec.sort_unstable(); + let mut vec = vec![false, false, true]; + vec.sort_unstable(); + let mut vec = vec!['a', 'A', 'c']; + vec.sort_unstable(); + let mut vec = vec!["ab", "cd", "ab", "bc"]; + vec.sort_unstable(); + let mut vec = vec![(2, 1), (1, 2), (2, 5)]; + vec.sort_unstable(); + let mut vec = vec![[2, 1], [1, 2], [2, 5]]; + vec.sort_unstable(); + let mut arr = [1, 3, 2]; + arr.sort_unstable(); + // Negative examples: behavior changes if made unstable + let mut vec = vec![1, 3, 2]; + vec.sort_by_key(|i| i / 2); + vec.sort_by(|a, b| (a + b).cmp(&b)); + // negative examples - Not of a primitive type + let mut vec_of_complex = vec![String::from("hello"), String::from("world!")]; + vec_of_complex.sort(); + vec_of_complex.sort_by_key(String::len); + let mut vec = vec![(String::from("hello"), String::from("world"))]; + vec.sort(); + let mut vec = vec![[String::from("hello"), String::from("world")]]; + vec.sort(); +} diff --git a/tests/ui/stable_sort_primitive.rs b/tests/ui/stable_sort_primitive.rs new file mode 100644 index 00000000000..f9bd9779067 --- /dev/null +++ b/tests/ui/stable_sort_primitive.rs @@ -0,0 +1,32 @@ +// run-rustfix +#![warn(clippy::stable_sort_primitive)] + +fn main() { + // positive examples + let mut vec = vec![1, 3, 2]; + vec.sort(); + let mut vec = vec![false, false, true]; + vec.sort(); + let mut vec = vec!['a', 'A', 'c']; + vec.sort(); + let mut vec = vec!["ab", "cd", "ab", "bc"]; + vec.sort(); + let mut vec = vec![(2, 1), (1, 2), (2, 5)]; + vec.sort(); + let mut vec = vec![[2, 1], [1, 2], [2, 5]]; + vec.sort(); + let mut arr = [1, 3, 2]; + arr.sort(); + // Negative examples: behavior changes if made unstable + let mut vec = vec![1, 3, 2]; + vec.sort_by_key(|i| i / 2); + vec.sort_by(|a, b| (a + b).cmp(&b)); + // negative examples - Not of a primitive type + let mut vec_of_complex = vec![String::from("hello"), String::from("world!")]; + vec_of_complex.sort(); + vec_of_complex.sort_by_key(String::len); + let mut vec = vec![(String::from("hello"), String::from("world"))]; + vec.sort(); + let mut vec = vec![[String::from("hello"), String::from("world")]]; + vec.sort(); +} diff --git a/tests/ui/stable_sort_primitive.stderr b/tests/ui/stable_sort_primitive.stderr new file mode 100644 index 00000000000..b0b729ede48 --- /dev/null +++ b/tests/ui/stable_sort_primitive.stderr @@ -0,0 +1,46 @@ +error: Use sort_unstable instead of sort + --> $DIR/stable_sort_primitive.rs:7:5 + | +LL | vec.sort(); + | ^^^^^^^^^^ help: try: `vec.sort_unstable()` + | + = note: `-D clippy::stable-sort-primitive` implied by `-D warnings` + +error: Use sort_unstable instead of sort + --> $DIR/stable_sort_primitive.rs:9:5 + | +LL | vec.sort(); + | ^^^^^^^^^^ help: try: `vec.sort_unstable()` + +error: Use sort_unstable instead of sort + --> $DIR/stable_sort_primitive.rs:11:5 + | +LL | vec.sort(); + | ^^^^^^^^^^ help: try: `vec.sort_unstable()` + +error: Use sort_unstable instead of sort + --> $DIR/stable_sort_primitive.rs:13:5 + | +LL | vec.sort(); + | ^^^^^^^^^^ help: try: `vec.sort_unstable()` + +error: Use sort_unstable instead of sort + --> $DIR/stable_sort_primitive.rs:15:5 + | +LL | vec.sort(); + | ^^^^^^^^^^ help: try: `vec.sort_unstable()` + +error: Use sort_unstable instead of sort + --> $DIR/stable_sort_primitive.rs:17:5 + | +LL | vec.sort(); + | ^^^^^^^^^^ help: try: `vec.sort_unstable()` + +error: Use sort_unstable instead of sort + --> $DIR/stable_sort_primitive.rs:19:5 + | +LL | arr.sort(); + | ^^^^^^^^^^ help: try: `arr.sort_unstable()` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index c017d1cf9a4..31c2ba0f9c5 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -1,5 +1,7 @@ // run-rustfix +#![allow(clippy::stable_sort_primitive)] + use std::cmp::Reverse; fn unnecessary_sort_by() { diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index 1929c72b2f2..a3c8ae468ed 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -1,5 +1,7 @@ // run-rustfix +#![allow(clippy::stable_sort_primitive)] + use std::cmp::Reverse; fn unnecessary_sort_by() { diff --git a/tests/ui/unnecessary_sort_by.stderr b/tests/ui/unnecessary_sort_by.stderr index 903b6e5099c..70c6cf0a3b6 100644 --- a/tests/ui/unnecessary_sort_by.stderr +++ b/tests/ui/unnecessary_sort_by.stderr @@ -1,5 +1,5 @@ error: use Vec::sort here instead - --> $DIR/unnecessary_sort_by.rs:12:5 + --> $DIR/unnecessary_sort_by.rs:14:5 | LL | vec.sort_by(|a, b| a.cmp(b)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort()` @@ -7,37 +7,37 @@ LL | vec.sort_by(|a, b| a.cmp(b)); = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` error: use Vec::sort here instead - --> $DIR/unnecessary_sort_by.rs:13:5 + --> $DIR/unnecessary_sort_by.rs:15:5 | LL | vec.sort_unstable_by(|a, b| a.cmp(b)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable()` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:14:5 + --> $DIR/unnecessary_sort_by.rs:16:5 | LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&a| (a + 5).abs())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:15:5 + --> $DIR/unnecessary_sort_by.rs:17:5 | LL | vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|&a| id(-a))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:17:5 + --> $DIR/unnecessary_sort_by.rs:19:5 | LL | vec.sort_by(|a, b| b.cmp(a)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse(b))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:18:5 + --> $DIR/unnecessary_sort_by.rs:20:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|&b| Reverse((b + 5).abs()))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:19:5 + --> $DIR/unnecessary_sort_by.rs:21:5 | LL | vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|&b| Reverse(id(-b)))` From e9677105bf85a2b0c57e8d67d2ed22a286333033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com> Date: Sun, 2 Aug 2020 00:00:00 +0000 Subject: [PATCH 346/526] try_err: Consider Try impl for Poll when generating suggestions There are two different implementation of Try trait for Poll type; Poll<Result<T, E>> and Poll<Option<Result<T, E>>>. Take them into account when generating suggestions. For example, for Err(e)? suggest either return Poll::Ready(Err(e)) or return Poll::Ready(Some(Err(e))) as appropriate. --- clippy_lints/src/try_err.rs | 112 +++++++++++++++++++++++++------- clippy_lints/src/utils/paths.rs | 2 +- tests/ui/try_err.fixed | 21 ++++++ tests/ui/try_err.rs | 21 ++++++ tests/ui/try_err.stderr | 30 +++++++-- 5 files changed, 155 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/try_err.rs b/clippy_lints/src/try_err.rs index d3b351f30ef..3bd73d9f21a 100644 --- a/clippy_lints/src/try_err.rs +++ b/clippy_lints/src/try_err.rs @@ -1,10 +1,13 @@ -use crate::utils::{match_qpath, paths, snippet, snippet_with_macro_callsite, span_lint_and_sugg}; +use crate::utils::{ + is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet, snippet_with_macro_callsite, + span_lint_and_sugg, +}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Arm, Expr, ExprKind, MatchSource}; +use rustc_hir::{Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -65,19 +68,39 @@ impl<'tcx> LateLintPass<'tcx> for TryErr { if let Some(ref err_arg) = err_args.get(0); if let ExprKind::Path(ref err_fun_path) = err_fun.kind; if match_qpath(err_fun_path, &paths::RESULT_ERR); - if let Some(return_type) = find_err_return_type(cx, &expr.kind); - + if let Some(return_ty) = find_return_type(cx, &expr.kind); then { - let err_type = cx.typeck_results().expr_ty(err_arg); + let prefix; + let suffix; + let err_ty; + + if let Some(ty) = result_error_type(cx, return_ty) { + prefix = "Err("; + suffix = ")"; + err_ty = ty; + } else if let Some(ty) = poll_result_error_type(cx, return_ty) { + prefix = "Poll::Ready(Err("; + suffix = "))"; + err_ty = ty; + } else if let Some(ty) = poll_option_result_error_type(cx, return_ty) { + prefix = "Poll::Ready(Some(Err("; + suffix = ")))"; + err_ty = ty; + } else { + return; + }; + + let expr_err_ty = cx.typeck_results().expr_ty(err_arg); + let origin_snippet = if err_arg.span.from_expansion() { snippet_with_macro_callsite(cx, err_arg.span, "_") } else { snippet(cx, err_arg.span, "_") }; - let suggestion = if err_type == return_type { - format!("return Err({})", origin_snippet) + let suggestion = if err_ty == expr_err_ty { + format!("return {}{}{}", prefix, origin_snippet, suffix) } else { - format!("return Err({}.into())", origin_snippet) + format!("return {}{}.into(){}", prefix, origin_snippet, suffix) }; span_lint_and_sugg( @@ -94,27 +117,68 @@ impl<'tcx> LateLintPass<'tcx> for TryErr { } } -// In order to determine whether to suggest `.into()` or not, we need to find the error type the -// function returns. To do that, we look for the From::from call (see tree above), and capture -// its output type. -fn find_err_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> Option<Ty<'tcx>> { +/// Finds function return type by examining return expressions in match arms. +fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> Option<Ty<'tcx>> { if let ExprKind::Match(_, ref arms, MatchSource::TryDesugar) = expr { - arms.iter().find_map(|ty| find_err_return_type_arm(cx, ty)) - } else { - None + for arm in arms.iter() { + if let ExprKind::Ret(Some(ref ret)) = arm.body.kind { + return Some(cx.typeck_results().expr_ty(ret)); + } + } } + None } -// Check for From::from in one of the match arms. -fn find_err_return_type_arm<'tcx>(cx: &LateContext<'tcx>, arm: &'tcx Arm<'_>) -> Option<Ty<'tcx>> { +/// Extracts the error type from Result<T, E>. +fn result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> { if_chain! { - if let ExprKind::Ret(Some(ref err_ret)) = arm.body.kind; - if let ExprKind::Call(ref from_error_path, ref from_error_args) = err_ret.kind; - if let ExprKind::Path(ref from_error_fn) = from_error_path.kind; - if match_qpath(from_error_fn, &paths::TRY_FROM_ERROR); - if let Some(from_error_arg) = from_error_args.get(0); + if let ty::Adt(_, subst) = ty.kind; + if is_type_diagnostic_item(cx, ty, sym!(result_type)); + let err_ty = subst.type_at(1); then { - Some(cx.typeck_results().expr_ty(from_error_arg)) + Some(err_ty) + } else { + None + } + } +} + +/// Extracts the error type from Poll<Result<T, E>>. +fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> { + if_chain! { + if let ty::Adt(def, subst) = ty.kind; + if match_def_path(cx, def.did, &paths::POLL); + let ready_ty = subst.type_at(0); + + if let ty::Adt(ready_def, ready_subst) = ready_ty.kind; + if cx.tcx.is_diagnostic_item(sym!(result_type), ready_def.did); + let err_ty = ready_subst.type_at(1); + + then { + Some(err_ty) + } else { + None + } + } +} + +/// Extracts the error type from Poll<Option<Result<T, E>>>. +fn poll_option_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> { + if_chain! { + if let ty::Adt(def, subst) = ty.kind; + if match_def_path(cx, def.did, &paths::POLL); + let ready_ty = subst.type_at(0); + + if let ty::Adt(ready_def, ready_subst) = ready_ty.kind; + if cx.tcx.is_diagnostic_item(sym!(option_type), ready_def.did); + let some_ty = ready_subst.type_at(0); + + if let ty::Adt(some_def, some_subst) = some_ty.kind; + if cx.tcx.is_diagnostic_item(sym!(result_type), some_def.did); + let err_ty = some_subst.type_at(1); + + then { + Some(err_ty) } else { None } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index a515ee29c82..923b319d777 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -80,6 +80,7 @@ pub const PATH: [&str; 3] = ["std", "path", "Path"]; pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"]; pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"]; pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; +pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"]; pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; @@ -129,7 +130,6 @@ pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"]; pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"]; pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"]; -pub const TRY_FROM_ERROR: [&str; 4] = ["std", "ops", "Try", "from_error"]; pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"]; pub const TRY_INTO_TRAIT: [&str; 3] = ["core", "convert", "TryInto"]; pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"]; diff --git a/tests/ui/try_err.fixed b/tests/ui/try_err.fixed index 29d9139d3e3..9e77dcd8731 100644 --- a/tests/ui/try_err.fixed +++ b/tests/ui/try_err.fixed @@ -6,6 +6,9 @@ #[macro_use] extern crate macro_rules; +use std::io; +use std::task::Poll; + // Tests that a simple case works // Should flag `Err(err)?` pub fn basic_test() -> Result<i32, i32> { @@ -104,3 +107,21 @@ pub fn macro_inside(fail: bool) -> Result<i32, String> { } Ok(0) } + +pub fn poll_write(n: usize) -> Poll<io::Result<usize>> { + if n == 0 { + return Poll::Ready(Err(io::ErrorKind::WriteZero.into())) + } else if n == 1 { + return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))) + }; + + Poll::Ready(Ok(n)) +} + +pub fn poll_next(ready: bool) -> Poll<Option<io::Result<()>>> { + if !ready { + return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into()))) + } + + Poll::Ready(None) +} diff --git a/tests/ui/try_err.rs b/tests/ui/try_err.rs index 5e85d091a2a..41bcb0a189e 100644 --- a/tests/ui/try_err.rs +++ b/tests/ui/try_err.rs @@ -6,6 +6,9 @@ #[macro_use] extern crate macro_rules; +use std::io; +use std::task::Poll; + // Tests that a simple case works // Should flag `Err(err)?` pub fn basic_test() -> Result<i32, i32> { @@ -104,3 +107,21 @@ pub fn macro_inside(fail: bool) -> Result<i32, String> { } Ok(0) } + +pub fn poll_write(n: usize) -> Poll<io::Result<usize>> { + if n == 0 { + Err(io::ErrorKind::WriteZero)? + } else if n == 1 { + Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))? + }; + + Poll::Ready(Ok(n)) +} + +pub fn poll_next(ready: bool) -> Poll<Option<io::Result<()>>> { + if !ready { + Err(io::ErrorKind::NotFound)? + } + + Poll::Ready(None) +} diff --git a/tests/ui/try_err.stderr b/tests/ui/try_err.stderr index 21e9d4048a5..3f1cbc17e72 100644 --- a/tests/ui/try_err.stderr +++ b/tests/ui/try_err.stderr @@ -1,5 +1,5 @@ error: returning an `Err(_)` with the `?` operator - --> $DIR/try_err.rs:15:9 + --> $DIR/try_err.rs:18:9 | LL | Err(err)?; | ^^^^^^^^^ help: try this: `return Err(err)` @@ -11,28 +11,46 @@ LL | #![deny(clippy::try_err)] | ^^^^^^^^^^^^^^^ error: returning an `Err(_)` with the `?` operator - --> $DIR/try_err.rs:25:9 + --> $DIR/try_err.rs:28:9 | LL | Err(err)?; | ^^^^^^^^^ help: try this: `return Err(err.into())` error: returning an `Err(_)` with the `?` operator - --> $DIR/try_err.rs:45:17 + --> $DIR/try_err.rs:48:17 | LL | Err(err)?; | ^^^^^^^^^ help: try this: `return Err(err)` error: returning an `Err(_)` with the `?` operator - --> $DIR/try_err.rs:64:17 + --> $DIR/try_err.rs:67:17 | LL | Err(err)?; | ^^^^^^^^^ help: try this: `return Err(err.into())` error: returning an `Err(_)` with the `?` operator - --> $DIR/try_err.rs:103:9 + --> $DIR/try_err.rs:106:9 | LL | Err(foo!())?; | ^^^^^^^^^^^^ help: try this: `return Err(foo!())` -error: aborting due to 5 previous errors +error: returning an `Err(_)` with the `?` operator + --> $DIR/try_err.rs:113:9 + | +LL | Err(io::ErrorKind::WriteZero)? + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Err(io::ErrorKind::WriteZero.into()))` + +error: returning an `Err(_)` with the `?` operator + --> $DIR/try_err.rs:115:9 + | +LL | Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))? + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error")))` + +error: returning an `Err(_)` with the `?` operator + --> $DIR/try_err.rs:123:9 + | +LL | Err(io::ErrorKind::NotFound)? + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into())))` + +error: aborting due to 8 previous errors From 0ccdf2913a335c4f0b34098f84baeeb3fc852255 Mon Sep 17 00:00:00 2001 From: Cameron Steffen <cam.steffen94@gmail.com> Date: Mon, 3 Aug 2020 16:23:20 -0500 Subject: [PATCH 347/526] Remove obsolete known problems unnecessary_fold --- clippy_lints/src/methods/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 9edcdd979ff..ff8da6b4015 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1052,8 +1052,7 @@ declare_clippy_lint! { /// /// **Why is this bad?** Readability. /// - /// **Known problems:** False positive in pattern guards. Will be resolved once - /// non-lexical lifetimes are stable. + /// **Known problems:** None. /// /// **Example:** /// ```rust From 542740c2eceff2369b2ac44e891a37313dd1785c Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Tue, 4 Aug 2020 17:53:29 -0700 Subject: [PATCH 348/526] Run cargo dev fmt --- clippy_lints/src/stable_sort_primitive.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/stable_sort_primitive.rs b/clippy_lints/src/stable_sort_primitive.rs index c48da004a60..cd7056620a2 100644 --- a/clippy_lints/src/stable_sort_primitive.rs +++ b/clippy_lints/src/stable_sort_primitive.rs @@ -43,30 +43,30 @@ declare_lint_pass!(StableSortPrimitive => [STABLE_SORT_PRIMITIVE]); /// The three "kinds" of sorts enum SortingKind { Vanilla, - // The other kinds of lint are currently commented out because they - // can map distinct values to equal ones. If the key function is - // provably one-to-one, or if the Cmp function conserves equality, - // then they could be linted on, but I don't know if we can check - // for that. + /* The other kinds of lint are currently commented out because they + * can map distinct values to equal ones. If the key function is + * provably one-to-one, or if the Cmp function conserves equality, + * then they could be linted on, but I don't know if we can check + * for that. */ - // ByKey, - // ByCmp, + /* ByKey, + * ByCmp, */ } impl SortingKind { /// The name of the stable version of this kind of sort fn stable_name(&self) -> &str { match self { SortingKind::Vanilla => "sort", - // SortingKind::ByKey => "sort_by_key", - // SortingKind::ByCmp => "sort_by", + /* SortingKind::ByKey => "sort_by_key", + * SortingKind::ByCmp => "sort_by", */ } } /// The name of the unstable version of this kind of sort fn unstable_name(&self) -> &str { match self { SortingKind::Vanilla => "sort_unstable", - // SortingKind::ByKey => "sort_unstable_by_key", - // SortingKind::ByCmp => "sort_unstable_by", + /* SortingKind::ByKey => "sort_unstable_by_key", + * SortingKind::ByCmp => "sort_unstable_by", */ } } /// Takes the name of a function call and returns the kind of sort From 1e8ada3cab5470a4f2070c0aa9d1a94922476621 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Sat, 18 Jul 2020 23:28:31 +0900 Subject: [PATCH 349/526] Add lint `same_item_push` --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 3 + clippy_lints/src/loops.rs | 265 +++++++++++++++++++++++++++++++++ src/lintlist/mod.rs | 7 + tests/ui/same_item_push.rs | 77 ++++++++++ tests/ui/same_item_push.stderr | 35 +++++ 6 files changed, 388 insertions(+) create mode 100644 tests/ui/same_item_push.rs create mode 100644 tests/ui/same_item_push.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 43d83d978b8..fbc783f1c2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1687,6 +1687,7 @@ Released 2018-09-13 [`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn [`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges [`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition +[`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 26aff6af8cd..2bd5ae0ed98 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -610,6 +610,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::WHILE_IMMUTABLE_CONDITION, &loops::WHILE_LET_LOOP, &loops::WHILE_LET_ON_ITERATOR, + &loops::SAME_ITEM_PUSH, ¯o_use::MACRO_USE_IMPORTS, &main_recursion::MAIN_RECURSION, &manual_async_fn::MANUAL_ASYNC_FN, @@ -1405,6 +1406,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&repeat_once::REPEAT_ONCE), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), + LintId::of(&loops::SAME_ITEM_PUSH), LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), @@ -1543,6 +1545,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(®ex::TRIVIAL_REGEX), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), + LintId::of(&loops::SAME_ITEM_PUSH), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6359c20040c..48891a59c00 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -419,6 +419,39 @@ declare_clippy_lint! { "variables used within while expression are not mutated in the body" } +declare_clippy_lint! { + /// **What it does:** Checks whether a for loop is being used to push a constant + /// value into a Vec. + /// + /// **Why is this bad?** This kind of operation can be expressed more succinctly with + /// `vec![item;SIZE]` or `vec.resize(NEW_SIZE, item)` and using these alternatives may also + /// have better performance. + /// **Known problems:** None + /// + /// **Example:** + /// ```rust + /// let item1 = 2; + /// let item2 = 3; + /// let mut vec: Vec<u8> = Vec::new(); + /// for _ in 0..20 { + /// vec.push(item1); + /// } + /// for _ in 0..30 { + /// vec.push(item2); + /// } + /// ``` + /// could be written as + /// ```rust + /// let item1 = 2; + /// let item2 = 3; + /// let mut vec: Vec<u8> = vec![item1; 20]; + /// vec.resize(20 + 30, item2); + /// ``` + pub SAME_ITEM_PUSH, + style, + "the same item is pushed inside of a for loop" +} + declare_lint_pass!(Loops => [ MANUAL_MEMCPY, NEEDLESS_RANGE_LOOP, @@ -435,6 +468,7 @@ declare_lint_pass!(Loops => [ NEVER_LOOP, MUT_RANGE_BOUND, WHILE_IMMUTABLE_CONDITION, + SAME_ITEM_PUSH, ]); impl<'tcx> LateLintPass<'tcx> for Loops { @@ -740,6 +774,7 @@ fn check_for_loop<'tcx>( check_for_loop_over_map_kv(cx, pat, arg, body, expr); check_for_mut_range_bound(cx, arg, body); detect_manual_memcpy(cx, pat, arg, body, expr); + detect_same_item_push(cx, pat, arg, body, expr); } fn same_var<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, var: HirId) -> bool { @@ -1016,6 +1051,236 @@ fn detect_manual_memcpy<'tcx>( } } +// Delegate that traverses expression and detects mutable variables being used +struct UsesMutableDelegate { + found_mutable: bool, +} + +impl<'tcx> Delegate<'tcx> for UsesMutableDelegate { + fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: ConsumeMode) {} + + fn borrow(&mut self, _: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { + // Mutable variable is found + if let ty::BorrowKind::MutBorrow = bk { + self.found_mutable = true; + } + } + + fn mutate(&mut self, _: &PlaceWithHirId<'tcx>) {} +} + +// Uses UsesMutableDelegate to find mutable variables in an expression expr +fn has_mutable_variables<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { + let mut delegate = UsesMutableDelegate { found_mutable: false }; + let def_id = expr.hir_id.owner.to_def_id(); + cx.tcx.infer_ctxt().enter(|infcx| { + ExprUseVisitor::new( + &mut delegate, + &infcx, + def_id.expect_local(), + cx.param_env, + cx.tables(), + ).walk_expr(expr); + }); + + delegate.found_mutable +} + +// Scans for the usage of the for loop pattern +struct ForPatternVisitor<'a, 'tcx> { + found_pattern: bool, + // Pattern that we are searching for + for_pattern: &'a Pat<'tcx>, + cx: &'a LateContext<'tcx>, +} + +impl<'a, 'tcx> Visitor<'tcx> for ForPatternVisitor<'a, 'tcx> { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + // Recursively explore an expression until a ExprKind::Path is found + match &expr.kind { + ExprKind::Array(expr_list) | ExprKind::MethodCall(_, _, expr_list, _) | ExprKind::Tup(expr_list) => { + for expr in *expr_list { + self.visit_expr(expr) + } + }, + ExprKind::Binary(_, lhs_expr, rhs_expr) => { + self.visit_expr(lhs_expr); + self.visit_expr(rhs_expr); + }, + ExprKind::Box(expr) + | ExprKind::Unary(_, expr) + | ExprKind::Cast(expr, _) + | ExprKind::Type(expr, _) + | ExprKind::AddrOf(_, _, expr) + | ExprKind::Struct(_, _, Some(expr)) => self.visit_expr(expr), + _ => { + // Exploration cannot continue ... calculate the hir_id of the current + // expr assuming it is a Path + if let Some(hir_id) = var_def_id(self.cx, &expr) { + // Pattern is found + if hir_id == self.for_pattern.hir_id { + self.found_pattern = true; + } + // If the for loop pattern is a tuple, determine whether the current + // expr is inside that tuple pattern + if let PatKind::Tuple(pat_list, _) = &self.for_pattern.kind { + let hir_id_list: Vec<HirId> = pat_list.iter().map(|p| p.hir_id).collect(); + if hir_id_list.contains(&hir_id) { + self.found_pattern = true; + } + } + } + }, + } + } + + // This is triggered by walk_expr() for the case of vec.push(pat) + fn visit_qpath(&mut self, qpath: &'tcx QPath<'_>, _: HirId, _: Span) { + if_chain! { + if let QPath::Resolved(_, path) = qpath; + if let Res::Local(hir_id) = &path.res; + then { + if *hir_id == self.for_pattern.hir_id{ + self.found_pattern = true; + } + + if let PatKind::Tuple(pat_list, _) = &self.for_pattern.kind { + let hir_id_list: Vec<HirId> = pat_list.iter().map(|p| p.hir_id).collect(); + if hir_id_list.contains(&hir_id) { + self.found_pattern = true; + } + } + } + } + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } +} + +// Scans the body of the for loop and determines whether lint should be given +struct SameItemPushVisitor<'a, 'tcx> { + should_lint: bool, + // this field holds the last vec push operation visited, which should be the only push seen + vec_push: Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)>, + cx: &'a LateContext<'tcx>, +} + +impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + match &expr.kind { + // Non-determinism may occur ... don't give a lint + ExprKind::Loop(_, _, _) | ExprKind::Match(_, _, _) => self.should_lint = false, + ExprKind::Block(block, _) => self.visit_block(block), + _ => {}, + } + } + + fn visit_block(&mut self, b: &'tcx Block<'_>) { + for stmt in b.stmts.iter() { + self.visit_stmt(stmt); + } + } + + fn visit_stmt(&mut self, s: &'tcx Stmt<'_>) { + let vec_push_option = get_vec_push(self.cx, s); + if vec_push_option.is_none() { + // Current statement is not a push so visit inside + match &s.kind { + StmtKind::Expr(expr) | StmtKind::Semi(expr) => self.visit_expr(&expr), + _ => {}, + } + } else { + // Current statement is a push ...check whether another + // push had been previously done + if self.vec_push.is_none() { + self.vec_push = vec_push_option; + } else { + // There are multiple pushes ... don't lint + self.should_lint = false; + } + } + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } +} + +// Given some statement, determine if that statement is a push on a Vec. If it is, return +// the Vec being pushed into and the item being pushed +fn get_vec_push<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> { + if_chain! { + // Extract method being called + if let StmtKind::Semi(semi_stmt) = &stmt.kind; + if let ExprKind::MethodCall(path, _, args, _) = &semi_stmt.kind; + // Figure out the parameters for the method call + if let Some(self_expr) = args.get(0); + if let Some(pushed_item) = args.get(1); + // Check that the method being called is push() on a Vec + if match_type(cx, cx.tables().expr_ty(self_expr), &paths::VEC); + if path.ident.name.as_str() == "push"; + then { + return Some((self_expr, pushed_item)) + } + } + None +} + +/// Detects for loop pushing the same item into a Vec +fn detect_same_item_push<'tcx>( + cx: &LateContext<'tcx>, + pat: &'tcx Pat<'_>, + _: &'tcx Expr<'_>, + body: &'tcx Expr<'_>, + _: &'tcx Expr<'_>, +) { + // Determine whether it is safe to lint the body + let mut same_item_push_visitor = SameItemPushVisitor { + should_lint: true, + vec_push: None, + cx, + }; + walk_expr(&mut same_item_push_visitor, body); + if same_item_push_visitor.should_lint { + if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push { + // Make sure that the push does not involve possibly mutating values + if !has_mutable_variables(cx, pushed_item) { + // Walk through the expression being pushed and make sure that it + // does not contain the for loop pattern + let mut for_pat_visitor = ForPatternVisitor { + found_pattern: false, + for_pattern: pat, + cx, + }; + walk_expr(&mut for_pat_visitor, pushed_item); + + if !for_pat_visitor.found_pattern { + let vec_str = snippet(cx, vec.span, ""); + let item_str = snippet(cx, pushed_item.span, ""); + + span_lint_and_help( + cx, + SAME_ITEM_PUSH, + vec.span, + "it looks like the same item is being pushed into this Vec", + None, + &format!( + "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})", + item_str, vec_str, item_str + ), + ) + } + } + } + } +} + /// Checks for looping over a range and then indexing a sequence with it. /// The iteratee must be a range literal. #[allow(clippy::too_many_lines)] diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index a08d7da6dcb..1b10226c930 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1935,6 +1935,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "copies", }, + Lint { + name: "same_item_push", + group: "style", + desc: "default lint description", + deprecation: None, + module: "same_item_push", + }, Lint { name: "search_is_some", group: "complexity", diff --git a/tests/ui/same_item_push.rs b/tests/ui/same_item_push.rs new file mode 100644 index 00000000000..e3a5a647f76 --- /dev/null +++ b/tests/ui/same_item_push.rs @@ -0,0 +1,77 @@ +#![warn(clippy::same_item_push)] + +fn mutate_increment(x: &mut u8) -> u8 { + *x += 1; + *x +} + +fn increment(x: u8) -> u8 { + x + 1 +} + +fn main() { + // Test for basic case + let mut spaces = Vec::with_capacity(10); + for _ in 0..10 { + spaces.push(vec![b' ']); + } + + let mut vec2: Vec<u8> = Vec::new(); + let item = 2; + for _ in 5..=20 { + vec2.push(item); + } + + let mut vec3: Vec<u8> = Vec::new(); + for _ in 0..15 { + let item = 2; + vec3.push(item); + } + + let mut vec4: Vec<u8> = Vec::new(); + for _ in 0..15 { + vec4.push(13); + } + + // Suggestion should not be given as pushed variable can mutate + let mut vec5: Vec<u8> = Vec::new(); + let mut item: u8 = 2; + for _ in 0..30 { + vec5.push(mutate_increment(&mut item)); + } + + let mut vec6: Vec<u8> = Vec::new(); + let mut item: u8 = 2; + let mut item2 = &mut mutate_increment(&mut item); + for _ in 0..30 { + vec6.push(mutate_increment(item2)); + } + + let mut vec7: Vec<usize> = Vec::new(); + for (a, b) in [0, 1, 4, 9, 16].iter().enumerate() { + vec7.push(a); + } + + let mut vec8: Vec<u8> = Vec::new(); + for i in 0..30 { + vec8.push(increment(i)); + } + + let mut vec9: Vec<u8> = Vec::new(); + for i in 0..30 { + vec9.push(i + i * i); + } + + // Suggestion should not be given as there are multiple pushes that are not the same + let mut vec10: Vec<u8> = Vec::new(); + let item: u8 = 2; + for _ in 0..30 { + vec10.push(item); + vec10.push(item * 2); + } + + // Suggestion should not be given as Vec is not involved + for _ in 0..5 { + println!("Same Item Push"); + } +} diff --git a/tests/ui/same_item_push.stderr b/tests/ui/same_item_push.stderr new file mode 100644 index 00000000000..559cc450b9d --- /dev/null +++ b/tests/ui/same_item_push.stderr @@ -0,0 +1,35 @@ +error: it looks like the same item is being pushed into this Vec + --> $DIR/same_item_push.rs:16:9 + | +LL | spaces.push(vec![b' ']); + | ^^^^^^ + | + = note: `-D clippy::same-item-push` implied by `-D warnings` + = help: try using vec![<[_]>::into_vec(box [$($x),+]);SIZE] or spaces.resize(NEW_SIZE, <[_]>::into_vec(box [$($x),+])) + +error: it looks like the same item is being pushed into this Vec + --> $DIR/same_item_push.rs:22:9 + | +LL | vec2.push(item); + | ^^^^ + | + = help: try using vec![item;SIZE] or vec2.resize(NEW_SIZE, item) + +error: it looks like the same item is being pushed into this Vec + --> $DIR/same_item_push.rs:28:9 + | +LL | vec3.push(item); + | ^^^^ + | + = help: try using vec![item;SIZE] or vec3.resize(NEW_SIZE, item) + +error: it looks like the same item is being pushed into this Vec + --> $DIR/same_item_push.rs:33:9 + | +LL | vec4.push(13); + | ^^^^ + | + = help: try using vec![13;SIZE] or vec4.resize(NEW_SIZE, 13) + +error: aborting due to 4 previous errors + From 161f47510076d36722546c3541a546f9b724fadd Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Sun, 19 Jul 2020 23:43:35 +0900 Subject: [PATCH 350/526] Add test case for `same_item_push` --- clippy_lints/src/loops.rs | 1 + tests/ui/same_item_push.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 48891a59c00..1c2f1225497 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1114,6 +1114,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ForPatternVisitor<'a, 'tcx> { | ExprKind::Cast(expr, _) | ExprKind::Type(expr, _) | ExprKind::AddrOf(_, _, expr) + | ExprKind::Field(expr, _) | ExprKind::Struct(_, _, Some(expr)) => self.visit_expr(expr), _ => { // Exploration cannot continue ... calculate the hir_id of the current diff --git a/tests/ui/same_item_push.rs b/tests/ui/same_item_push.rs index e3a5a647f76..4bb5e73ff0d 100644 --- a/tests/ui/same_item_push.rs +++ b/tests/ui/same_item_push.rs @@ -74,4 +74,16 @@ fn main() { for _ in 0..5 { println!("Same Item Push"); } + + struct A { + kind: u32, + } + let mut vec_a: Vec<A> = Vec::new(); + for i in 0..30 { + vec_a.push(A{kind: i}); + } + let mut vec12: Vec<u8> = Vec::new(); + for a in vec_a { + vec12.push(2u8.pow(a.kind)); + } } From 2beb9090d1b9adb2b0930da511bf1750e570905b Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Mon, 20 Jul 2020 22:40:31 +0900 Subject: [PATCH 351/526] Rename TypeckTables to TypeckResults --- clippy_lints/src/loops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 1c2f1225497..766c68df623 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1079,7 +1079,7 @@ fn has_mutable_variables<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> &infcx, def_id.expect_local(), cx.param_env, - cx.tables(), + cx.typeck_results(), ).walk_expr(expr); }); @@ -1224,7 +1224,7 @@ fn get_vec_push<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) -> Option<(& if let Some(self_expr) = args.get(0); if let Some(pushed_item) = args.get(1); // Check that the method being called is push() on a Vec - if match_type(cx, cx.tables().expr_ty(self_expr), &paths::VEC); + if match_type(cx, cx.typeck_results().expr_ty(self_expr), &paths::VEC); if path.ident.name.as_str() == "push"; then { return Some((self_expr, pushed_item)) From 1543e117cc7459bef2b57389503f0f526a903f45 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Mon, 20 Jul 2020 22:52:30 +0900 Subject: [PATCH 352/526] cargo dev update_lints --- clippy_lints/src/lib.rs | 6 +++--- src/lintlist/mod.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2bd5ae0ed98..308868fc90a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -607,10 +607,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::NEEDLESS_COLLECT, &loops::NEEDLESS_RANGE_LOOP, &loops::NEVER_LOOP, + &loops::SAME_ITEM_PUSH, &loops::WHILE_IMMUTABLE_CONDITION, &loops::WHILE_LET_LOOP, &loops::WHILE_LET_ON_ITERATOR, - &loops::SAME_ITEM_PUSH, ¯o_use::MACRO_USE_IMPORTS, &main_recursion::MAIN_RECURSION, &manual_async_fn::MANUAL_ASYNC_FN, @@ -1293,6 +1293,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::NEEDLESS_COLLECT), LintId::of(&loops::NEEDLESS_RANGE_LOOP), LintId::of(&loops::NEVER_LOOP), + LintId::of(&loops::SAME_ITEM_PUSH), LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), LintId::of(&loops::WHILE_LET_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), @@ -1406,7 +1407,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&repeat_once::REPEAT_ONCE), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), - LintId::of(&loops::SAME_ITEM_PUSH), LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), @@ -1495,6 +1495,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::FOR_KV_MAP), LintId::of(&loops::NEEDLESS_RANGE_LOOP), + LintId::of(&loops::SAME_ITEM_PUSH), LintId::of(&loops::WHILE_LET_ON_ITERATOR), LintId::of(&main_recursion::MAIN_RECURSION), LintId::of(&manual_async_fn::MANUAL_ASYNC_FN), @@ -1545,7 +1546,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(®ex::TRIVIAL_REGEX), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), - LintId::of(&loops::SAME_ITEM_PUSH), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 1b10226c930..1f79e44049f 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1938,9 +1938,9 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ Lint { name: "same_item_push", group: "style", - desc: "default lint description", + desc: "the same item is pushed inside of a for loop", deprecation: None, - module: "same_item_push", + module: "loops", }, Lint { name: "search_is_some", From 14a4e3bcc8082b0323886ae15365ea2424b512cf Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Tue, 21 Jul 2020 08:15:13 +0900 Subject: [PATCH 353/526] Fix a lint message --- clippy_lints/src/loops.rs | 11 ++++++----- tests/ui/same_item_push.stderr | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 766c68df623..8ca67cae0e9 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -3,9 +3,10 @@ use crate::utils::paths; use crate::utils::sugg::Sugg; use crate::utils::usage::{is_unused, mutated_variables}; use crate::utils::{ - get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, - is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, last_path_segment, match_trait_method, - match_type, match_var, multispan_sugg, qpath_res, snippet, snippet_opt, snippet_with_applicability, span_lint, + get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, + implements_trait, is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, + last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, qpath_res, + snippet, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, SpanlessEq, }; use if_chain::if_chain; @@ -1262,8 +1263,8 @@ fn detect_same_item_push<'tcx>( walk_expr(&mut for_pat_visitor, pushed_item); if !for_pat_visitor.found_pattern { - let vec_str = snippet(cx, vec.span, ""); - let item_str = snippet(cx, pushed_item.span, ""); + let vec_str = snippet_with_macro_callsite(cx, vec.span, ""); + let item_str = snippet_with_macro_callsite(cx, pushed_item.span, ""); span_lint_and_help( cx, diff --git a/tests/ui/same_item_push.stderr b/tests/ui/same_item_push.stderr index 559cc450b9d..ddc5d48cd41 100644 --- a/tests/ui/same_item_push.stderr +++ b/tests/ui/same_item_push.stderr @@ -5,7 +5,7 @@ LL | spaces.push(vec![b' ']); | ^^^^^^ | = note: `-D clippy::same-item-push` implied by `-D warnings` - = help: try using vec![<[_]>::into_vec(box [$($x),+]);SIZE] or spaces.resize(NEW_SIZE, <[_]>::into_vec(box [$($x),+])) + = help: try using vec![vec![b' '];SIZE] or spaces.resize(NEW_SIZE, vec![b' ']) error: it looks like the same item is being pushed into this Vec --> $DIR/same_item_push.rs:22:9 From b7ceb4d3d7ed3ea7039caf803073e86ad3643e21 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Tue, 21 Jul 2020 08:25:11 +0900 Subject: [PATCH 354/526] rustfmt --- clippy_lints/src/loops.rs | 5 +++-- tests/ui/same_item_push.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8ca67cae0e9..3a1fbc4bfed 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1081,7 +1081,8 @@ fn has_mutable_variables<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> def_id.expect_local(), cx.param_env, cx.typeck_results(), - ).walk_expr(expr); + ) + .walk_expr(expr); }); delegate.found_mutable @@ -1271,7 +1272,7 @@ fn detect_same_item_push<'tcx>( SAME_ITEM_PUSH, vec.span, "it looks like the same item is being pushed into this Vec", - None, + None, &format!( "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})", item_str, vec_str, item_str diff --git a/tests/ui/same_item_push.rs b/tests/ui/same_item_push.rs index 4bb5e73ff0d..ff1088f86f6 100644 --- a/tests/ui/same_item_push.rs +++ b/tests/ui/same_item_push.rs @@ -80,7 +80,7 @@ fn main() { } let mut vec_a: Vec<A> = Vec::new(); for i in 0..30 { - vec_a.push(A{kind: i}); + vec_a.push(A { kind: i }); } let mut vec12: Vec<u8> = Vec::new(); for a in vec_a { From 228f668282daab05ec20adbbdeb227e923d10864 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Wed, 22 Jul 2020 22:11:31 +0900 Subject: [PATCH 355/526] Use `mutated_variables` --- clippy_lints/src/loops.rs | 38 +------------------------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3a1fbc4bfed..86952c10dfc 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1052,42 +1052,6 @@ fn detect_manual_memcpy<'tcx>( } } -// Delegate that traverses expression and detects mutable variables being used -struct UsesMutableDelegate { - found_mutable: bool, -} - -impl<'tcx> Delegate<'tcx> for UsesMutableDelegate { - fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: ConsumeMode) {} - - fn borrow(&mut self, _: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { - // Mutable variable is found - if let ty::BorrowKind::MutBorrow = bk { - self.found_mutable = true; - } - } - - fn mutate(&mut self, _: &PlaceWithHirId<'tcx>) {} -} - -// Uses UsesMutableDelegate to find mutable variables in an expression expr -fn has_mutable_variables<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { - let mut delegate = UsesMutableDelegate { found_mutable: false }; - let def_id = expr.hir_id.owner.to_def_id(); - cx.tcx.infer_ctxt().enter(|infcx| { - ExprUseVisitor::new( - &mut delegate, - &infcx, - def_id.expect_local(), - cx.param_env, - cx.typeck_results(), - ) - .walk_expr(expr); - }); - - delegate.found_mutable -} - // Scans for the usage of the for loop pattern struct ForPatternVisitor<'a, 'tcx> { found_pattern: bool, @@ -1253,7 +1217,7 @@ fn detect_same_item_push<'tcx>( if same_item_push_visitor.should_lint { if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push { // Make sure that the push does not involve possibly mutating values - if !has_mutable_variables(cx, pushed_item) { + if mutated_variables(pushed_item, cx).map_or(false, |mutvars| mutvars.is_empty()) { // Walk through the expression being pushed and make sure that it // does not contain the for loop pattern let mut for_pat_visitor = ForPatternVisitor { From e48685edef9889d7c0ae391cf050f878d228ae25 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Wed, 22 Jul 2020 23:22:17 +0900 Subject: [PATCH 356/526] Just check if it contains `_` in `for pat` --- clippy_lints/src/loops.rs | 87 +-------------------------------------- 1 file changed, 1 insertion(+), 86 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 86952c10dfc..3104f0c137e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1052,82 +1052,6 @@ fn detect_manual_memcpy<'tcx>( } } -// Scans for the usage of the for loop pattern -struct ForPatternVisitor<'a, 'tcx> { - found_pattern: bool, - // Pattern that we are searching for - for_pattern: &'a Pat<'tcx>, - cx: &'a LateContext<'tcx>, -} - -impl<'a, 'tcx> Visitor<'tcx> for ForPatternVisitor<'a, 'tcx> { - type Map = Map<'tcx>; - - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - // Recursively explore an expression until a ExprKind::Path is found - match &expr.kind { - ExprKind::Array(expr_list) | ExprKind::MethodCall(_, _, expr_list, _) | ExprKind::Tup(expr_list) => { - for expr in *expr_list { - self.visit_expr(expr) - } - }, - ExprKind::Binary(_, lhs_expr, rhs_expr) => { - self.visit_expr(lhs_expr); - self.visit_expr(rhs_expr); - }, - ExprKind::Box(expr) - | ExprKind::Unary(_, expr) - | ExprKind::Cast(expr, _) - | ExprKind::Type(expr, _) - | ExprKind::AddrOf(_, _, expr) - | ExprKind::Field(expr, _) - | ExprKind::Struct(_, _, Some(expr)) => self.visit_expr(expr), - _ => { - // Exploration cannot continue ... calculate the hir_id of the current - // expr assuming it is a Path - if let Some(hir_id) = var_def_id(self.cx, &expr) { - // Pattern is found - if hir_id == self.for_pattern.hir_id { - self.found_pattern = true; - } - // If the for loop pattern is a tuple, determine whether the current - // expr is inside that tuple pattern - if let PatKind::Tuple(pat_list, _) = &self.for_pattern.kind { - let hir_id_list: Vec<HirId> = pat_list.iter().map(|p| p.hir_id).collect(); - if hir_id_list.contains(&hir_id) { - self.found_pattern = true; - } - } - } - }, - } - } - - // This is triggered by walk_expr() for the case of vec.push(pat) - fn visit_qpath(&mut self, qpath: &'tcx QPath<'_>, _: HirId, _: Span) { - if_chain! { - if let QPath::Resolved(_, path) = qpath; - if let Res::Local(hir_id) = &path.res; - then { - if *hir_id == self.for_pattern.hir_id{ - self.found_pattern = true; - } - - if let PatKind::Tuple(pat_list, _) = &self.for_pattern.kind { - let hir_id_list: Vec<HirId> = pat_list.iter().map(|p| p.hir_id).collect(); - if hir_id_list.contains(&hir_id) { - self.found_pattern = true; - } - } - } - } - } - - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::None - } -} - // Scans the body of the for loop and determines whether lint should be given struct SameItemPushVisitor<'a, 'tcx> { should_lint: bool, @@ -1218,16 +1142,7 @@ fn detect_same_item_push<'tcx>( if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push { // Make sure that the push does not involve possibly mutating values if mutated_variables(pushed_item, cx).map_or(false, |mutvars| mutvars.is_empty()) { - // Walk through the expression being pushed and make sure that it - // does not contain the for loop pattern - let mut for_pat_visitor = ForPatternVisitor { - found_pattern: false, - for_pattern: pat, - cx, - }; - walk_expr(&mut for_pat_visitor, pushed_item); - - if !for_pat_visitor.found_pattern { + if let PatKind::Wild = pat.kind { let vec_str = snippet_with_macro_callsite(cx, vec.span, ""); let item_str = snippet_with_macro_callsite(cx, pushed_item.span, ""); From 610d4e3c8b1bfa27e059043554f4156fe1254142 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Wed, 5 Aug 2020 23:10:30 +0900 Subject: [PATCH 357/526] rustfmt --- clippy_lints/src/loops.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3104f0c137e..5c918ff648f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -3,11 +3,11 @@ use crate::utils::paths; use crate::utils::sugg::Sugg; use crate::utils::usage::{is_unused, mutated_variables}; use crate::utils::{ - get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, - implements_trait, is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, - last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, qpath_res, - snippet, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite, span_lint, - span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, SpanlessEq, + get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, + is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, last_path_segment, match_trait_method, + match_type, match_var, multispan_sugg, qpath_res, snippet, snippet_opt, snippet_with_applicability, + snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, + SpanlessEq, }; use if_chain::if_chain; use rustc_ast::ast; From 50a86d492718f2ad5e653575d19324205fa007f1 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 6 Aug 2020 00:40:11 +0200 Subject: [PATCH 358/526] enable #[allow(clippy::unsafe_derive_deserialize)] --- clippy_lints/src/derive.rs | 8 +++++--- tests/ui/unsafe_derive_deserialize.rs | 10 ++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 08d8100a885..80a06758982 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,7 +1,7 @@ use crate::utils::paths; use crate::utils::{ - get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, - span_lint_and_then, + get_trait_def_id, is_allowed, is_automatically_derived, is_copy, match_path, span_lint_and_help, + span_lint_and_note, span_lint_and_then, }; use if_chain::if_chain; use rustc_hir::def_id::DefId; @@ -354,7 +354,9 @@ fn check_unsafe_derive_deserialize<'tcx>( if_chain! { if match_path(&trait_ref.path, &paths::SERDE_DESERIALIZE); if let ty::Adt(def, _) = ty.kind; - if def.did.is_local(); + if let Some(local_def_id) = def.did.as_local(); + let adt_hir_id = cx.tcx.hir().as_local_hir_id(local_def_id); + if !is_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id); if cx.tcx.inherent_impls(def.did) .iter() .map(|imp_did| item_from_def_id(cx, *imp_did)) diff --git a/tests/ui/unsafe_derive_deserialize.rs b/tests/ui/unsafe_derive_deserialize.rs index 7bee9c499e1..690d705573d 100644 --- a/tests/ui/unsafe_derive_deserialize.rs +++ b/tests/ui/unsafe_derive_deserialize.rs @@ -57,4 +57,14 @@ impl E { #[derive(Deserialize)] pub struct F {} +// Check that we honor the `allow` attribute on the ADT +#[allow(clippy::unsafe_derive_deserialize)] +#[derive(Deserialize)] +pub struct G {} +impl G { + pub fn unsafe_block(&self) { + unsafe {} + } +} + fn main() {} From 0abc4833e5dc8ec4da48d5b25e1d0df81cceec4d Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Thu, 6 Aug 2020 02:42:40 +0200 Subject: [PATCH 359/526] Lint .min(x).max(y) with x < y Fixes #5854 --- clippy_lints/src/minmax.rs | 52 ++++++++++++++++++++++++-------------- tests/ui/min_max.rs | 14 ++++++++++ tests/ui/min_max.stderr | 32 ++++++++++++++++++++++- 3 files changed, 78 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index dae39aaf5e2..1f798fd1120 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -18,6 +18,10 @@ declare_clippy_lint! { /// ```ignore /// min(0, max(100, x)) /// ``` + /// or + /// ```ignore + /// x.max(100).min(0) + /// ``` /// It will always be equal to `0`. Probably the author meant to clamp the value /// between 0 and 100, but has erroneously swapped `min` and `max`. pub MIN_MAX, @@ -60,25 +64,35 @@ enum MinMax { } fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant, &'a Expr<'a>)> { - if let ExprKind::Call(ref path, ref args) = expr.kind { - if let ExprKind::Path(ref qpath) = path.kind { - cx.typeck_results() - .qpath_res(qpath, path.hir_id) - .opt_def_id() - .and_then(|def_id| { - if match_def_path(cx, def_id, &paths::CMP_MIN) { - fetch_const(cx, args, MinMax::Min) - } else if match_def_path(cx, def_id, &paths::CMP_MAX) { - fetch_const(cx, args, MinMax::Max) - } else { - None - } - }) - } else { - None - } - } else { - None + match expr.kind { + ExprKind::Call(ref path, ref args) => { + if let ExprKind::Path(ref qpath) = path.kind { + cx.typeck_results() + .qpath_res(qpath, path.hir_id) + .opt_def_id() + .and_then(|def_id| { + if match_def_path(cx, def_id, &paths::CMP_MIN) { + fetch_const(cx, args, MinMax::Min) + } else if match_def_path(cx, def_id, &paths::CMP_MAX) { + fetch_const(cx, args, MinMax::Max) + } else { + None + } + }) + } else { + None + } + }, + ExprKind::MethodCall(ref path, _, ref args, _) => { + if path.ident.as_str() == sym!(max).as_str() { + fetch_const(cx, args, MinMax::Max) + } else if path.ident.as_str() == sym!(min).as_str() { + fetch_const(cx, args, MinMax::Min) + } else { + None + } + }, + _ => None, } } diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index 8307d4b3019..90ec5676493 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -30,4 +30,18 @@ fn main() { max(min(s, "Apple"), "Zoo"); max("Apple", min(s, "Zoo")); // ok + + x.min(1).max(3); + x.max(3).min(1); + + x.max(1).min(3); // ok + x.min(3).max(1); // ok + + max(x.min(1), 3); + min(x.max(1), 3); // ok + + s.max("Zoo").min("Apple"); + s.min("Apple").max("Zoo"); + + s.min("Zoo").max("Apple"); // ok } diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index b552c137f7c..653946dc025 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -42,5 +42,35 @@ error: this `min`/`max` combination leads to constant result LL | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: this `min`/`max` combination leads to constant result + --> $DIR/min_max.rs:34:5 + | +LL | x.min(1).max(3); + | ^^^^^^^^^^^^^^^ + +error: this `min`/`max` combination leads to constant result + --> $DIR/min_max.rs:35:5 + | +LL | x.max(3).min(1); + | ^^^^^^^^^^^^^^^ + +error: this `min`/`max` combination leads to constant result + --> $DIR/min_max.rs:40:5 + | +LL | max(x.min(1), 3); + | ^^^^^^^^^^^^^^^^ + +error: this `min`/`max` combination leads to constant result + --> $DIR/min_max.rs:43:5 + | +LL | s.max("Zoo").min("Apple"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this `min`/`max` combination leads to constant result + --> $DIR/min_max.rs:44:5 + | +LL | s.min("Apple").max("Zoo"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors From e0a4988fcc716e349fd801d98182c0d984a2ee3f Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Tue, 4 Aug 2020 20:23:14 +0200 Subject: [PATCH 360/526] Lint against `Self` as an arbitrary self type Fixes #5861 --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 ++ clippy_lints/src/needless_fn_self_type.rs | 64 +++++++++++++++++++++++ clippy_lints/src/trait_bounds.rs | 2 +- src/lintlist/mod.rs | 7 +++ tests/ui/needless_fn_self_type.rs | 26 +++++++++ tests/ui/needless_fn_self_type.stderr | 11 ++++ 7 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/needless_fn_self_type.rs create mode 100644 tests/ui/needless_fn_self_type.rs create mode 100644 tests/ui/needless_fn_self_type.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index bfe896d5efa..179ecee03da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1622,6 +1622,7 @@ Released 2018-09-13 [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect [`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main +[`needless_fn_self_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_fn_self_type [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 81864340f1a..80c85e70e89 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -254,6 +254,7 @@ mod needless_bool; mod needless_borrow; mod needless_borrowed_ref; mod needless_continue; +mod needless_fn_self_type; mod needless_pass_by_value; mod needless_update; mod neg_cmp_op_on_partial_ord; @@ -722,6 +723,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &needless_borrow::NEEDLESS_BORROW, &needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, &needless_continue::NEEDLESS_CONTINUE, + &needless_fn_self_type::NEEDLESS_FN_SELF_TYPE, &needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, &needless_update::NEEDLESS_UPDATE, &neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, @@ -1027,6 +1029,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box items_after_statements::ItemsAfterStatements); store.register_early_pass(|| box precedence::Precedence); store.register_early_pass(|| box needless_continue::NeedlessContinue); + store.register_early_pass(|| box needless_fn_self_type::NeedlessFnSelfType); store.register_early_pass(|| box redundant_static_lifetimes::RedundantStaticLifetimes); store.register_late_pass(|| box cargo_common_metadata::CargoCommonMetadata); store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions); @@ -1374,6 +1377,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&needless_bool::BOOL_COMPARISON), LintId::of(&needless_bool::NEEDLESS_BOOL), LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), + LintId::of(&needless_fn_self_type::NEEDLESS_FN_SELF_TYPE), LintId::of(&needless_update::NEEDLESS_UPDATE), LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), LintId::of(&neg_multiply::NEG_MULTIPLY), @@ -1534,6 +1538,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), LintId::of(&misc_early::REDUNDANT_PATTERN), LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED), + LintId::of(&needless_fn_self_type::NEEDLESS_FN_SELF_TYPE), LintId::of(&neg_multiply::NEG_MULTIPLY), LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), diff --git a/clippy_lints/src/needless_fn_self_type.rs b/clippy_lints/src/needless_fn_self_type.rs new file mode 100644 index 00000000000..050a03467fb --- /dev/null +++ b/clippy_lints/src/needless_fn_self_type.rs @@ -0,0 +1,64 @@ +use crate::utils::span_lint_and_help; +use if_chain::if_chain; +use rustc_ast::ast::{Param, TyKind}; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** The lint checks for `self` fn fn parameters that explicitly + /// specify the `Self`-type explicitly + /// **Why is this bad?** Increases the amount and decreases the readability of code + /// + /// **Known problems:** None + /// + /// **Example:** + /// ```rust + /// impl ValType { + /// pub fn bytes(self: Self) -> usize { + /// match self { + /// Self::I32 | Self::F32 => 4, + /// Self::I64 | Self::F64 => 8, + /// } + /// } + /// } + /// ``` + /// + /// Could be rewritten as + /// + /// ```rust + /// impl ValType { + /// pub fn bytes(self) -> usize { + /// match self { + /// Self::I32 | Self::F32 => 4, + /// Self::I64 | Self::F64 => 8, + /// } + /// } + /// } + /// ``` + pub NEEDLESS_FN_SELF_TYPE, + style, + "type of `self` parameter is already by default `Self`" +} + +declare_lint_pass!(NeedlessFnSelfType => [NEEDLESS_FN_SELF_TYPE]); + +impl EarlyLintPass for NeedlessFnSelfType { + fn check_param(&mut self, cx: &EarlyContext<'_>, p: &Param) { + if_chain! { + if p.is_self(); + if let TyKind::Path(None, path) = &p.ty.kind; + if let Some(segment) = path.segments.first(); + if segment.ident.as_str() == sym!(Self).as_str(); + then { + span_lint_and_help( + cx, + NEEDLESS_FN_SELF_TYPE, + p.ty.span, + "the type of the `self` parameter is already by default `Self`", + None, + "consider removing the type specification", + ); + } + } + } +} diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 06631f89f27..d4acf8df46d 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -50,7 +50,7 @@ declare_clippy_lint! { /// fn func<T: Clone + Default>(arg: T) {} /// ``` /// or - /// /// + /// /// ```rust /// fn func<T>(arg: T) where T: Clone + Default {} /// ``` diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index b64c6e54409..a20e410f79b 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1501,6 +1501,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "doc", }, + Lint { + name: "needless_fn_self_type", + group: "style", + desc: "type of `self` parameter is already by default `Self`", + deprecation: None, + module: "needless_fn_self_type", + }, Lint { name: "needless_lifetimes", group: "complexity", diff --git a/tests/ui/needless_fn_self_type.rs b/tests/ui/needless_fn_self_type.rs new file mode 100644 index 00000000000..12bb84582ff --- /dev/null +++ b/tests/ui/needless_fn_self_type.rs @@ -0,0 +1,26 @@ +#![warn(clippy::style, clippy::needless_fn_self_type)] + +pub enum ValType { + I32, + I64, + F32, + F64, +} + +impl ValType { + pub fn bytes_bad(self: Self) -> usize { + match self { + Self::I32 | Self::F32 => 4, + Self::I64 | Self::F64 => 8, + } + } + + pub fn bytes_good(self) -> usize { + match self { + Self::I32 | Self::F32 => 4, + Self::I64 | Self::F64 => 8, + } + } +} + +fn main() {} diff --git a/tests/ui/needless_fn_self_type.stderr b/tests/ui/needless_fn_self_type.stderr new file mode 100644 index 00000000000..703705c7842 --- /dev/null +++ b/tests/ui/needless_fn_self_type.stderr @@ -0,0 +1,11 @@ +error: the type of the `self` parameter is already by default `Self` + --> $DIR/needless_fn_self_type.rs:11:28 + | +LL | pub fn bytes_bad(self: Self) -> usize { + | ^^^^ + | + = note: `-D clippy::needless-fn-self-type` implied by `-D warnings` + = help: consider removing the type specification + +error: aborting due to previous error + From 737f62cb6eaa5eca23701dbbe8d63465e1c4843b Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Tue, 4 Aug 2020 21:07:35 +0200 Subject: [PATCH 361/526] fix doc --- clippy_lints/src/needless_fn_self_type.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/clippy_lints/src/needless_fn_self_type.rs b/clippy_lints/src/needless_fn_self_type.rs index 050a03467fb..b71f2fbbd46 100644 --- a/clippy_lints/src/needless_fn_self_type.rs +++ b/clippy_lints/src/needless_fn_self_type.rs @@ -13,6 +13,13 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// enum ValType { + /// I32, + /// I64, + /// F32, + /// F64, + /// } + /// /// impl ValType { /// pub fn bytes(self: Self) -> usize { /// match self { @@ -26,6 +33,13 @@ declare_clippy_lint! { /// Could be rewritten as /// /// ```rust + /// enum ValType { + /// I32, + /// I64, + /// F32, + /// F64, + /// } + /// /// impl ValType { /// pub fn bytes(self) -> usize { /// match self { From d635b76eaf3435f9bdce1dcbdd315b0e770493f0 Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Wed, 5 Aug 2020 02:59:30 +0200 Subject: [PATCH 362/526] adopt comments from review --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 10 +- .../src/needless_arbitrary_self_type.rs | 114 ++++++++++++++++++ clippy_lints/src/needless_fn_self_type.rs | 78 ------------ src/lintlist/mod.rs | 14 +-- tests/ui/needless_arbitrary_self_type.rs | 58 +++++++++ tests/ui/needless_arbitrary_self_type.stderr | 46 +++++++ tests/ui/needless_fn_self_type.rs | 26 ---- tests/ui/needless_fn_self_type.stderr | 11 -- 9 files changed, 231 insertions(+), 128 deletions(-) create mode 100644 clippy_lints/src/needless_arbitrary_self_type.rs delete mode 100644 clippy_lints/src/needless_fn_self_type.rs create mode 100644 tests/ui/needless_arbitrary_self_type.rs create mode 100644 tests/ui/needless_arbitrary_self_type.stderr delete mode 100644 tests/ui/needless_fn_self_type.rs delete mode 100644 tests/ui/needless_fn_self_type.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 179ecee03da..3f470f601ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1616,13 +1616,13 @@ Released 2018-09-13 [`mutex_atomic`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_atomic [`mutex_integer`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_integer [`naive_bytecount`]: https://rust-lang.github.io/rust-clippy/master/index.html#naive_bytecount +[`needless_arbitrary_self_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_arbitrary_self_type [`needless_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool [`needless_borrow`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow [`needless_borrowed_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect [`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main -[`needless_fn_self_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_fn_self_type [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 80c85e70e89..3c39de1abf1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -250,11 +250,11 @@ mod mut_mut; mod mut_reference; mod mutable_debug_assertion; mod mutex_atomic; +mod needless_arbitrary_self_type; mod needless_bool; mod needless_borrow; mod needless_borrowed_ref; mod needless_continue; -mod needless_fn_self_type; mod needless_pass_by_value; mod needless_update; mod neg_cmp_op_on_partial_ord; @@ -718,12 +718,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL, &mutex_atomic::MUTEX_ATOMIC, &mutex_atomic::MUTEX_INTEGER, + &needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE, &needless_bool::BOOL_COMPARISON, &needless_bool::NEEDLESS_BOOL, &needless_borrow::NEEDLESS_BORROW, &needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, &needless_continue::NEEDLESS_CONTINUE, - &needless_fn_self_type::NEEDLESS_FN_SELF_TYPE, &needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, &needless_update::NEEDLESS_UPDATE, &neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, @@ -1029,7 +1029,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box items_after_statements::ItemsAfterStatements); store.register_early_pass(|| box precedence::Precedence); store.register_early_pass(|| box needless_continue::NeedlessContinue); - store.register_early_pass(|| box needless_fn_self_type::NeedlessFnSelfType); + store.register_early_pass(|| box needless_arbitrary_self_type::NeedlessArbitrarySelfType); store.register_early_pass(|| box redundant_static_lifetimes::RedundantStaticLifetimes); store.register_late_pass(|| box cargo_common_metadata::CargoCommonMetadata); store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions); @@ -1374,10 +1374,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&mut_key::MUTABLE_KEY_TYPE), LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED), LintId::of(&mutex_atomic::MUTEX_ATOMIC), + LintId::of(&needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), LintId::of(&needless_bool::BOOL_COMPARISON), LintId::of(&needless_bool::NEEDLESS_BOOL), LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), - LintId::of(&needless_fn_self_type::NEEDLESS_FN_SELF_TYPE), LintId::of(&needless_update::NEEDLESS_UPDATE), LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), LintId::of(&neg_multiply::NEG_MULTIPLY), @@ -1538,7 +1538,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), LintId::of(&misc_early::REDUNDANT_PATTERN), LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED), - LintId::of(&needless_fn_self_type::NEEDLESS_FN_SELF_TYPE), LintId::of(&neg_multiply::NEG_MULTIPLY), LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), @@ -1607,6 +1606,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&misc::SHORT_CIRCUIT_STATEMENT), LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN), LintId::of(&misc_early::ZERO_PREFIXED_LITERAL), + LintId::of(&needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), LintId::of(&needless_bool::BOOL_COMPARISON), LintId::of(&needless_bool::NEEDLESS_BOOL), LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), diff --git a/clippy_lints/src/needless_arbitrary_self_type.rs b/clippy_lints/src/needless_arbitrary_self_type.rs new file mode 100644 index 00000000000..1b23ecd9ad2 --- /dev/null +++ b/clippy_lints/src/needless_arbitrary_self_type.rs @@ -0,0 +1,114 @@ +use crate::utils::span_lint_and_sugg; +use if_chain::if_chain; +use rustc_ast::ast::{BindingMode, Lifetime, Mutability, Param, PatKind, Path, TyKind}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::kw; +use rustc_span::Span; + +declare_clippy_lint! { + /// **What it does:** The lint checks for `self` in fn parameters that + /// specify the `Self`-type explicitly + /// **Why is this bad?** Increases the amount and decreases the readability of code + /// + /// **Known problems:** None + /// + /// **Example:** + /// ```rust + /// enum ValType { + /// I32, + /// I64, + /// F32, + /// F64, + /// } + /// + /// impl ValType { + /// pub fn bytes(self: Self) -> usize { + /// match self { + /// Self::I32 | Self::F32 => 4, + /// Self::I64 | Self::F64 => 8, + /// } + /// } + /// } + /// ``` + /// + /// Could be rewritten as + /// + /// ```rust + /// enum ValType { + /// I32, + /// I64, + /// F32, + /// F64, + /// } + /// + /// impl ValType { + /// pub fn bytes(self) -> usize { + /// match self { + /// Self::I32 | Self::F32 => 4, + /// Self::I64 | Self::F64 => 8, + /// } + /// } + /// } + /// ``` + pub NEEDLESS_ARBITRARY_SELF_TYPE, + complexity, + "type of `self` parameter is already by default `Self`" +} + +declare_lint_pass!(NeedlessArbitrarySelfType => [NEEDLESS_ARBITRARY_SELF_TYPE]); + +enum Mode { + Ref(Option<Lifetime>), + Value, +} + +fn check_param_inner(cx: &EarlyContext<'_>, path: &Path, span: Span, binding_mode: &Mode, mutbl: Mutability) { + if_chain! { + if let [segment] = &path.segments[..]; + if segment.ident.name == kw::SelfUpper; + then { + let self_param = match (binding_mode, mutbl) { + (Mode::Ref(None), Mutability::Mut) => "&mut self".to_string(), + (Mode::Ref(Some(lifetime)), Mutability::Mut) => format!("&{} mut self", &lifetime.ident.name), + (Mode::Ref(None), Mutability::Not) => "&self".to_string(), + (Mode::Ref(Some(lifetime)), Mutability::Not) => format!("&{} self", &lifetime.ident.name), + (Mode::Value, Mutability::Mut) => "mut self".to_string(), + (Mode::Value, Mutability::Not) => "self".to_string(), + }; + + span_lint_and_sugg( + cx, + NEEDLESS_ARBITRARY_SELF_TYPE, + span, + "the type of the `self` parameter is arbitrary", + "consider to change this parameter to", + self_param, + Applicability::MachineApplicable, + ) + } + } +} + +impl EarlyLintPass for NeedlessArbitrarySelfType { + fn check_param(&mut self, cx: &EarlyContext<'_>, p: &Param) { + if !p.is_self() { + return; + } + + match &p.ty.kind { + TyKind::Path(None, path) => { + if let PatKind::Ident(BindingMode::ByValue(mutbl), _, _) = p.pat.kind { + check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl) + } + }, + TyKind::Rptr(lifetime, mut_ty) => { + if let TyKind::Path(None, path) = &mut_ty.ty.kind { + check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl) + } + }, + _ => {}, + } + } +} diff --git a/clippy_lints/src/needless_fn_self_type.rs b/clippy_lints/src/needless_fn_self_type.rs deleted file mode 100644 index b71f2fbbd46..00000000000 --- a/clippy_lints/src/needless_fn_self_type.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::utils::span_lint_and_help; -use if_chain::if_chain; -use rustc_ast::ast::{Param, TyKind}; -use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// **What it does:** The lint checks for `self` fn fn parameters that explicitly - /// specify the `Self`-type explicitly - /// **Why is this bad?** Increases the amount and decreases the readability of code - /// - /// **Known problems:** None - /// - /// **Example:** - /// ```rust - /// enum ValType { - /// I32, - /// I64, - /// F32, - /// F64, - /// } - /// - /// impl ValType { - /// pub fn bytes(self: Self) -> usize { - /// match self { - /// Self::I32 | Self::F32 => 4, - /// Self::I64 | Self::F64 => 8, - /// } - /// } - /// } - /// ``` - /// - /// Could be rewritten as - /// - /// ```rust - /// enum ValType { - /// I32, - /// I64, - /// F32, - /// F64, - /// } - /// - /// impl ValType { - /// pub fn bytes(self) -> usize { - /// match self { - /// Self::I32 | Self::F32 => 4, - /// Self::I64 | Self::F64 => 8, - /// } - /// } - /// } - /// ``` - pub NEEDLESS_FN_SELF_TYPE, - style, - "type of `self` parameter is already by default `Self`" -} - -declare_lint_pass!(NeedlessFnSelfType => [NEEDLESS_FN_SELF_TYPE]); - -impl EarlyLintPass for NeedlessFnSelfType { - fn check_param(&mut self, cx: &EarlyContext<'_>, p: &Param) { - if_chain! { - if p.is_self(); - if let TyKind::Path(None, path) = &p.ty.kind; - if let Some(segment) = path.segments.first(); - if segment.ident.as_str() == sym!(Self).as_str(); - then { - span_lint_and_help( - cx, - NEEDLESS_FN_SELF_TYPE, - p.ty.span, - "the type of the `self` parameter is already by default `Self`", - None, - "consider removing the type specification", - ); - } - } - } -} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index a20e410f79b..91761e8a86d 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1459,6 +1459,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "bytecount", }, + Lint { + name: "needless_arbitrary_self_type", + group: "complexity", + desc: "type of `self` parameter is already by default `Self`", + deprecation: None, + module: "needless_arbitrary_self_type", + }, Lint { name: "needless_bool", group: "complexity", @@ -1501,13 +1508,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "doc", }, - Lint { - name: "needless_fn_self_type", - group: "style", - desc: "type of `self` parameter is already by default `Self`", - deprecation: None, - module: "needless_fn_self_type", - }, Lint { name: "needless_lifetimes", group: "complexity", diff --git a/tests/ui/needless_arbitrary_self_type.rs b/tests/ui/needless_arbitrary_self_type.rs new file mode 100644 index 00000000000..da4bbcf4a7d --- /dev/null +++ b/tests/ui/needless_arbitrary_self_type.rs @@ -0,0 +1,58 @@ +#![warn(clippy::needless_arbitrary_self_type)] + +pub enum ValType { + A, + B, +} + +impl ValType { + pub fn bad(self: Self) { + unimplemented!(); + } + + pub fn good(self) { + unimplemented!(); + } + + pub fn mut_bad(mut self: Self) { + unimplemented!(); + } + + pub fn mut_good(mut self) { + unimplemented!(); + } + + pub fn ref_bad(self: &Self) { + unimplemented!(); + } + + pub fn ref_bad_with_lifetime<'a>(self: &'a Self) { + unimplemented!(); + } + + pub fn ref_good(&self) { + unimplemented!(); + } + + pub fn mut_ref_bad(self: &mut Self) { + unimplemented!(); + } + + pub fn mut_ref_bad_with_lifetime<'a>(self: &'a mut Self) { + unimplemented!(); + } + + pub fn mut_ref_good(&mut self) { + unimplemented!(); + } + + pub fn mut_ref_mut_bad(mut self: &mut Self) { + unimplemented!(); + } + + pub fn mut_ref_mut_ref_good(self: &&mut &mut Self) { + unimplemented!(); + } +} + +fn main() {} diff --git a/tests/ui/needless_arbitrary_self_type.stderr b/tests/ui/needless_arbitrary_self_type.stderr new file mode 100644 index 00000000000..ee803b24071 --- /dev/null +++ b/tests/ui/needless_arbitrary_self_type.stderr @@ -0,0 +1,46 @@ +error: the type of the `self` parameter is arbitrary + --> $DIR/needless_arbitrary_self_type.rs:9:16 + | +LL | pub fn bad(self: Self) { + | ^^^^^^^^^^ help: consider to change this parameter to: `self` + | + = note: `-D clippy::needless-arbitrary-self-type` implied by `-D warnings` + +error: the type of the `self` parameter is arbitrary + --> $DIR/needless_arbitrary_self_type.rs:17:20 + | +LL | pub fn mut_bad(mut self: Self) { + | ^^^^^^^^^^^^^^ help: consider to change this parameter to: `mut self` + +error: the type of the `self` parameter is arbitrary + --> $DIR/needless_arbitrary_self_type.rs:25:20 + | +LL | pub fn ref_bad(self: &Self) { + | ^^^^^^^^^^^ help: consider to change this parameter to: `&self` + +error: the type of the `self` parameter is arbitrary + --> $DIR/needless_arbitrary_self_type.rs:29:38 + | +LL | pub fn ref_bad_with_lifetime<'a>(self: &'a Self) { + | ^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'a self` + +error: the type of the `self` parameter is arbitrary + --> $DIR/needless_arbitrary_self_type.rs:37:24 + | +LL | pub fn mut_ref_bad(self: &mut Self) { + | ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&mut self` + +error: the type of the `self` parameter is arbitrary + --> $DIR/needless_arbitrary_self_type.rs:41:42 + | +LL | pub fn mut_ref_bad_with_lifetime<'a>(self: &'a mut Self) { + | ^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'a mut self` + +error: the type of the `self` parameter is arbitrary + --> $DIR/needless_arbitrary_self_type.rs:49:28 + | +LL | pub fn mut_ref_mut_bad(mut self: &mut Self) { + | ^^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&mut self` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/needless_fn_self_type.rs b/tests/ui/needless_fn_self_type.rs deleted file mode 100644 index 12bb84582ff..00000000000 --- a/tests/ui/needless_fn_self_type.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![warn(clippy::style, clippy::needless_fn_self_type)] - -pub enum ValType { - I32, - I64, - F32, - F64, -} - -impl ValType { - pub fn bytes_bad(self: Self) -> usize { - match self { - Self::I32 | Self::F32 => 4, - Self::I64 | Self::F64 => 8, - } - } - - pub fn bytes_good(self) -> usize { - match self { - Self::I32 | Self::F32 => 4, - Self::I64 | Self::F64 => 8, - } - } -} - -fn main() {} diff --git a/tests/ui/needless_fn_self_type.stderr b/tests/ui/needless_fn_self_type.stderr deleted file mode 100644 index 703705c7842..00000000000 --- a/tests/ui/needless_fn_self_type.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: the type of the `self` parameter is already by default `Self` - --> $DIR/needless_fn_self_type.rs:11:28 - | -LL | pub fn bytes_bad(self: Self) -> usize { - | ^^^^ - | - = note: `-D clippy::needless-fn-self-type` implied by `-D warnings` - = help: consider removing the type specification - -error: aborting due to previous error - From c87d999fa2f8e88f986aa5f4d76b708824e1fd3a Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Wed, 5 Aug 2020 03:37:29 +0200 Subject: [PATCH 363/526] fix ui tests --- tests/ui/extra_unused_lifetimes.rs | 8 ++- tests/ui/extra_unused_lifetimes.stderr | 8 +-- tests/ui/len_without_is_empty.rs | 40 ++++++------- tests/ui/len_without_is_empty.stderr | 8 +-- tests/ui/len_zero.fixed | 20 +++---- tests/ui/len_zero.rs | 20 +++---- tests/ui/needless_arbitrary_self_type.fixed | 61 ++++++++++++++++++++ tests/ui/needless_arbitrary_self_type.rs | 3 + tests/ui/needless_arbitrary_self_type.stderr | 14 ++--- tests/ui/option_map_unit_fn_fixable.fixed | 4 +- tests/ui/option_map_unit_fn_fixable.rs | 4 +- tests/ui/result_map_unit_fn_fixable.fixed | 4 +- tests/ui/result_map_unit_fn_fixable.rs | 4 +- 13 files changed, 134 insertions(+), 64 deletions(-) create mode 100644 tests/ui/needless_arbitrary_self_type.fixed diff --git a/tests/ui/extra_unused_lifetimes.rs b/tests/ui/extra_unused_lifetimes.rs index ddbf4e98c51..150acfbfee7 100644 --- a/tests/ui/extra_unused_lifetimes.rs +++ b/tests/ui/extra_unused_lifetimes.rs @@ -1,4 +1,10 @@ -#![allow(unused, dead_code, clippy::needless_lifetimes, clippy::needless_pass_by_value)] +#![allow( + unused, + dead_code, + clippy::needless_lifetimes, + clippy::needless_pass_by_value, + clippy::needless_arbitrary_self_type +)] #![warn(clippy::extra_unused_lifetimes)] fn empty() {} diff --git a/tests/ui/extra_unused_lifetimes.stderr b/tests/ui/extra_unused_lifetimes.stderr index 16bbb1c037d..ebdb8e74952 100644 --- a/tests/ui/extra_unused_lifetimes.stderr +++ b/tests/ui/extra_unused_lifetimes.stderr @@ -1,5 +1,5 @@ error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:8:14 + --> $DIR/extra_unused_lifetimes.rs:14:14 | LL | fn unused_lt<'a>(x: u8) {} | ^^ @@ -7,19 +7,19 @@ LL | fn unused_lt<'a>(x: u8) {} = note: `-D clippy::extra-unused-lifetimes` implied by `-D warnings` error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:10:25 + --> $DIR/extra_unused_lifetimes.rs:16:25 | LL | fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { | ^^ error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:35:10 + --> $DIR/extra_unused_lifetimes.rs:41:10 | LL | fn x<'a>(&self) {} | ^^ error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:61:22 + --> $DIR/extra_unused_lifetimes.rs:67:22 | LL | fn unused_lt<'a>(x: u8) {} | ^^ diff --git a/tests/ui/len_without_is_empty.rs b/tests/ui/len_without_is_empty.rs index 3ef29dd6388..b5211318a15 100644 --- a/tests/ui/len_without_is_empty.rs +++ b/tests/ui/len_without_is_empty.rs @@ -4,14 +4,14 @@ pub struct PubOne; impl PubOne { - pub fn len(self: &Self) -> isize { + pub fn len(&self) -> isize { 1 } } impl PubOne { // A second impl for this struct -- the error span shouldn't mention this. - pub fn irrelevant(self: &Self) -> bool { + pub fn irrelevant(&self) -> bool { false } } @@ -21,7 +21,7 @@ pub struct PubAllowed; #[allow(clippy::len_without_is_empty)] impl PubAllowed { - pub fn len(self: &Self) -> isize { + pub fn len(&self) -> isize { 1 } } @@ -29,17 +29,17 @@ impl PubAllowed { // No `allow` attribute on this impl block, but that doesn't matter -- we only require one on the // impl containing `len`. impl PubAllowed { - pub fn irrelevant(self: &Self) -> bool { + pub fn irrelevant(&self) -> bool { false } } pub trait PubTraitsToo { - fn len(self: &Self) -> isize; + fn len(&self) -> isize; } impl PubTraitsToo for One { - fn len(self: &Self) -> isize { + fn len(&self) -> isize { 0 } } @@ -47,11 +47,11 @@ impl PubTraitsToo for One { pub struct HasIsEmpty; impl HasIsEmpty { - pub fn len(self: &Self) -> isize { + pub fn len(&self) -> isize { 1 } - fn is_empty(self: &Self) -> bool { + fn is_empty(&self) -> bool { false } } @@ -59,11 +59,11 @@ impl HasIsEmpty { pub struct HasWrongIsEmpty; impl HasWrongIsEmpty { - pub fn len(self: &Self) -> isize { + pub fn len(&self) -> isize { 1 } - pub fn is_empty(self: &Self, x: u32) -> bool { + pub fn is_empty(&self, x: u32) -> bool { false } } @@ -71,7 +71,7 @@ impl HasWrongIsEmpty { struct NotPubOne; impl NotPubOne { - pub fn len(self: &Self) -> isize { + pub fn len(&self) -> isize { // No error; `len` is pub but `NotPubOne` is not exported anyway. 1 } @@ -80,19 +80,19 @@ impl NotPubOne { struct One; impl One { - fn len(self: &Self) -> isize { + fn len(&self) -> isize { // No error; `len` is private; see issue #1085. 1 } } trait TraitsToo { - fn len(self: &Self) -> isize; + fn len(&self) -> isize; // No error; `len` is private; see issue #1085. } impl TraitsToo for One { - fn len(self: &Self) -> isize { + fn len(&self) -> isize { 0 } } @@ -100,11 +100,11 @@ impl TraitsToo for One { struct HasPrivateIsEmpty; impl HasPrivateIsEmpty { - pub fn len(self: &Self) -> isize { + pub fn len(&self) -> isize { 1 } - fn is_empty(self: &Self) -> bool { + fn is_empty(&self) -> bool { false } } @@ -112,16 +112,16 @@ impl HasPrivateIsEmpty { struct Wither; pub trait WithIsEmpty { - fn len(self: &Self) -> isize; - fn is_empty(self: &Self) -> bool; + fn len(&self) -> isize; + fn is_empty(&self) -> bool; } impl WithIsEmpty for Wither { - fn len(self: &Self) -> isize { + fn len(&self) -> isize { 1 } - fn is_empty(self: &Self) -> bool { + fn is_empty(&self) -> bool { false } } diff --git a/tests/ui/len_without_is_empty.stderr b/tests/ui/len_without_is_empty.stderr index 4493b17a4b4..d79c300c074 100644 --- a/tests/ui/len_without_is_empty.stderr +++ b/tests/ui/len_without_is_empty.stderr @@ -2,7 +2,7 @@ error: item `PubOne` has a public `len` method but no corresponding `is_empty` m --> $DIR/len_without_is_empty.rs:6:1 | LL | / impl PubOne { -LL | | pub fn len(self: &Self) -> isize { +LL | | pub fn len(&self) -> isize { LL | | 1 LL | | } LL | | } @@ -14,7 +14,7 @@ error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_e --> $DIR/len_without_is_empty.rs:37:1 | LL | / pub trait PubTraitsToo { -LL | | fn len(self: &Self) -> isize; +LL | | fn len(&self) -> isize; LL | | } | |_^ @@ -22,7 +22,7 @@ error: item `HasIsEmpty` has a public `len` method but a private `is_empty` meth --> $DIR/len_without_is_empty.rs:49:1 | LL | / impl HasIsEmpty { -LL | | pub fn len(self: &Self) -> isize { +LL | | pub fn len(&self) -> isize { LL | | 1 LL | | } ... | @@ -34,7 +34,7 @@ error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is --> $DIR/len_without_is_empty.rs:61:1 | LL | / impl HasWrongIsEmpty { -LL | | pub fn len(self: &Self) -> isize { +LL | | pub fn len(&self) -> isize { LL | | 1 LL | | } ... | diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed index a29b832eb60..d81676a3d9f 100644 --- a/tests/ui/len_zero.fixed +++ b/tests/ui/len_zero.fixed @@ -7,12 +7,12 @@ pub struct One; struct Wither; trait TraitsToo { - fn len(self: &Self) -> isize; + fn len(&self) -> isize; // No error; `len` is private; see issue #1085. } impl TraitsToo for One { - fn len(self: &Self) -> isize { + fn len(&self) -> isize { 0 } } @@ -20,11 +20,11 @@ impl TraitsToo for One { pub struct HasIsEmpty; impl HasIsEmpty { - pub fn len(self: &Self) -> isize { + pub fn len(&self) -> isize { 1 } - fn is_empty(self: &Self) -> bool { + fn is_empty(&self) -> bool { false } } @@ -32,26 +32,26 @@ impl HasIsEmpty { pub struct HasWrongIsEmpty; impl HasWrongIsEmpty { - pub fn len(self: &Self) -> isize { + pub fn len(&self) -> isize { 1 } - pub fn is_empty(self: &Self, x: u32) -> bool { + pub fn is_empty(&self, x: u32) -> bool { false } } pub trait WithIsEmpty { - fn len(self: &Self) -> isize; - fn is_empty(self: &Self) -> bool; + fn len(&self) -> isize; + fn is_empty(&self) -> bool; } impl WithIsEmpty for Wither { - fn len(self: &Self) -> isize { + fn len(&self) -> isize { 1 } - fn is_empty(self: &Self) -> bool { + fn is_empty(&self) -> bool { false } } diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index 8fd0093f4fd..ecdba921a5d 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -7,12 +7,12 @@ pub struct One; struct Wither; trait TraitsToo { - fn len(self: &Self) -> isize; + fn len(&self) -> isize; // No error; `len` is private; see issue #1085. } impl TraitsToo for One { - fn len(self: &Self) -> isize { + fn len(&self) -> isize { 0 } } @@ -20,11 +20,11 @@ impl TraitsToo for One { pub struct HasIsEmpty; impl HasIsEmpty { - pub fn len(self: &Self) -> isize { + pub fn len(&self) -> isize { 1 } - fn is_empty(self: &Self) -> bool { + fn is_empty(&self) -> bool { false } } @@ -32,26 +32,26 @@ impl HasIsEmpty { pub struct HasWrongIsEmpty; impl HasWrongIsEmpty { - pub fn len(self: &Self) -> isize { + pub fn len(&self) -> isize { 1 } - pub fn is_empty(self: &Self, x: u32) -> bool { + pub fn is_empty(&self, x: u32) -> bool { false } } pub trait WithIsEmpty { - fn len(self: &Self) -> isize; - fn is_empty(self: &Self) -> bool; + fn len(&self) -> isize; + fn is_empty(&self) -> bool; } impl WithIsEmpty for Wither { - fn len(self: &Self) -> isize { + fn len(&self) -> isize { 1 } - fn is_empty(self: &Self) -> bool { + fn is_empty(&self) -> bool { false } } diff --git a/tests/ui/needless_arbitrary_self_type.fixed b/tests/ui/needless_arbitrary_self_type.fixed new file mode 100644 index 00000000000..642e48fd131 --- /dev/null +++ b/tests/ui/needless_arbitrary_self_type.fixed @@ -0,0 +1,61 @@ +// run-rustfix + +#![warn(clippy::needless_arbitrary_self_type)] +#![allow(unused_mut, clippy::needless_lifetimes)] + +pub enum ValType { + A, + B, +} + +impl ValType { + pub fn bad(self) { + unimplemented!(); + } + + pub fn good(self) { + unimplemented!(); + } + + pub fn mut_bad(mut self) { + unimplemented!(); + } + + pub fn mut_good(mut self) { + unimplemented!(); + } + + pub fn ref_bad(&self) { + unimplemented!(); + } + + pub fn ref_bad_with_lifetime<'a>(&'a self) { + unimplemented!(); + } + + pub fn ref_good(&self) { + unimplemented!(); + } + + pub fn mut_ref_bad(&mut self) { + unimplemented!(); + } + + pub fn mut_ref_bad_with_lifetime<'a>(&'a mut self) { + unimplemented!(); + } + + pub fn mut_ref_good(&mut self) { + unimplemented!(); + } + + pub fn mut_ref_mut_bad(&mut self) { + unimplemented!(); + } + + pub fn mut_ref_mut_ref_good(self: &&mut &mut Self) { + unimplemented!(); + } +} + +fn main() {} diff --git a/tests/ui/needless_arbitrary_self_type.rs b/tests/ui/needless_arbitrary_self_type.rs index da4bbcf4a7d..178abc341a8 100644 --- a/tests/ui/needless_arbitrary_self_type.rs +++ b/tests/ui/needless_arbitrary_self_type.rs @@ -1,4 +1,7 @@ +// run-rustfix + #![warn(clippy::needless_arbitrary_self_type)] +#![allow(unused_mut, clippy::needless_lifetimes)] pub enum ValType { A, diff --git a/tests/ui/needless_arbitrary_self_type.stderr b/tests/ui/needless_arbitrary_self_type.stderr index ee803b24071..fc21d3d0afd 100644 --- a/tests/ui/needless_arbitrary_self_type.stderr +++ b/tests/ui/needless_arbitrary_self_type.stderr @@ -1,5 +1,5 @@ error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:9:16 + --> $DIR/needless_arbitrary_self_type.rs:12:16 | LL | pub fn bad(self: Self) { | ^^^^^^^^^^ help: consider to change this parameter to: `self` @@ -7,37 +7,37 @@ LL | pub fn bad(self: Self) { = note: `-D clippy::needless-arbitrary-self-type` implied by `-D warnings` error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:17:20 + --> $DIR/needless_arbitrary_self_type.rs:20:20 | LL | pub fn mut_bad(mut self: Self) { | ^^^^^^^^^^^^^^ help: consider to change this parameter to: `mut self` error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:25:20 + --> $DIR/needless_arbitrary_self_type.rs:28:20 | LL | pub fn ref_bad(self: &Self) { | ^^^^^^^^^^^ help: consider to change this parameter to: `&self` error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:29:38 + --> $DIR/needless_arbitrary_self_type.rs:32:38 | LL | pub fn ref_bad_with_lifetime<'a>(self: &'a Self) { | ^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'a self` error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:37:24 + --> $DIR/needless_arbitrary_self_type.rs:40:24 | LL | pub fn mut_ref_bad(self: &mut Self) { | ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&mut self` error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:41:42 + --> $DIR/needless_arbitrary_self_type.rs:44:42 | LL | pub fn mut_ref_bad_with_lifetime<'a>(self: &'a mut Self) { | ^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'a mut self` error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:49:28 + --> $DIR/needless_arbitrary_self_type.rs:52:28 | LL | pub fn mut_ref_mut_bad(mut self: &mut Self) { | ^^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&mut self` diff --git a/tests/ui/option_map_unit_fn_fixable.fixed b/tests/ui/option_map_unit_fn_fixable.fixed index 9a0da404cb6..96d1c54946c 100644 --- a/tests/ui/option_map_unit_fn_fixable.fixed +++ b/tests/ui/option_map_unit_fn_fixable.fixed @@ -22,9 +22,9 @@ struct HasOption { } impl HasOption { - fn do_option_nothing(self: &Self, value: usize) {} + fn do_option_nothing(&self, value: usize) {} - fn do_option_plus_one(self: &Self, value: usize) -> usize { + fn do_option_plus_one(&self, value: usize) -> usize { value + 1 } } diff --git a/tests/ui/option_map_unit_fn_fixable.rs b/tests/ui/option_map_unit_fn_fixable.rs index 58041b62df3..931ffc18665 100644 --- a/tests/ui/option_map_unit_fn_fixable.rs +++ b/tests/ui/option_map_unit_fn_fixable.rs @@ -22,9 +22,9 @@ struct HasOption { } impl HasOption { - fn do_option_nothing(self: &Self, value: usize) {} + fn do_option_nothing(&self, value: usize) {} - fn do_option_plus_one(self: &Self, value: usize) -> usize { + fn do_option_plus_one(&self, value: usize) -> usize { value + 1 } } diff --git a/tests/ui/result_map_unit_fn_fixable.fixed b/tests/ui/result_map_unit_fn_fixable.fixed index 1d0a3ecd0ff..631042c616b 100644 --- a/tests/ui/result_map_unit_fn_fixable.fixed +++ b/tests/ui/result_map_unit_fn_fixable.fixed @@ -18,9 +18,9 @@ struct HasResult { } impl HasResult { - fn do_result_nothing(self: &Self, value: usize) {} + fn do_result_nothing(&self, value: usize) {} - fn do_result_plus_one(self: &Self, value: usize) -> usize { + fn do_result_plus_one(&self, value: usize) -> usize { value + 1 } } diff --git a/tests/ui/result_map_unit_fn_fixable.rs b/tests/ui/result_map_unit_fn_fixable.rs index 2fe18f923f0..679eb232626 100644 --- a/tests/ui/result_map_unit_fn_fixable.rs +++ b/tests/ui/result_map_unit_fn_fixable.rs @@ -18,9 +18,9 @@ struct HasResult { } impl HasResult { - fn do_result_nothing(self: &Self, value: usize) {} + fn do_result_nothing(&self, value: usize) {} - fn do_result_plus_one(self: &Self, value: usize) -> usize { + fn do_result_plus_one(&self, value: usize) -> usize { value + 1 } } From e03f73e627721c35459886781af281632cac299d Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Wed, 5 Aug 2020 23:38:55 +0200 Subject: [PATCH 364/526] fix nits --- .../src/needless_arbitrary_self_type.rs | 2 +- tests/ui/needless_arbitrary_self_type.fixed | 12 ++++++++-- tests/ui/needless_arbitrary_self_type.rs | 12 ++++++++-- tests/ui/needless_arbitrary_self_type.stderr | 22 +++++++++---------- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/needless_arbitrary_self_type.rs b/clippy_lints/src/needless_arbitrary_self_type.rs index 1b23ecd9ad2..4590128bedc 100644 --- a/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/clippy_lints/src/needless_arbitrary_self_type.rs @@ -82,7 +82,7 @@ fn check_param_inner(cx: &EarlyContext<'_>, path: &Path, span: Span, binding_mod cx, NEEDLESS_ARBITRARY_SELF_TYPE, span, - "the type of the `self` parameter is arbitrary", + "the type of the `self` parameter does not need to be arbitrary", "consider to change this parameter to", self_param, Applicability::MachineApplicable, diff --git a/tests/ui/needless_arbitrary_self_type.fixed b/tests/ui/needless_arbitrary_self_type.fixed index 642e48fd131..bc770d8bf68 100644 --- a/tests/ui/needless_arbitrary_self_type.fixed +++ b/tests/ui/needless_arbitrary_self_type.fixed @@ -29,11 +29,15 @@ impl ValType { unimplemented!(); } + pub fn ref_good(&self) { + unimplemented!(); + } + pub fn ref_bad_with_lifetime<'a>(&'a self) { unimplemented!(); } - pub fn ref_good(&self) { + pub fn ref_good_with_lifetime<'a>(&'a self) { unimplemented!(); } @@ -41,11 +45,15 @@ impl ValType { unimplemented!(); } + pub fn mut_ref_good(&mut self) { + unimplemented!(); + } + pub fn mut_ref_bad_with_lifetime<'a>(&'a mut self) { unimplemented!(); } - pub fn mut_ref_good(&mut self) { + pub fn mut_ref_good_with_lifetime<'a>(&'a mut self) { unimplemented!(); } diff --git a/tests/ui/needless_arbitrary_self_type.rs b/tests/ui/needless_arbitrary_self_type.rs index 178abc341a8..9074920b204 100644 --- a/tests/ui/needless_arbitrary_self_type.rs +++ b/tests/ui/needless_arbitrary_self_type.rs @@ -29,11 +29,15 @@ impl ValType { unimplemented!(); } + pub fn ref_good(&self) { + unimplemented!(); + } + pub fn ref_bad_with_lifetime<'a>(self: &'a Self) { unimplemented!(); } - pub fn ref_good(&self) { + pub fn ref_good_with_lifetime<'a>(&'a self) { unimplemented!(); } @@ -41,11 +45,15 @@ impl ValType { unimplemented!(); } + pub fn mut_ref_good(&mut self) { + unimplemented!(); + } + pub fn mut_ref_bad_with_lifetime<'a>(self: &'a mut Self) { unimplemented!(); } - pub fn mut_ref_good(&mut self) { + pub fn mut_ref_good_with_lifetime<'a>(&'a mut self) { unimplemented!(); } diff --git a/tests/ui/needless_arbitrary_self_type.stderr b/tests/ui/needless_arbitrary_self_type.stderr index fc21d3d0afd..227c6d73b62 100644 --- a/tests/ui/needless_arbitrary_self_type.stderr +++ b/tests/ui/needless_arbitrary_self_type.stderr @@ -1,4 +1,4 @@ -error: the type of the `self` parameter is arbitrary +error: the type of the `self` parameter does not need to be arbitrary --> $DIR/needless_arbitrary_self_type.rs:12:16 | LL | pub fn bad(self: Self) { @@ -6,38 +6,38 @@ LL | pub fn bad(self: Self) { | = note: `-D clippy::needless-arbitrary-self-type` implied by `-D warnings` -error: the type of the `self` parameter is arbitrary +error: the type of the `self` parameter does not need to be arbitrary --> $DIR/needless_arbitrary_self_type.rs:20:20 | LL | pub fn mut_bad(mut self: Self) { | ^^^^^^^^^^^^^^ help: consider to change this parameter to: `mut self` -error: the type of the `self` parameter is arbitrary +error: the type of the `self` parameter does not need to be arbitrary --> $DIR/needless_arbitrary_self_type.rs:28:20 | LL | pub fn ref_bad(self: &Self) { | ^^^^^^^^^^^ help: consider to change this parameter to: `&self` -error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:32:38 +error: the type of the `self` parameter does not need to be arbitrary + --> $DIR/needless_arbitrary_self_type.rs:36:38 | LL | pub fn ref_bad_with_lifetime<'a>(self: &'a Self) { | ^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'a self` -error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:40:24 +error: the type of the `self` parameter does not need to be arbitrary + --> $DIR/needless_arbitrary_self_type.rs:44:24 | LL | pub fn mut_ref_bad(self: &mut Self) { | ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&mut self` -error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:44:42 +error: the type of the `self` parameter does not need to be arbitrary + --> $DIR/needless_arbitrary_self_type.rs:52:42 | LL | pub fn mut_ref_bad_with_lifetime<'a>(self: &'a mut Self) { | ^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'a mut self` -error: the type of the `self` parameter is arbitrary - --> $DIR/needless_arbitrary_self_type.rs:52:28 +error: the type of the `self` parameter does not need to be arbitrary + --> $DIR/needless_arbitrary_self_type.rs:60:28 | LL | pub fn mut_ref_mut_bad(mut self: &mut Self) { | ^^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&mut self` From bfe610cc8d7d380cfaf83f03629a23747fc54fad Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Fri, 7 Aug 2020 18:03:12 +0200 Subject: [PATCH 365/526] ignore mutable self reference parameters --- clippy_lints/src/needless_arbitrary_self_type.rs | 8 ++++++-- tests/ui/needless_arbitrary_self_type.fixed | 2 +- tests/ui/needless_arbitrary_self_type.rs | 2 +- tests/ui/needless_arbitrary_self_type.stderr | 8 +------- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/needless_arbitrary_self_type.rs b/clippy_lints/src/needless_arbitrary_self_type.rs index 4590128bedc..38bdd0f7ed2 100644 --- a/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/clippy_lints/src/needless_arbitrary_self_type.rs @@ -104,8 +104,12 @@ impl EarlyLintPass for NeedlessArbitrarySelfType { } }, TyKind::Rptr(lifetime, mut_ty) => { - if let TyKind::Path(None, path) = &mut_ty.ty.kind { - check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl) + if_chain! { + if let TyKind::Path(None, path) = &mut_ty.ty.kind; + if let PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, _) = p.pat.kind; + then { + check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl) + } } }, _ => {}, diff --git a/tests/ui/needless_arbitrary_self_type.fixed b/tests/ui/needless_arbitrary_self_type.fixed index bc770d8bf68..9da21eb6b29 100644 --- a/tests/ui/needless_arbitrary_self_type.fixed +++ b/tests/ui/needless_arbitrary_self_type.fixed @@ -57,7 +57,7 @@ impl ValType { unimplemented!(); } - pub fn mut_ref_mut_bad(&mut self) { + pub fn mut_ref_mut_good(mut self: &mut Self) { unimplemented!(); } diff --git a/tests/ui/needless_arbitrary_self_type.rs b/tests/ui/needless_arbitrary_self_type.rs index 9074920b204..17aeaaf97ac 100644 --- a/tests/ui/needless_arbitrary_self_type.rs +++ b/tests/ui/needless_arbitrary_self_type.rs @@ -57,7 +57,7 @@ impl ValType { unimplemented!(); } - pub fn mut_ref_mut_bad(mut self: &mut Self) { + pub fn mut_ref_mut_good(mut self: &mut Self) { unimplemented!(); } diff --git a/tests/ui/needless_arbitrary_self_type.stderr b/tests/ui/needless_arbitrary_self_type.stderr index 227c6d73b62..f4c645d35c8 100644 --- a/tests/ui/needless_arbitrary_self_type.stderr +++ b/tests/ui/needless_arbitrary_self_type.stderr @@ -36,11 +36,5 @@ error: the type of the `self` parameter does not need to be arbitrary LL | pub fn mut_ref_bad_with_lifetime<'a>(self: &'a mut Self) { | ^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'a mut self` -error: the type of the `self` parameter does not need to be arbitrary - --> $DIR/needless_arbitrary_self_type.rs:60:28 - | -LL | pub fn mut_ref_mut_bad(mut self: &mut Self) { - | ^^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&mut self` - -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors From 87e740921abd4132152f090545fa4c9ed9fa0d6d Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Fri, 7 Aug 2020 17:55:25 +0200 Subject: [PATCH 366/526] check impl Ord / is_float --- clippy_lints/src/minmax.rs | 23 ++++++++++++++++------- tests/ui/min_max.rs | 18 ++++++++++++++++++ tests/ui/min_max.stderr | 32 +++++++++++++++++++------------- 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 1f798fd1120..004dd50a31b 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,5 +1,6 @@ use crate::consts::{constant_simple, Constant}; -use crate::utils::{match_def_path, paths, span_lint}; +use crate::utils::{match_def_path, match_trait_method, paths, span_lint}; +use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -84,12 +85,20 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons } }, ExprKind::MethodCall(ref path, _, ref args, _) => { - if path.ident.as_str() == sym!(max).as_str() { - fetch_const(cx, args, MinMax::Max) - } else if path.ident.as_str() == sym!(min).as_str() { - fetch_const(cx, args, MinMax::Min) - } else { - None + if_chain! { + if let [obj, _] = args; + if cx.typeck_results().expr_ty(obj).is_floating_point() || match_trait_method(cx, expr, &paths::ORD); + then { + if path.ident.as_str() == sym!(max).as_str() { + fetch_const(cx, args, MinMax::Max) + } else if path.ident.as_str() == sym!(min).as_str() { + fetch_const(cx, args, MinMax::Min) + } else { + None + } + } else { + None + } } }, _ => None, diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index 90ec5676493..f7ed72a11cf 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -6,6 +6,18 @@ use std::cmp::{max, min}; const LARGE: usize = 3; +struct NotOrd(u64); + +impl NotOrd { + fn min(self, x: u64) -> NotOrd { + NotOrd(x) + } + + fn max(self, x: u64) -> NotOrd { + NotOrd(x) + } +} + fn main() { let x; x = 2usize; @@ -31,11 +43,14 @@ fn main() { max("Apple", min(s, "Zoo")); // ok + let f = 3f32; x.min(1).max(3); x.max(3).min(1); + f.max(3f32).min(1f32); x.max(1).min(3); // ok x.min(3).max(1); // ok + f.min(3f32).max(1f32); // ok max(x.min(1), 3); min(x.max(1), 3); // ok @@ -44,4 +59,7 @@ fn main() { s.min("Apple").max("Zoo"); s.min("Zoo").max("Apple"); // ok + + let not_ord = NotOrd(1); + not_ord.min(1).max(3); // ok } diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index 653946dc025..9f8e26fa406 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -1,5 +1,5 @@ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:12:5 + --> $DIR/min_max.rs:24:5 | LL | min(1, max(3, x)); | ^^^^^^^^^^^^^^^^^ @@ -7,70 +7,76 @@ LL | min(1, max(3, x)); = note: `-D clippy::min-max` implied by `-D warnings` error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:13:5 + --> $DIR/min_max.rs:25:5 | LL | min(max(3, x), 1); | ^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:14:5 + --> $DIR/min_max.rs:26:5 | LL | max(min(x, 1), 3); | ^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:15:5 + --> $DIR/min_max.rs:27:5 | LL | max(3, min(x, 1)); | ^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:17:5 + --> $DIR/min_max.rs:29:5 | LL | my_max(3, my_min(x, 1)); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:29:5 + --> $DIR/min_max.rs:41:5 | LL | min("Apple", max("Zoo", s)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:30:5 + --> $DIR/min_max.rs:42:5 | LL | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:34:5 + --> $DIR/min_max.rs:47:5 | LL | x.min(1).max(3); | ^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:35:5 + --> $DIR/min_max.rs:48:5 | LL | x.max(3).min(1); | ^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:40:5 + --> $DIR/min_max.rs:49:5 + | +LL | f.max(3f32).min(1f32); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: this `min`/`max` combination leads to constant result + --> $DIR/min_max.rs:55:5 | LL | max(x.min(1), 3); | ^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:43:5 + --> $DIR/min_max.rs:58:5 | LL | s.max("Zoo").min("Apple"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> $DIR/min_max.rs:44:5 + --> $DIR/min_max.rs:59:5 | LL | s.min("Apple").max("Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors From bd71b01a8280dd0faa02416b7064ce170c1b40f5 Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Fri, 7 Aug 2020 14:21:14 -0700 Subject: [PATCH 367/526] Make the docs clearer for new contributors * Add an easy-to-see note at the top of `CONTRIBUTING.md` that points new contributors to the Basics docs * Add a note about compiler errors as a result of internals changes that break Clippy --- CONTRIBUTING.md | 7 +++++-- doc/basics.md | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dfc5cc077c3..5f7b1e85ee9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,11 +28,14 @@ All contributors are expected to follow the [Rust Code of Conduct]. ## Getting started -High level approach: +**Note: If this is your first time contributing to Clippy, you should +first read the [Basics docs](doc/basics.md).** + +### High level approach 1. Find something to fix/improve 2. Change code (likely some file in `clippy_lints/src/`) -3. Follow the instructions in the [Basics docs](doc/basics.md) such as running the `setup-toolchain.sh` script +3. Follow the instructions in the [Basics docs](doc/basics.md) to get set up 4. Run `cargo test` in the root directory and wiggle code until it passes 5. Open a PR (also can be done after 2. if you run into problems) diff --git a/doc/basics.md b/doc/basics.md index 5c07d9b98a5..c81e7f6e069 100644 --- a/doc/basics.md +++ b/doc/basics.md @@ -53,6 +53,9 @@ rustup-toolchain-install-master -f -n master -c rustc-dev -c llvm-tools rustup override set master ``` +_Note:_ Sometimes you may get compiler errors when building Clippy, even if you +didn't change anything. Normally those will be fixed by a maintainer in a few hours. + ## Building and Testing Once the `master` toolchain is installed, you can build and test Clippy like From 888657e09a2133fc105382136f61915086144e3f Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sat, 8 Aug 2020 18:13:43 +0200 Subject: [PATCH 368/526] Fix ICE in `loops` module --- clippy_lints/src/loops.rs | 20 ++++++++++---------- tests/ui/crashes/ice-5872.rs | 5 +++++ tests/ui/crashes/ice-5872.stderr | 10 ++++++++++ tests/ui/needless_collect.fixed | 4 ++-- tests/ui/needless_collect.rs | 2 +- tests/ui/needless_collect.stderr | 4 ++-- 6 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 tests/ui/crashes/ice-5872.rs create mode 100644 tests/ui/crashes/ice-5872.stderr diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6359c20040c..1729fea7bc8 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2374,7 +2374,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont match_type(cx, ty, &paths::BTREEMAP) || is_type_diagnostic_item(cx, ty, sym!(hashmap_type)) { if method.ident.name == sym!(len) { - let span = shorten_span(expr, sym!(collect)); + let span = shorten_needless_collect_span(expr); span_lint_and_sugg( cx, NEEDLESS_COLLECT, @@ -2386,20 +2386,20 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont ); } if method.ident.name == sym!(is_empty) { - let span = shorten_span(expr, sym!(iter)); + let span = shorten_needless_collect_span(expr); span_lint_and_sugg( cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, "replace with", - "get(0).is_none()".to_string(), + "next().is_none()".to_string(), Applicability::MachineApplicable, ); } if method.ident.name == sym!(contains) { let contains_arg = snippet(cx, args[1].span, "??"); - let span = shorten_span(expr, sym!(collect)); + let span = shorten_needless_collect_span(expr); span_lint_and_then( cx, NEEDLESS_COLLECT, @@ -2579,13 +2579,13 @@ fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) } } -fn shorten_span(expr: &Expr<'_>, target_fn_name: Symbol) -> Span { - let mut current_expr = expr; - while let ExprKind::MethodCall(ref path, ref span, ref args, _) = current_expr.kind { - if path.ident.name == target_fn_name { +fn shorten_needless_collect_span(expr: &Expr<'_>) -> Span { + if_chain! { + if let ExprKind::MethodCall(.., args, _) = &expr.kind; + if let ExprKind::MethodCall(_, span, ..) = &args[0].kind; + then { return expr.span.with_lo(span.lo()); } - current_expr = &args[0]; } - unreachable!() + unreachable!(); } diff --git a/tests/ui/crashes/ice-5872.rs b/tests/ui/crashes/ice-5872.rs new file mode 100644 index 00000000000..68afa8f8c3a --- /dev/null +++ b/tests/ui/crashes/ice-5872.rs @@ -0,0 +1,5 @@ +#![warn(clippy::needless_collect)] + +fn main() { + let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>().is_empty(); +} diff --git a/tests/ui/crashes/ice-5872.stderr b/tests/ui/crashes/ice-5872.stderr new file mode 100644 index 00000000000..a60ca345cf7 --- /dev/null +++ b/tests/ui/crashes/ice-5872.stderr @@ -0,0 +1,10 @@ +error: avoid using `collect()` when not needed + --> $DIR/ice-5872.rs:4:39 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>().is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` + | + = note: `-D clippy::needless-collect` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index be37dc16b9a..7f2fcf02f6b 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -5,11 +5,11 @@ use std::collections::{BTreeSet, HashMap, HashSet}; #[warn(clippy::needless_collect)] -#[allow(unused_variables, clippy::iter_cloned_collect)] +#[allow(unused_variables, clippy::iter_cloned_collect, clippy::iter_next_slice)] fn main() { let sample = [1; 5]; let len = sample.iter().count(); - if sample.get(0).is_none() { + if sample.iter().next().is_none() { // Empty } sample.iter().cloned().any(|x| x == 1); diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 7ee603afeb0..788a9eb3264 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -5,7 +5,7 @@ use std::collections::{BTreeSet, HashMap, HashSet}; #[warn(clippy::needless_collect)] -#[allow(unused_variables, clippy::iter_cloned_collect)] +#[allow(unused_variables, clippy::iter_cloned_collect, clippy::iter_next_slice)] fn main() { let sample = [1; 5]; let len = sample.iter().collect::<Vec<_>>().len(); diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index 9113aad90dd..2a9539d5975 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -7,10 +7,10 @@ LL | let len = sample.iter().collect::<Vec<_>>().len(); = note: `-D clippy::needless-collect` implied by `-D warnings` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:12:15 + --> $DIR/needless_collect.rs:12:22 | LL | if sample.iter().collect::<Vec<_>>().is_empty() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get(0).is_none()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:15:28 From fd87cdb357b801b1fab465f0be595386a3f84134 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Sat, 8 Aug 2020 19:20:34 +0200 Subject: [PATCH 369/526] Run fmt --- clippy_lints/src/functions.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 6a141f1fc78..28b276967bc 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -294,7 +294,8 @@ impl<'tcx> LateLintPass<'tcx> for Functions { let body = cx.tcx.hir().body(eid); Self::check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id); - if attr.is_none() && cx.access_levels.is_exported(item.hir_id) && !is_proc_macro(cx.sess(), &item.attrs) { + if attr.is_none() && cx.access_levels.is_exported(item.hir_id) && !is_proc_macro(cx.sess(), &item.attrs) + { check_must_use_candidate( cx, &sig.decl, From a77e881ec9f324cdc544150f897d8b34281f92e4 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Wed, 17 Jun 2020 01:16:34 +0200 Subject: [PATCH 370/526] should_impl_trait - ignore methods with lifetime params --- clippy_lints/src/methods/mod.rs | 11 ++++++++++- tests/ui/methods.rs | 5 +++++ tests/ui/methods.stderr | 26 +++++++++++++------------- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 570ae66d595..3009aa3a64e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1497,11 +1497,20 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if cx.access_levels.is_exported(impl_item.hir_id) { // check missing trait implementations for &(method_name, n_args, fn_header, self_kind, out_type, trait_name) in &TRAIT_METHODS { + let no_lifetime_params = || { + impl_item.generics.params.iter().filter(|p| match p.kind { + hir::GenericParamKind::Lifetime { .. } => true, + _ => false, + }).count() == 0 + }; if name == method_name && sig.decl.inputs.len() == n_args && out_type.matches(cx, &sig.decl.output) && self_kind.matches(cx, self_ty, first_arg_ty) && - fn_header_equals(*fn_header, sig.header) { + fn_header_equals(*fn_header, sig.header) && + // ignore methods with lifetime params, risk of false positive + no_lifetime_params() + { span_lint(cx, SHOULD_IMPLEMENT_TRAIT, impl_item.span, &format!( "defining a method called `{}` on this type; consider implementing \ the `{}` trait or choosing a less ambiguous name", name, trait_name)); diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 7880cf36415..3b267b0dab2 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -10,6 +10,7 @@ clippy::non_ascii_literal, clippy::new_without_default, clippy::needless_pass_by_value, + clippy::needless_lifetimes, clippy::print_stdout, clippy::must_use_candidate, clippy::use_self, @@ -82,6 +83,10 @@ impl T { fn new(self) -> Self { unimplemented!(); } + + pub fn next<'b>(&'b mut self) -> Option<&'b mut T> { + unimplemented!(); + } } pub struct T1; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 01cf487ac14..9b8ecaed692 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:39:5 + --> $DIR/methods.rs:40:5 | LL | / pub fn add(self, other: T) -> T { LL | | self @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: methods called `new` usually return `Self` - --> $DIR/methods.rs:169:5 + --> $DIR/methods.rs:174:5 | LL | / fn new() -> i32 { LL | | 0 @@ -19,7 +19,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:188:13 + --> $DIR/methods.rs:193:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:191:13 + --> $DIR/methods.rs:196:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -38,7 +38,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:208:22 + --> $DIR/methods.rs:213:22 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)` @@ -46,25 +46,25 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: `-D clippy::search-is-some` implied by `-D warnings` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:209:20 + --> $DIR/methods.rs:214:20 | LL | let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:210:20 + --> $DIR/methods.rs:215:20 | LL | let _ = (0..1).find(|x| *x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:211:22 + --> $DIR/methods.rs:216:22 | LL | let _ = v.iter().find(|x| **x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:214:13 + --> $DIR/methods.rs:219:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -74,13 +74,13 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:220:22 + --> $DIR/methods.rs:225:22 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:223:13 + --> $DIR/methods.rs:228:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -90,13 +90,13 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:229:22 + --> $DIR/methods.rs:234:22 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:232:13 + --> $DIR/methods.rs:237:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ From 2bc0ecd44b4d09476eade641e02451d949a1c8e2 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Fri, 19 Jun 2020 22:12:51 +0200 Subject: [PATCH 371/526] should_implement_trait - add test cases for every checked trait method --- clippy_lints/src/methods/mod.rs | 1 + tests/ui/methods.rs | 146 ++++++++++++++++-- tests/ui/methods.stderr | 264 ++++++++++++++++++++++++++++++-- 3 files changed, 386 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 3009aa3a64e..c225a3bd359 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3424,6 +3424,7 @@ const TRAIT_METHODS: [(&str, usize, &hir::FnHeader, SelfKind, OutType, &str); 30 ("borrow_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), ("clone", 1, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::clone::Clone"), ("cmp", 2, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), + // FIXME: default doesn't work ("default", 0, &FN_HEADER, SelfKind::No, OutType::Any, "std::default::Default"), ("deref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), ("deref_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 3b267b0dab2..adf81607440 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -37,10 +37,137 @@ use option_helpers::IteratorFalsePositives; pub struct T; impl T { + // ******************************************* + // complete trait method list, should lint all + // ******************************************* pub fn add(self, other: T) -> T { - self + unimplemented!() } + pub fn as_mut(&mut self) -> &mut T { + unimplemented!() + } + + pub fn as_ref(&self) -> &T { + unimplemented!() + } + + pub fn bitand(self, rhs: T) -> T { + unimplemented!() + } + + pub fn bitor(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn bitxor(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn borrow(&self) -> &str { + unimplemented!() + } + + pub fn borrow_mut(&mut self) -> &mut str { + unimplemented!() + } + + pub fn clone(&self) -> Self { + unimplemented!() + } + + pub fn cmp(&self, other: &Self) -> Self { + unimplemented!() + } + + pub fn default() -> Self { + unimplemented!() + } + + pub fn deref(&self) -> &Self { + unimplemented!() + } + + pub fn deref_mut(&mut self) -> &mut Self { + unimplemented!() + } + + pub fn div(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn drop(&mut self) { + unimplemented!() + } + + pub fn eq(&self, other: &Self) -> bool { + unimplemented!() + } + + pub fn from_iter<T>(iter: T) -> Self { + unimplemented!() + } + + pub fn from_str(s: &str) -> Result<Self, Self> { + unimplemented!() + } + + pub fn hash(&self, state: &mut T) { + unimplemented!() + } + + pub fn index(&self, index: usize) -> &Self { + unimplemented!() + } + + pub fn index_mut(&mut self, index: usize) -> &mut Self { + unimplemented!() + } + + pub fn into_iter(self) -> Self { + unimplemented!() + } + + pub fn mul(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn neg(self) -> Self { + unimplemented!() + } + + pub fn next(&mut self) -> Option<Self> { + unimplemented!() + } + + pub fn not(self) -> Self { + unimplemented!() + } + + pub fn rem(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn shl(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn shr(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn sub(self, rhs: Self) -> Self { + unimplemented!() + } + // ***************** + // complete list end + // ***************** +} + +pub struct T1; +impl T1 { + // corner cases: should not lint + // no error, not public interface pub(crate) fn drop(&mut self) {} @@ -50,22 +177,22 @@ impl T { } // no error, private function - fn eq(&self, other: T) -> bool { + fn eq(&self, other: Self) -> bool { true } // No error; self is a ref. - fn sub(&self, other: T) -> &T { + fn sub(&self, other: Self) -> &Self { self } // No error; different number of arguments. - fn div(self) -> T { + fn div(self) -> Self { self } // No error; wrong return type. - fn rem(self, other: T) {} + fn rem(self, other: Self) {} // Fine fn into_u32(self) -> u32 { @@ -89,16 +216,15 @@ impl T { } } -pub struct T1; - -impl T1 { +pub struct T2; +impl T2 { // Shouldn't trigger lint as it is unsafe. - pub unsafe fn add(self, rhs: T1) -> T1 { + pub unsafe fn add(self, rhs: Self) -> Self { self } // Should not trigger lint since this is an async function. - pub async fn next(&mut self) -> Option<T1> { + pub async fn next(&mut self) -> Option<Self> { None } } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 9b8ecaed692..5105fff8f5b 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,15 +1,249 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:40:5 + --> $DIR/methods.rs:43:5 | LL | / pub fn add(self, other: T) -> T { -LL | | self +LL | | unimplemented!() LL | | } | |_____^ | = note: `-D clippy::should-implement-trait` implied by `-D warnings` +error: defining a method called `as_mut` on this type; consider implementing the `std::convert::AsMut` trait or choosing a less ambiguous name + --> $DIR/methods.rs:47:5 + | +LL | / pub fn as_mut(&mut self) -> &mut T { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `as_ref` on this type; consider implementing the `std::convert::AsRef` trait or choosing a less ambiguous name + --> $DIR/methods.rs:51:5 + | +LL | / pub fn as_ref(&self) -> &T { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `bitand` on this type; consider implementing the `std::ops::BitAnd` trait or choosing a less ambiguous name + --> $DIR/methods.rs:55:5 + | +LL | / pub fn bitand(self, rhs: T) -> T { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `bitor` on this type; consider implementing the `std::ops::BitOr` trait or choosing a less ambiguous name + --> $DIR/methods.rs:59:5 + | +LL | / pub fn bitor(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `bitxor` on this type; consider implementing the `std::ops::BitXor` trait or choosing a less ambiguous name + --> $DIR/methods.rs:63:5 + | +LL | / pub fn bitxor(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `borrow` on this type; consider implementing the `std::borrow::Borrow` trait or choosing a less ambiguous name + --> $DIR/methods.rs:67:5 + | +LL | / pub fn borrow(&self) -> &str { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `borrow_mut` on this type; consider implementing the `std::borrow::BorrowMut` trait or choosing a less ambiguous name + --> $DIR/methods.rs:71:5 + | +LL | / pub fn borrow_mut(&mut self) -> &mut str { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `clone` on this type; consider implementing the `std::clone::Clone` trait or choosing a less ambiguous name + --> $DIR/methods.rs:75:5 + | +LL | / pub fn clone(&self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `cmp` on this type; consider implementing the `std::cmp::Ord` trait or choosing a less ambiguous name + --> $DIR/methods.rs:79:5 + | +LL | / pub fn cmp(&self, other: &Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `deref` on this type; consider implementing the `std::ops::Deref` trait or choosing a less ambiguous name + --> $DIR/methods.rs:87:5 + | +LL | / pub fn deref(&self) -> &Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `deref_mut` on this type; consider implementing the `std::ops::DerefMut` trait or choosing a less ambiguous name + --> $DIR/methods.rs:91:5 + | +LL | / pub fn deref_mut(&mut self) -> &mut Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `div` on this type; consider implementing the `std::ops::Div` trait or choosing a less ambiguous name + --> $DIR/methods.rs:95:5 + | +LL | / pub fn div(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `drop` on this type; consider implementing the `std::ops::Drop` trait or choosing a less ambiguous name + --> $DIR/methods.rs:99:5 + | +LL | / pub fn drop(&mut self) { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `eq` on this type; consider implementing the `std::cmp::PartialEq` trait or choosing a less ambiguous name + --> $DIR/methods.rs:103:5 + | +LL | / pub fn eq(&self, other: &Self) -> bool { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `from_iter` on this type; consider implementing the `std::iter::FromIterator` trait or choosing a less ambiguous name + --> $DIR/methods.rs:107:5 + | +LL | / pub fn from_iter<T>(iter: T) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `from_str` on this type; consider implementing the `std::str::FromStr` trait or choosing a less ambiguous name + --> $DIR/methods.rs:111:5 + | +LL | / pub fn from_str(s: &str) -> Result<Self, Self> { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: docs for function returning `Result` missing `# Errors` section + --> $DIR/methods.rs:111:5 + | +LL | / pub fn from_str(s: &str) -> Result<Self, Self> { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = note: `-D clippy::missing-errors-doc` implied by `-D warnings` + +error: defining a method called `hash` on this type; consider implementing the `std::hash::Hash` trait or choosing a less ambiguous name + --> $DIR/methods.rs:115:5 + | +LL | / pub fn hash(&self, state: &mut T) { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `index` on this type; consider implementing the `std::ops::Index` trait or choosing a less ambiguous name + --> $DIR/methods.rs:119:5 + | +LL | / pub fn index(&self, index: usize) -> &Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `index_mut` on this type; consider implementing the `std::ops::IndexMut` trait or choosing a less ambiguous name + --> $DIR/methods.rs:123:5 + | +LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `into_iter` on this type; consider implementing the `std::iter::IntoIterator` trait or choosing a less ambiguous name + --> $DIR/methods.rs:127:5 + | +LL | / pub fn into_iter(self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `mul` on this type; consider implementing the `std::ops::Mul` trait or choosing a less ambiguous name + --> $DIR/methods.rs:131:5 + | +LL | / pub fn mul(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `neg` on this type; consider implementing the `std::ops::Neg` trait or choosing a less ambiguous name + --> $DIR/methods.rs:135:5 + | +LL | / pub fn neg(self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `next` on this type; consider implementing the `std::iter::Iterator` trait or choosing a less ambiguous name + --> $DIR/methods.rs:139:5 + | +LL | / pub fn next(&mut self) -> Option<Self> { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `not` on this type; consider implementing the `std::ops::Not` trait or choosing a less ambiguous name + --> $DIR/methods.rs:143:5 + | +LL | / pub fn not(self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `rem` on this type; consider implementing the `std::ops::Rem` trait or choosing a less ambiguous name + --> $DIR/methods.rs:147:5 + | +LL | / pub fn rem(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `shl` on this type; consider implementing the `std::ops::Shl` trait or choosing a less ambiguous name + --> $DIR/methods.rs:151:5 + | +LL | / pub fn shl(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `shr` on this type; consider implementing the `std::ops::Shr` trait or choosing a less ambiguous name + --> $DIR/methods.rs:155:5 + | +LL | / pub fn shr(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + +error: defining a method called `sub` on this type; consider implementing the `std::ops::Sub` trait or choosing a less ambiguous name + --> $DIR/methods.rs:159:5 + | +LL | / pub fn sub(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + error: methods called `new` usually return `Self` - --> $DIR/methods.rs:174:5 + --> $DIR/methods.rs:300:5 | LL | / fn new() -> i32 { LL | | 0 @@ -19,7 +253,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:193:13 + --> $DIR/methods.rs:319:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +262,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:196:13 + --> $DIR/methods.rs:322:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -38,7 +272,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:213:22 + --> $DIR/methods.rs:339:22 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)` @@ -46,25 +280,25 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: `-D clippy::search-is-some` implied by `-D warnings` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:214:20 + --> $DIR/methods.rs:340:20 | LL | let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:215:20 + --> $DIR/methods.rs:341:20 | LL | let _ = (0..1).find(|x| *x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:216:22 + --> $DIR/methods.rs:342:22 | LL | let _ = v.iter().find(|x| **x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:219:13 + --> $DIR/methods.rs:345:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -74,13 +308,13 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:225:22 + --> $DIR/methods.rs:351:22 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:228:13 + --> $DIR/methods.rs:354:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -90,13 +324,13 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:234:22 + --> $DIR/methods.rs:360:22 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:237:13 + --> $DIR/methods.rs:363:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -105,5 +339,5 @@ LL | | } LL | | ).is_some(); | |______________________________^ -error: aborting due to 13 previous errors +error: aborting due to 42 previous errors From e6b2254f9e55743dbace44cc73c6447b6bda58e5 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Sun, 21 Jun 2020 00:12:09 +0200 Subject: [PATCH 372/526] should_implement_trait - pr remarks --- clippy_lints/src/methods/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index c225a3bd359..a75989e3f13 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1498,10 +1498,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods { // check missing trait implementations for &(method_name, n_args, fn_header, self_kind, out_type, trait_name) in &TRAIT_METHODS { let no_lifetime_params = || { - impl_item.generics.params.iter().filter(|p| match p.kind { - hir::GenericParamKind::Lifetime { .. } => true, - _ => false, - }).count() == 0 + !impl_item.generics.params.iter() + .any(|p| matches!( + p.kind, + hir::GenericParamKind::Lifetime { .. })) }; if name == method_name && sig.decl.inputs.len() == n_args && @@ -1510,7 +1510,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { fn_header_equals(*fn_header, sig.header) && // ignore methods with lifetime params, risk of false positive no_lifetime_params() - { + { span_lint(cx, SHOULD_IMPLEMENT_TRAIT, impl_item.span, &format!( "defining a method called `{}` on this type; consider implementing \ the `{}` trait or choosing a less ambiguous name", name, trait_name)); From 7cc1a2ed879e45605a53b802cfa5291c9a51284c Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Tue, 23 Jun 2020 21:27:48 +0200 Subject: [PATCH 373/526] should_implement_trait - filter on explicit lifetime param only --- clippy_lints/src/methods/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index a75989e3f13..bad1bb7224e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1501,7 +1501,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { !impl_item.generics.params.iter() .any(|p| matches!( p.kind, - hir::GenericParamKind::Lifetime { .. })) + hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit })) }; if name == method_name && sig.decl.inputs.len() == n_args && From 166c520e9a8b1a45819255e75dee737136aa6ec8 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Thu, 30 Jul 2020 01:41:12 +0200 Subject: [PATCH 374/526] should_impl_trait - pr comments --- clippy_lints/src/methods/mod.rs | 150 ++++++---- tests/ui/methods.rs | 197 +------------ tests/ui/methods.stderr | 270 +----------------- tests/ui/should_impl_trait/corner_cases.rs | 83 ++++++ tests/ui/should_impl_trait/method_list_1.rs | 87 ++++++ .../ui/should_impl_trait/method_list_1.stderr | 143 ++++++++++ tests/ui/should_impl_trait/method_list_2.rs | 88 ++++++ .../ui/should_impl_trait/method_list_2.stderr | 153 ++++++++++ 8 files changed, 670 insertions(+), 501 deletions(-) create mode 100644 tests/ui/should_impl_trait/corner_cases.rs create mode 100644 tests/ui/should_impl_trait/method_list_1.rs create mode 100644 tests/ui/should_impl_trait/method_list_1.stderr create mode 100644 tests/ui/should_impl_trait/method_list_2.rs create mode 100644 tests/ui/should_impl_trait/method_list_2.stderr diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index bad1bb7224e..a549c3b78ef 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1495,25 +1495,31 @@ impl<'tcx> LateLintPass<'tcx> for Methods { then { if cx.access_levels.is_exported(impl_item.hir_id) { - // check missing trait implementations - for &(method_name, n_args, fn_header, self_kind, out_type, trait_name) in &TRAIT_METHODS { - let no_lifetime_params = || { - !impl_item.generics.params.iter() - .any(|p| matches!( - p.kind, - hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit })) - }; - if name == method_name && - sig.decl.inputs.len() == n_args && - out_type.matches(cx, &sig.decl.output) && - self_kind.matches(cx, self_ty, first_arg_ty) && - fn_header_equals(*fn_header, sig.header) && - // ignore methods with lifetime params, risk of false positive - no_lifetime_params() + // check missing trait implementations + for method_config in &TRAIT_METHODS { + if name == method_config.method_name && + sig.decl.inputs.len() == method_config.param_count && + method_config.output_type.matches(cx, &sig.decl.output) && + method_config.self_kind.matches(cx, self_ty, first_arg_ty) && + fn_header_equals(*method_config.fn_header, sig.header) && + method_config.lifetime_param_cond(&impl_item) { - span_lint(cx, SHOULD_IMPLEMENT_TRAIT, impl_item.span, &format!( - "defining a method called `{}` on this type; consider implementing \ - the `{}` trait or choosing a less ambiguous name", name, trait_name)); + span_lint_and_help( + cx, + SHOULD_IMPLEMENT_TRAIT, + impl_item.span, + &format!( + "method `{}` can be confused for the standard trait method `{}::{}`", + method_config.method_name, + method_config.trait_name, + method_config.method_name + ), + None, + &format!( + "consider implementing the trait `{}` or choosing a less ambiguous method name", + method_config.trait_name + ) + ); } } } @@ -3412,39 +3418,85 @@ const FN_HEADER: hir::FnHeader = hir::FnHeader { abi: rustc_target::spec::abi::Abi::Rust, }; +struct ShouldImplTraitCase { + trait_name: &'static str, + method_name: &'static str, + param_count: usize, + fn_header: &'static hir::FnHeader, + // implicit self kind expected (none, self, &self, ...) + self_kind: SelfKind, + // checks against the output type + output_type: OutType, + // certain methods with explicit lifetimes can't implement the equivalent trait method + lint_explicit_lifetime: bool, +} +impl ShouldImplTraitCase { + const fn new( + trait_name: &'static str, + method_name: &'static str, + param_count: usize, + fn_header: &'static hir::FnHeader, + self_kind: SelfKind, + output_type: OutType, + lint_explicit_lifetime: bool, + ) -> ShouldImplTraitCase { + ShouldImplTraitCase { + trait_name, + method_name, + param_count, + fn_header, + self_kind, + output_type, + lint_explicit_lifetime, + } + } + + fn lifetime_param_cond(&self, impl_item: &hir::ImplItem<'_>) -> bool { + self.lint_explicit_lifetime + || !impl_item.generics.params.iter().any(|p| { + matches!( + p.kind, + hir::GenericParamKind::Lifetime { + kind: hir::LifetimeParamKind::Explicit + } + ) + }) + } +} + #[rustfmt::skip] -const TRAIT_METHODS: [(&str, usize, &hir::FnHeader, SelfKind, OutType, &str); 30] = [ - ("add", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Add"), - ("as_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), - ("as_ref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), - ("bitand", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitAnd"), - ("bitor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitOr"), - ("bitxor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitXor"), - ("borrow", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"), - ("borrow_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), - ("clone", 1, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::clone::Clone"), - ("cmp", 2, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), +const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [ + ShouldImplTraitCase::new("std::ops::Add", "add", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::convert::AsMut", "as_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, true), + ShouldImplTraitCase::new("std::convert::AsRef", "as_ref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, true), + ShouldImplTraitCase::new("std::ops::BitAnd", "bitand", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::BitOr", "bitor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::BitXor", "bitxor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::borrow::Borrow", "borrow", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, true), + ShouldImplTraitCase::new("std::borrow::BorrowMut", "borrow_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, true), + ShouldImplTraitCase::new("std::clone::Clone", "clone", 1, &FN_HEADER, SelfKind::Ref, OutType::Any, true), + ShouldImplTraitCase::new("std::cmp::Ord", "cmp", 2, &FN_HEADER, SelfKind::Ref, OutType::Any, true), // FIXME: default doesn't work - ("default", 0, &FN_HEADER, SelfKind::No, OutType::Any, "std::default::Default"), - ("deref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), - ("deref_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), - ("div", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Div"), - ("drop", 1, &FN_HEADER, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), - ("eq", 2, &FN_HEADER, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), - ("from_iter", 1, &FN_HEADER, SelfKind::No, OutType::Any, "std::iter::FromIterator"), - ("from_str", 1, &FN_HEADER, SelfKind::No, OutType::Any, "std::str::FromStr"), - ("hash", 2, &FN_HEADER, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), - ("index", 2, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Index"), - ("index_mut", 2, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), - ("into_iter", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), - ("mul", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Mul"), - ("neg", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Neg"), - ("next", 1, &FN_HEADER, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), - ("not", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Not"), - ("rem", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Rem"), - ("shl", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Shl"), - ("shr", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Shr"), - ("sub", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Sub"), + ShouldImplTraitCase::new("std::default::Default", "default", 0, &FN_HEADER, SelfKind::No, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Deref", "deref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, true), + ShouldImplTraitCase::new("std::ops::DerefMut", "deref_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, true), + ShouldImplTraitCase::new("std::ops::Div", "div", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Drop", "drop", 1, &FN_HEADER, SelfKind::RefMut, OutType::Unit, true), + ShouldImplTraitCase::new("std::cmp::PartialEq", "eq", 2, &FN_HEADER, SelfKind::Ref, OutType::Bool, true), + ShouldImplTraitCase::new("std::iter::FromIterator", "from_iter", 1, &FN_HEADER, SelfKind::No, OutType::Any, true), + ShouldImplTraitCase::new("std::str::FromStr", "from_str", 1, &FN_HEADER, SelfKind::No, OutType::Any, true), + ShouldImplTraitCase::new("std::hash::Hash", "hash", 2, &FN_HEADER, SelfKind::Ref, OutType::Unit, true), + ShouldImplTraitCase::new("std::ops::Index", "index", 2, &FN_HEADER, SelfKind::Ref, OutType::Ref, true), + ShouldImplTraitCase::new("std::ops::IndexMut", "index_mut", 2, &FN_HEADER, SelfKind::RefMut, OutType::Ref, true), + ShouldImplTraitCase::new("std::iter::IntoIterator", "into_iter", 1, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Mul", "mul", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Neg", "neg", 1, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::iter::Iterator", "next", 1, &FN_HEADER, SelfKind::RefMut, OutType::Any, false), + ShouldImplTraitCase::new("std::ops::Not", "not", 1, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Rem", "rem", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Shl", "shl", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Shr", "shr", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Sub", "sub", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), ]; #[rustfmt::skip] diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index adf81607440..80dd2f744b3 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -34,201 +34,6 @@ use std::sync::{self, Arc}; use option_helpers::IteratorFalsePositives; -pub struct T; - -impl T { - // ******************************************* - // complete trait method list, should lint all - // ******************************************* - pub fn add(self, other: T) -> T { - unimplemented!() - } - - pub fn as_mut(&mut self) -> &mut T { - unimplemented!() - } - - pub fn as_ref(&self) -> &T { - unimplemented!() - } - - pub fn bitand(self, rhs: T) -> T { - unimplemented!() - } - - pub fn bitor(self, rhs: Self) -> Self { - unimplemented!() - } - - pub fn bitxor(self, rhs: Self) -> Self { - unimplemented!() - } - - pub fn borrow(&self) -> &str { - unimplemented!() - } - - pub fn borrow_mut(&mut self) -> &mut str { - unimplemented!() - } - - pub fn clone(&self) -> Self { - unimplemented!() - } - - pub fn cmp(&self, other: &Self) -> Self { - unimplemented!() - } - - pub fn default() -> Self { - unimplemented!() - } - - pub fn deref(&self) -> &Self { - unimplemented!() - } - - pub fn deref_mut(&mut self) -> &mut Self { - unimplemented!() - } - - pub fn div(self, rhs: Self) -> Self { - unimplemented!() - } - - pub fn drop(&mut self) { - unimplemented!() - } - - pub fn eq(&self, other: &Self) -> bool { - unimplemented!() - } - - pub fn from_iter<T>(iter: T) -> Self { - unimplemented!() - } - - pub fn from_str(s: &str) -> Result<Self, Self> { - unimplemented!() - } - - pub fn hash(&self, state: &mut T) { - unimplemented!() - } - - pub fn index(&self, index: usize) -> &Self { - unimplemented!() - } - - pub fn index_mut(&mut self, index: usize) -> &mut Self { - unimplemented!() - } - - pub fn into_iter(self) -> Self { - unimplemented!() - } - - pub fn mul(self, rhs: Self) -> Self { - unimplemented!() - } - - pub fn neg(self) -> Self { - unimplemented!() - } - - pub fn next(&mut self) -> Option<Self> { - unimplemented!() - } - - pub fn not(self) -> Self { - unimplemented!() - } - - pub fn rem(self, rhs: Self) -> Self { - unimplemented!() - } - - pub fn shl(self, rhs: Self) -> Self { - unimplemented!() - } - - pub fn shr(self, rhs: Self) -> Self { - unimplemented!() - } - - pub fn sub(self, rhs: Self) -> Self { - unimplemented!() - } - // ***************** - // complete list end - // ***************** -} - -pub struct T1; -impl T1 { - // corner cases: should not lint - - // no error, not public interface - pub(crate) fn drop(&mut self) {} - - // no error, private function - fn neg(self) -> Self { - self - } - - // no error, private function - fn eq(&self, other: Self) -> bool { - true - } - - // No error; self is a ref. - fn sub(&self, other: Self) -> &Self { - self - } - - // No error; different number of arguments. - fn div(self) -> Self { - self - } - - // No error; wrong return type. - fn rem(self, other: Self) {} - - // Fine - fn into_u32(self) -> u32 { - 0 - } - - fn into_u16(&self) -> u16 { - 0 - } - - fn to_something(self) -> u32 { - 0 - } - - fn new(self) -> Self { - unimplemented!(); - } - - pub fn next<'b>(&'b mut self) -> Option<&'b mut T> { - unimplemented!(); - } -} - -pub struct T2; -impl T2 { - // Shouldn't trigger lint as it is unsafe. - pub unsafe fn add(self, rhs: Self) -> Self { - self - } - - // Should not trigger lint since this is an async function. - pub async fn next(&mut self) -> Option<Self> { - None - } -} - struct Lt<'a> { foo: &'a u32, } @@ -302,6 +107,8 @@ impl BadNew { } } +struct T; + impl Mul<T> for T { type Output = T; // No error, obviously. diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 5105fff8f5b..2a0a43e83a6 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,249 +1,5 @@ -error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:43:5 - | -LL | / pub fn add(self, other: T) -> T { -LL | | unimplemented!() -LL | | } - | |_____^ - | - = note: `-D clippy::should-implement-trait` implied by `-D warnings` - -error: defining a method called `as_mut` on this type; consider implementing the `std::convert::AsMut` trait or choosing a less ambiguous name - --> $DIR/methods.rs:47:5 - | -LL | / pub fn as_mut(&mut self) -> &mut T { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `as_ref` on this type; consider implementing the `std::convert::AsRef` trait or choosing a less ambiguous name - --> $DIR/methods.rs:51:5 - | -LL | / pub fn as_ref(&self) -> &T { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `bitand` on this type; consider implementing the `std::ops::BitAnd` trait or choosing a less ambiguous name - --> $DIR/methods.rs:55:5 - | -LL | / pub fn bitand(self, rhs: T) -> T { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `bitor` on this type; consider implementing the `std::ops::BitOr` trait or choosing a less ambiguous name - --> $DIR/methods.rs:59:5 - | -LL | / pub fn bitor(self, rhs: Self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `bitxor` on this type; consider implementing the `std::ops::BitXor` trait or choosing a less ambiguous name - --> $DIR/methods.rs:63:5 - | -LL | / pub fn bitxor(self, rhs: Self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `borrow` on this type; consider implementing the `std::borrow::Borrow` trait or choosing a less ambiguous name - --> $DIR/methods.rs:67:5 - | -LL | / pub fn borrow(&self) -> &str { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `borrow_mut` on this type; consider implementing the `std::borrow::BorrowMut` trait or choosing a less ambiguous name - --> $DIR/methods.rs:71:5 - | -LL | / pub fn borrow_mut(&mut self) -> &mut str { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `clone` on this type; consider implementing the `std::clone::Clone` trait or choosing a less ambiguous name - --> $DIR/methods.rs:75:5 - | -LL | / pub fn clone(&self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `cmp` on this type; consider implementing the `std::cmp::Ord` trait or choosing a less ambiguous name - --> $DIR/methods.rs:79:5 - | -LL | / pub fn cmp(&self, other: &Self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `deref` on this type; consider implementing the `std::ops::Deref` trait or choosing a less ambiguous name - --> $DIR/methods.rs:87:5 - | -LL | / pub fn deref(&self) -> &Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `deref_mut` on this type; consider implementing the `std::ops::DerefMut` trait or choosing a less ambiguous name - --> $DIR/methods.rs:91:5 - | -LL | / pub fn deref_mut(&mut self) -> &mut Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `div` on this type; consider implementing the `std::ops::Div` trait or choosing a less ambiguous name - --> $DIR/methods.rs:95:5 - | -LL | / pub fn div(self, rhs: Self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `drop` on this type; consider implementing the `std::ops::Drop` trait or choosing a less ambiguous name - --> $DIR/methods.rs:99:5 - | -LL | / pub fn drop(&mut self) { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `eq` on this type; consider implementing the `std::cmp::PartialEq` trait or choosing a less ambiguous name - --> $DIR/methods.rs:103:5 - | -LL | / pub fn eq(&self, other: &Self) -> bool { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `from_iter` on this type; consider implementing the `std::iter::FromIterator` trait or choosing a less ambiguous name - --> $DIR/methods.rs:107:5 - | -LL | / pub fn from_iter<T>(iter: T) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `from_str` on this type; consider implementing the `std::str::FromStr` trait or choosing a less ambiguous name - --> $DIR/methods.rs:111:5 - | -LL | / pub fn from_str(s: &str) -> Result<Self, Self> { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: docs for function returning `Result` missing `# Errors` section - --> $DIR/methods.rs:111:5 - | -LL | / pub fn from_str(s: &str) -> Result<Self, Self> { -LL | | unimplemented!() -LL | | } - | |_____^ - | - = note: `-D clippy::missing-errors-doc` implied by `-D warnings` - -error: defining a method called `hash` on this type; consider implementing the `std::hash::Hash` trait or choosing a less ambiguous name - --> $DIR/methods.rs:115:5 - | -LL | / pub fn hash(&self, state: &mut T) { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `index` on this type; consider implementing the `std::ops::Index` trait or choosing a less ambiguous name - --> $DIR/methods.rs:119:5 - | -LL | / pub fn index(&self, index: usize) -> &Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `index_mut` on this type; consider implementing the `std::ops::IndexMut` trait or choosing a less ambiguous name - --> $DIR/methods.rs:123:5 - | -LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `into_iter` on this type; consider implementing the `std::iter::IntoIterator` trait or choosing a less ambiguous name - --> $DIR/methods.rs:127:5 - | -LL | / pub fn into_iter(self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `mul` on this type; consider implementing the `std::ops::Mul` trait or choosing a less ambiguous name - --> $DIR/methods.rs:131:5 - | -LL | / pub fn mul(self, rhs: Self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `neg` on this type; consider implementing the `std::ops::Neg` trait or choosing a less ambiguous name - --> $DIR/methods.rs:135:5 - | -LL | / pub fn neg(self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `next` on this type; consider implementing the `std::iter::Iterator` trait or choosing a less ambiguous name - --> $DIR/methods.rs:139:5 - | -LL | / pub fn next(&mut self) -> Option<Self> { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `not` on this type; consider implementing the `std::ops::Not` trait or choosing a less ambiguous name - --> $DIR/methods.rs:143:5 - | -LL | / pub fn not(self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `rem` on this type; consider implementing the `std::ops::Rem` trait or choosing a less ambiguous name - --> $DIR/methods.rs:147:5 - | -LL | / pub fn rem(self, rhs: Self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `shl` on this type; consider implementing the `std::ops::Shl` trait or choosing a less ambiguous name - --> $DIR/methods.rs:151:5 - | -LL | / pub fn shl(self, rhs: Self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `shr` on this type; consider implementing the `std::ops::Shr` trait or choosing a less ambiguous name - --> $DIR/methods.rs:155:5 - | -LL | / pub fn shr(self, rhs: Self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - -error: defining a method called `sub` on this type; consider implementing the `std::ops::Sub` trait or choosing a less ambiguous name - --> $DIR/methods.rs:159:5 - | -LL | / pub fn sub(self, rhs: Self) -> Self { -LL | | unimplemented!() -LL | | } - | |_____^ - error: methods called `new` usually return `Self` - --> $DIR/methods.rs:300:5 + --> $DIR/methods.rs:105:5 | LL | / fn new() -> i32 { LL | | 0 @@ -253,7 +9,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:319:13 + --> $DIR/methods.rs:126:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -262,7 +18,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:322:13 + --> $DIR/methods.rs:129:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -272,7 +28,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:339:22 + --> $DIR/methods.rs:146:22 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)` @@ -280,25 +36,25 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: `-D clippy::search-is-some` implied by `-D warnings` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:340:20 + --> $DIR/methods.rs:147:20 | LL | let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:341:20 + --> $DIR/methods.rs:148:20 | LL | let _ = (0..1).find(|x| *x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:342:22 + --> $DIR/methods.rs:149:22 | LL | let _ = v.iter().find(|x| **x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:345:13 + --> $DIR/methods.rs:152:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -308,13 +64,13 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:351:22 + --> $DIR/methods.rs:158:22 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:354:13 + --> $DIR/methods.rs:161:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -324,13 +80,13 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:360:22 + --> $DIR/methods.rs:167:22 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:363:13 + --> $DIR/methods.rs:170:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -339,5 +95,5 @@ LL | | } LL | | ).is_some(); | |______________________________^ -error: aborting due to 42 previous errors +error: aborting due to 12 previous errors diff --git a/tests/ui/should_impl_trait/corner_cases.rs b/tests/ui/should_impl_trait/corner_cases.rs new file mode 100644 index 00000000000..6c5ffe6aba8 --- /dev/null +++ b/tests/ui/should_impl_trait/corner_cases.rs @@ -0,0 +1,83 @@ +// edition:2018 + +#![warn(clippy::all, clippy::pedantic)] +#![allow( + clippy::missing_errors_doc, + clippy::needless_pass_by_value, + clippy::must_use_candidate, + clippy::unused_self, + clippy::needless_lifetimes, + clippy::missing_safety_doc, + clippy::wrong_self_convention +)] + +use std::ops::Mul; +use std::rc::{self, Rc}; +use std::sync::{self, Arc}; + +fn main() {} + +pub struct T1; +impl T1 { + // corner cases: should not lint + + // no error, not public interface + pub(crate) fn drop(&mut self) {} + + // no error, private function + fn neg(self) -> Self { + self + } + + // no error, private function + fn eq(&self, other: Self) -> bool { + true + } + + // No error; self is a ref. + fn sub(&self, other: Self) -> &Self { + self + } + + // No error; different number of arguments. + fn div(self) -> Self { + self + } + + // No error; wrong return type. + fn rem(self, other: Self) {} + + // Fine + fn into_u32(self) -> u32 { + 0 + } + + fn into_u16(&self) -> u16 { + 0 + } + + fn to_something(self) -> u32 { + 0 + } + + fn new(self) -> Self { + unimplemented!(); + } + + pub fn next<'b>(&'b mut self) -> Option<&'b mut T1> { + unimplemented!(); + } +} + +pub struct T2; +impl T2 { + // Shouldn't trigger lint as it is unsafe. + pub unsafe fn add(self, rhs: Self) -> Self { + self + } + + // Should not trigger lint since this is an async function. + pub async fn next(&mut self) -> Option<Self> { + None + } +} diff --git a/tests/ui/should_impl_trait/method_list_1.rs b/tests/ui/should_impl_trait/method_list_1.rs new file mode 100644 index 00000000000..f8d248fc98d --- /dev/null +++ b/tests/ui/should_impl_trait/method_list_1.rs @@ -0,0 +1,87 @@ +// edition:2018 + +#![warn(clippy::all, clippy::pedantic)] +#![allow( + clippy::missing_errors_doc, + clippy::needless_pass_by_value, + clippy::must_use_candidate, + clippy::unused_self, + clippy::needless_lifetimes, + clippy::missing_safety_doc, + clippy::wrong_self_convention +)] + +use std::ops::Mul; +use std::rc::{self, Rc}; +use std::sync::{self, Arc}; + +fn main() {} +pub struct T; + +impl T { + // ***************************************** + // trait method list part 1, should lint all + // ***************************************** + pub fn add(self, other: T) -> T { + unimplemented!() + } + + pub fn as_mut(&mut self) -> &mut T { + unimplemented!() + } + + pub fn as_ref(&self) -> &T { + unimplemented!() + } + + pub fn bitand(self, rhs: T) -> T { + unimplemented!() + } + + pub fn bitor(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn bitxor(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn borrow(&self) -> &str { + unimplemented!() + } + + pub fn borrow_mut(&mut self) -> &mut str { + unimplemented!() + } + + pub fn clone(&self) -> Self { + unimplemented!() + } + + pub fn cmp(&self, other: &Self) -> Self { + unimplemented!() + } + + pub fn default() -> Self { + unimplemented!() + } + + pub fn deref(&self) -> &Self { + unimplemented!() + } + + pub fn deref_mut(&mut self) -> &mut Self { + unimplemented!() + } + + pub fn div(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn drop(&mut self) { + unimplemented!() + } + // ********** + // part 1 end + // ********** +} diff --git a/tests/ui/should_impl_trait/method_list_1.stderr b/tests/ui/should_impl_trait/method_list_1.stderr new file mode 100644 index 00000000000..2b7d4628c3f --- /dev/null +++ b/tests/ui/should_impl_trait/method_list_1.stderr @@ -0,0 +1,143 @@ +error: method `add` can be confused for the standard trait method `std::ops::Add::add` + --> $DIR/method_list_1.rs:25:5 + | +LL | / pub fn add(self, other: T) -> T { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = note: `-D clippy::should-implement-trait` implied by `-D warnings` + = help: consider implementing the trait `std::ops::Add` or choosing a less ambiguous method name + +error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut` + --> $DIR/method_list_1.rs:29:5 + | +LL | / pub fn as_mut(&mut self) -> &mut T { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name + +error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref` + --> $DIR/method_list_1.rs:33:5 + | +LL | / pub fn as_ref(&self) -> &T { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name + +error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand` + --> $DIR/method_list_1.rs:37:5 + | +LL | / pub fn bitand(self, rhs: T) -> T { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name + +error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor` + --> $DIR/method_list_1.rs:41:5 + | +LL | / pub fn bitor(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name + +error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor` + --> $DIR/method_list_1.rs:45:5 + | +LL | / pub fn bitxor(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name + +error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow` + --> $DIR/method_list_1.rs:49:5 + | +LL | / pub fn borrow(&self) -> &str { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name + +error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut` + --> $DIR/method_list_1.rs:53:5 + | +LL | / pub fn borrow_mut(&mut self) -> &mut str { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name + +error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone` + --> $DIR/method_list_1.rs:57:5 + | +LL | / pub fn clone(&self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name + +error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp` + --> $DIR/method_list_1.rs:61:5 + | +LL | / pub fn cmp(&self, other: &Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name + +error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref` + --> $DIR/method_list_1.rs:69:5 + | +LL | / pub fn deref(&self) -> &Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name + +error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut` + --> $DIR/method_list_1.rs:73:5 + | +LL | / pub fn deref_mut(&mut self) -> &mut Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name + +error: method `div` can be confused for the standard trait method `std::ops::Div::div` + --> $DIR/method_list_1.rs:77:5 + | +LL | / pub fn div(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name + +error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop` + --> $DIR/method_list_1.rs:81:5 + | +LL | / pub fn drop(&mut self) { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Drop` or choosing a less ambiguous method name + +error: aborting due to 14 previous errors + diff --git a/tests/ui/should_impl_trait/method_list_2.rs b/tests/ui/should_impl_trait/method_list_2.rs new file mode 100644 index 00000000000..ed5e0d384bf --- /dev/null +++ b/tests/ui/should_impl_trait/method_list_2.rs @@ -0,0 +1,88 @@ +// edition:2018 + +#![warn(clippy::all, clippy::pedantic)] +#![allow( + clippy::missing_errors_doc, + clippy::needless_pass_by_value, + clippy::must_use_candidate, + clippy::unused_self, + clippy::needless_lifetimes, + clippy::missing_safety_doc, + clippy::wrong_self_convention +)] + +use std::ops::Mul; +use std::rc::{self, Rc}; +use std::sync::{self, Arc}; + +fn main() {} +pub struct T; + +impl T { + // ***************************************** + // trait method list part 2, should lint all + // ***************************************** + + pub fn eq(&self, other: &Self) -> bool { + unimplemented!() + } + + pub fn from_iter<T>(iter: T) -> Self { + unimplemented!() + } + + pub fn from_str(s: &str) -> Result<Self, Self> { + unimplemented!() + } + + pub fn hash(&self, state: &mut T) { + unimplemented!() + } + + pub fn index(&self, index: usize) -> &Self { + unimplemented!() + } + + pub fn index_mut(&mut self, index: usize) -> &mut Self { + unimplemented!() + } + + pub fn into_iter(self) -> Self { + unimplemented!() + } + + pub fn mul(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn neg(self) -> Self { + unimplemented!() + } + + pub fn next(&mut self) -> Option<Self> { + unimplemented!() + } + + pub fn not(self) -> Self { + unimplemented!() + } + + pub fn rem(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn shl(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn shr(self, rhs: Self) -> Self { + unimplemented!() + } + + pub fn sub(self, rhs: Self) -> Self { + unimplemented!() + } + // ********** + // part 2 end + // ********** +} diff --git a/tests/ui/should_impl_trait/method_list_2.stderr b/tests/ui/should_impl_trait/method_list_2.stderr new file mode 100644 index 00000000000..b6fd4356956 --- /dev/null +++ b/tests/ui/should_impl_trait/method_list_2.stderr @@ -0,0 +1,153 @@ +error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq` + --> $DIR/method_list_2.rs:26:5 + | +LL | / pub fn eq(&self, other: &Self) -> bool { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = note: `-D clippy::should-implement-trait` implied by `-D warnings` + = help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name + +error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter` + --> $DIR/method_list_2.rs:30:5 + | +LL | / pub fn from_iter<T>(iter: T) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name + +error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` + --> $DIR/method_list_2.rs:34:5 + | +LL | / pub fn from_str(s: &str) -> Result<Self, Self> { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name + +error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash` + --> $DIR/method_list_2.rs:38:5 + | +LL | / pub fn hash(&self, state: &mut T) { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name + +error: method `index` can be confused for the standard trait method `std::ops::Index::index` + --> $DIR/method_list_2.rs:42:5 + | +LL | / pub fn index(&self, index: usize) -> &Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name + +error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut` + --> $DIR/method_list_2.rs:46:5 + | +LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name + +error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter` + --> $DIR/method_list_2.rs:50:5 + | +LL | / pub fn into_iter(self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name + +error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul` + --> $DIR/method_list_2.rs:54:5 + | +LL | / pub fn mul(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name + +error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg` + --> $DIR/method_list_2.rs:58:5 + | +LL | / pub fn neg(self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name + +error: method `next` can be confused for the standard trait method `std::iter::Iterator::next` + --> $DIR/method_list_2.rs:62:5 + | +LL | / pub fn next(&mut self) -> Option<Self> { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name + +error: method `not` can be confused for the standard trait method `std::ops::Not::not` + --> $DIR/method_list_2.rs:66:5 + | +LL | / pub fn not(self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name + +error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem` + --> $DIR/method_list_2.rs:70:5 + | +LL | / pub fn rem(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name + +error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl` + --> $DIR/method_list_2.rs:74:5 + | +LL | / pub fn shl(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name + +error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr` + --> $DIR/method_list_2.rs:78:5 + | +LL | / pub fn shr(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name + +error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub` + --> $DIR/method_list_2.rs:82:5 + | +LL | / pub fn sub(self, rhs: Self) -> Self { +LL | | unimplemented!() +LL | | } + | |_____^ + | + = help: consider implementing the trait `std::ops::Sub` or choosing a less ambiguous method name + +error: aborting due to 15 previous errors + From f9ba829f6701ae03a5c226044dbbde13ce87e123 Mon Sep 17 00:00:00 2001 From: Tim Nielens <tim.nielens@gmail.com> Date: Sun, 9 Aug 2020 15:35:41 +0200 Subject: [PATCH 375/526] should_impl_trait - self linting --- clippy_lints/src/methods/mod.rs | 67 +++++++++++++++++---------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index a549c3b78ef..07e55ab0762 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1470,6 +1470,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { } } + #[allow(clippy::too_many_lines)] fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { if in_external_macro(cx.sess(), impl_item.span) { return; @@ -1501,7 +1502,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { sig.decl.inputs.len() == method_config.param_count && method_config.output_type.matches(cx, &sig.decl.output) && method_config.self_kind.matches(cx, self_ty, first_arg_ty) && - fn_header_equals(*method_config.fn_header, sig.header) && + fn_header_equals(method_config.fn_header, sig.header) && method_config.lifetime_param_cond(&impl_item) { span_lint_and_help( @@ -3422,7 +3423,7 @@ struct ShouldImplTraitCase { trait_name: &'static str, method_name: &'static str, param_count: usize, - fn_header: &'static hir::FnHeader, + fn_header: hir::FnHeader, // implicit self kind expected (none, self, &self, ...) self_kind: SelfKind, // checks against the output type @@ -3435,7 +3436,7 @@ impl ShouldImplTraitCase { trait_name: &'static str, method_name: &'static str, param_count: usize, - fn_header: &'static hir::FnHeader, + fn_header: hir::FnHeader, self_kind: SelfKind, output_type: OutType, lint_explicit_lifetime: bool, @@ -3466,37 +3467,37 @@ impl ShouldImplTraitCase { #[rustfmt::skip] const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [ - ShouldImplTraitCase::new("std::ops::Add", "add", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::convert::AsMut", "as_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, true), - ShouldImplTraitCase::new("std::convert::AsRef", "as_ref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, true), - ShouldImplTraitCase::new("std::ops::BitAnd", "bitand", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::ops::BitOr", "bitor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::ops::BitXor", "bitxor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::borrow::Borrow", "borrow", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, true), - ShouldImplTraitCase::new("std::borrow::BorrowMut", "borrow_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, true), - ShouldImplTraitCase::new("std::clone::Clone", "clone", 1, &FN_HEADER, SelfKind::Ref, OutType::Any, true), - ShouldImplTraitCase::new("std::cmp::Ord", "cmp", 2, &FN_HEADER, SelfKind::Ref, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Add", "add", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::convert::AsMut", "as_mut", 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true), + ShouldImplTraitCase::new("std::convert::AsRef", "as_ref", 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true), + ShouldImplTraitCase::new("std::ops::BitAnd", "bitand", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::BitOr", "bitor", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::BitXor", "bitxor", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::borrow::Borrow", "borrow", 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true), + ShouldImplTraitCase::new("std::borrow::BorrowMut", "borrow_mut", 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true), + ShouldImplTraitCase::new("std::clone::Clone", "clone", 1, FN_HEADER, SelfKind::Ref, OutType::Any, true), + ShouldImplTraitCase::new("std::cmp::Ord", "cmp", 2, FN_HEADER, SelfKind::Ref, OutType::Any, true), // FIXME: default doesn't work - ShouldImplTraitCase::new("std::default::Default", "default", 0, &FN_HEADER, SelfKind::No, OutType::Any, true), - ShouldImplTraitCase::new("std::ops::Deref", "deref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, true), - ShouldImplTraitCase::new("std::ops::DerefMut", "deref_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, true), - ShouldImplTraitCase::new("std::ops::Div", "div", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::ops::Drop", "drop", 1, &FN_HEADER, SelfKind::RefMut, OutType::Unit, true), - ShouldImplTraitCase::new("std::cmp::PartialEq", "eq", 2, &FN_HEADER, SelfKind::Ref, OutType::Bool, true), - ShouldImplTraitCase::new("std::iter::FromIterator", "from_iter", 1, &FN_HEADER, SelfKind::No, OutType::Any, true), - ShouldImplTraitCase::new("std::str::FromStr", "from_str", 1, &FN_HEADER, SelfKind::No, OutType::Any, true), - ShouldImplTraitCase::new("std::hash::Hash", "hash", 2, &FN_HEADER, SelfKind::Ref, OutType::Unit, true), - ShouldImplTraitCase::new("std::ops::Index", "index", 2, &FN_HEADER, SelfKind::Ref, OutType::Ref, true), - ShouldImplTraitCase::new("std::ops::IndexMut", "index_mut", 2, &FN_HEADER, SelfKind::RefMut, OutType::Ref, true), - ShouldImplTraitCase::new("std::iter::IntoIterator", "into_iter", 1, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::ops::Mul", "mul", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::ops::Neg", "neg", 1, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::iter::Iterator", "next", 1, &FN_HEADER, SelfKind::RefMut, OutType::Any, false), - ShouldImplTraitCase::new("std::ops::Not", "not", 1, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::ops::Rem", "rem", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::ops::Shl", "shl", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::ops::Shr", "shr", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), - ShouldImplTraitCase::new("std::ops::Sub", "sub", 2, &FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::default::Default", "default", 0, FN_HEADER, SelfKind::No, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Deref", "deref", 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true), + ShouldImplTraitCase::new("std::ops::DerefMut", "deref_mut", 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true), + ShouldImplTraitCase::new("std::ops::Div", "div", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Drop", "drop", 1, FN_HEADER, SelfKind::RefMut, OutType::Unit, true), + ShouldImplTraitCase::new("std::cmp::PartialEq", "eq", 2, FN_HEADER, SelfKind::Ref, OutType::Bool, true), + ShouldImplTraitCase::new("std::iter::FromIterator", "from_iter", 1, FN_HEADER, SelfKind::No, OutType::Any, true), + ShouldImplTraitCase::new("std::str::FromStr", "from_str", 1, FN_HEADER, SelfKind::No, OutType::Any, true), + ShouldImplTraitCase::new("std::hash::Hash", "hash", 2, FN_HEADER, SelfKind::Ref, OutType::Unit, true), + ShouldImplTraitCase::new("std::ops::Index", "index", 2, FN_HEADER, SelfKind::Ref, OutType::Ref, true), + ShouldImplTraitCase::new("std::ops::IndexMut", "index_mut", 2, FN_HEADER, SelfKind::RefMut, OutType::Ref, true), + ShouldImplTraitCase::new("std::iter::IntoIterator", "into_iter", 1, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Mul", "mul", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Neg", "neg", 1, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::iter::Iterator", "next", 1, FN_HEADER, SelfKind::RefMut, OutType::Any, false), + ShouldImplTraitCase::new("std::ops::Not", "not", 1, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Rem", "rem", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Shl", "shl", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Shr", "shr", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), + ShouldImplTraitCase::new("std::ops::Sub", "sub", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), ]; #[rustfmt::skip] From 6af969379e766bf85652196c04ff267edf5cace7 Mon Sep 17 00:00:00 2001 From: Dmitry Murzin <diralik@yandex.ru> Date: Sun, 9 Aug 2020 22:21:09 +0500 Subject: [PATCH 376/526] Prevent compile parts of rustc when using `cargo dev ra-setup` --- clippy_dev/src/ra_setup.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_dev/src/ra_setup.rs b/clippy_dev/src/ra_setup.rs index 8617445c8a6..f2bd651ab25 100644 --- a/clippy_dev/src/ra_setup.rs +++ b/clippy_dev/src/ra_setup.rs @@ -68,10 +68,11 @@ fn inject_deps_into_manifest( }); // format a new [dependencies]-block with the new deps we need to inject - let mut all_deps = String::from("[dependencies]\n"); + let mut all_deps = String::from("[target.'cfg(NOT_A_PLATFORM)'.dependencies]\n"); new_deps.for_each(|dep_line| { all_deps.push_str(&dep_line); }); + all_deps.push_str("\n[dependencies]\n"); // replace "[dependencies]" with // [dependencies] From 3e3e50bf0fa6282c7265e34589170033c2301edd Mon Sep 17 00:00:00 2001 From: Ryan Wiedemann <Ryan1729@gmail.com> Date: Mon, 10 Aug 2020 08:50:20 -0600 Subject: [PATCH 377/526] Add example of false positive to PTR_ARG docs. Fixes #214 --- clippy_lints/src/ptr.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 7b6bd69ffca..33c1bbd488a 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -36,14 +36,27 @@ declare_clippy_lint! { /// argument may also fail to compile if you change the argument. Applying /// this lint on them will fix the problem, but they may be in other crates. /// + /// One notable example of a function that may cause issues, and which cannot + /// easily be changed due to beinng in the standard library is `Vec::contains`. + /// when called on a `Vec<Vec<T>>`. If a `&Vec` is passed to that method then + /// it will compile, but if a `&[T]` is passed then it will not compile. + /// + /// ```ignore + /// fn cannot_take_a_slice(v: &Vec<u8>) -> bool { + /// let vec_of_vecs: Vec<Vec<u8>> = some_other_fn(); + /// + /// vec_of_vecs.contains(v) + /// } + /// ``` + /// /// Also there may be `fn(&Vec)`-typed references pointing to your function. /// If you have them, you will get a compiler error after applying this lint's /// suggestions. You then have the choice to undo your changes or change the /// type of the reference. /// /// Note that if the function is part of your public interface, there may be - /// other crates referencing it you may not be aware. Carefully deprecate the - /// function before applying the lint suggestions in this case. + /// other crates referencing it, of which you may not be aware. Carefully + /// deprecate the function before applying the lint suggestions in this case. /// /// **Example:** /// ```ignore From fbf637d12c95528846bfa65ce67bd652f2affb43 Mon Sep 17 00:00:00 2001 From: Ryan Wiedemann <Ryan1729@gmail.com> Date: Mon, 10 Aug 2020 09:19:40 -0600 Subject: [PATCH 378/526] formatting --- clippy_lints/src/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 33c1bbd488a..7f58a381adc 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -55,7 +55,7 @@ declare_clippy_lint! { /// type of the reference. /// /// Note that if the function is part of your public interface, there may be - /// other crates referencing it, of which you may not be aware. Carefully + /// other crates referencing it, of which you may not be aware. Carefully /// deprecate the function before applying the lint suggestions in this case. /// /// **Example:** From 82c816ee022c420306c6a7475162f252a8432c30 Mon Sep 17 00:00:00 2001 From: robojumper <robojumper@gmail.com> Date: Mon, 10 Aug 2020 17:45:04 +0200 Subject: [PATCH 379/526] Fix CHANGELOG's commit range links Two most recent links linked to the wrong range changelog: none --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f09af0466c0..9d957371c6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,13 @@ document. ## Unreleased / In Rust Nightly -[c2c07fa...master](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...master) +[c2c07fa...master](https://github.com/rust-lang/rust-clippy/compare/c2c07fa...master) ## Rust 1.46 Current beta, release 2020-08-27 -[7ea7cd1...c2c07fa](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...master) +[7ea7cd1...c2c07fa](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...c2c07fa) ### New lints From e57aafe33f338208e612ecb816a948d28f2c3741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 15:06:33 +0200 Subject: [PATCH 380/526] too-many-lines: make lint adhere to lint message convention --- clippy_lints/src/functions.rs | 2 +- tests/ui-toml/functions_maxlines/test.stderr | 4 ++-- tests/ui/functions_maxlines.stderr | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 28b276967bc..ac1c7aa9bbb 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -374,7 +374,7 @@ impl<'tcx> Functions { } if line_count > self.max_lines { - span_lint(cx, TOO_MANY_LINES, span, "This function has a large number of lines.") + span_lint(cx, TOO_MANY_LINES, span, "this function has a large number of lines") } } diff --git a/tests/ui-toml/functions_maxlines/test.stderr b/tests/ui-toml/functions_maxlines/test.stderr index 4b77ac551e7..fb12257021a 100644 --- a/tests/ui-toml/functions_maxlines/test.stderr +++ b/tests/ui-toml/functions_maxlines/test.stderr @@ -1,4 +1,4 @@ -error: This function has a large number of lines. +error: this function has a large number of lines --> $DIR/test.rs:18:1 | LL | / fn too_many_lines() { @@ -9,7 +9,7 @@ LL | | } | = note: `-D clippy::too-many-lines` implied by `-D warnings` -error: This function has a large number of lines. +error: this function has a large number of lines --> $DIR/test.rs:38:1 | LL | / fn comment_before_code() { diff --git a/tests/ui/functions_maxlines.stderr b/tests/ui/functions_maxlines.stderr index 9b0e7550cc3..c640c82d6d7 100644 --- a/tests/ui/functions_maxlines.stderr +++ b/tests/ui/functions_maxlines.stderr @@ -1,4 +1,4 @@ -error: This function has a large number of lines. +error: this function has a large number of lines --> $DIR/functions_maxlines.rs:58:1 | LL | / fn bad_lines() { From 0876f17d77e8747f4cba889bd29fb64a0dc1a63f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 15:14:12 +0200 Subject: [PATCH 381/526] bool-comparison: make lint adhere to lint message convention --- clippy_lints/src/needless_bool.rs | 2 +- tests/ui/bool_comparison.stderr | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 8e44f2ec240..dc5aa669139 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -243,7 +243,7 @@ fn check_comparison<'a, 'tcx>( cx, BOOL_COMPARISON, e.span, - "This comparison might be written more concisely", + "this comparison might be written more concisely", "try simplifying it as shown", format!( "{} != {}", diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index eeb1f20ee89..55d94b8257d 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -84,25 +84,25 @@ error: order comparisons between booleans can be simplified LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` -error: This comparison might be written more concisely +error: this comparison might be written more concisely --> $DIR/bool_comparison.rs:120:8 | LL | if a == !b {}; | ^^^^^^^ help: try simplifying it as shown: `a != b` -error: This comparison might be written more concisely +error: this comparison might be written more concisely --> $DIR/bool_comparison.rs:121:8 | LL | if !a == b {}; | ^^^^^^^ help: try simplifying it as shown: `a != b` -error: This comparison might be written more concisely +error: this comparison might be written more concisely --> $DIR/bool_comparison.rs:125:8 | LL | if b == !a {}; | ^^^^^^^ help: try simplifying it as shown: `b != a` -error: This comparison might be written more concisely +error: this comparison might be written more concisely --> $DIR/bool_comparison.rs:126:8 | LL | if !b == a {}; From fd379a889e25c94c0568fe6fc08d0783bcbc3dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 15:16:10 +0200 Subject: [PATCH 382/526] builtin-type-shadow: make lint adhere to lint message convention --- clippy_lints/src/misc_early.rs | 2 +- tests/ui/builtin-type-shadow.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 29aba7c1218..38b11c5e733 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -271,7 +271,7 @@ impl EarlyLintPass for MiscEarlyLints { cx, BUILTIN_TYPE_SHADOW, param.ident.span, - &format!("This generic shadows the built-in type `{}`", name), + &format!("this generic shadows the built-in type `{}`", name), ); } } diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index bc785b075e0..f42b246afd2 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -1,4 +1,4 @@ -error: This generic shadows the built-in type `u32` +error: this generic shadows the built-in type `u32` --> $DIR/builtin-type-shadow.rs:4:8 | LL | fn foo<u32>(a: u32) -> u32 { From 40416c0fa8409da63fb27f065e82cabb51ec17d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 15:18:13 +0200 Subject: [PATCH 383/526] naive_bytecount: make lint adhere to lint message convention --- clippy_lints/src/bytecount.rs | 4 ++-- tests/ui/bytecount.stderr | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index dde799fcae4..cdb49d777d8 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -82,8 +82,8 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount { cx, NAIVE_BYTECOUNT, expr.span, - "You appear to be counting bytes the naive way", - "Consider using the bytecount crate", + "you appear to be counting bytes the naive way", + "consider using the bytecount crate", format!("bytecount::count({}, {})", snippet_with_applicability(cx, haystack.span, "..", &mut applicability), snippet_with_applicability(cx, needle.span, "..", &mut applicability)), diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr index 436f5d86a06..1dc37fc8b25 100644 --- a/tests/ui/bytecount.stderr +++ b/tests/ui/bytecount.stderr @@ -1,8 +1,8 @@ -error: You appear to be counting bytes the naive way +error: you appear to be counting bytes the naive way --> $DIR/bytecount.rs:5:13 | LL | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, 0)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the bytecount crate: `bytecount::count(x, 0)` | note: the lint level is defined here --> $DIR/bytecount.rs:1:8 @@ -10,17 +10,17 @@ note: the lint level is defined here LL | #[deny(clippy::naive_bytecount)] | ^^^^^^^^^^^^^^^^^^^^^^^ -error: You appear to be counting bytes the naive way +error: you appear to be counting bytes the naive way --> $DIR/bytecount.rs:7:13 | LL | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count((&x[..]), 0)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the bytecount crate: `bytecount::count((&x[..]), 0)` -error: You appear to be counting bytes the naive way +error: you appear to be counting bytes the naive way --> $DIR/bytecount.rs:19:13 | LL | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider using the bytecount crate: `bytecount::count(x, b + 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the bytecount crate: `bytecount::count(x, b + 1)` error: aborting due to 3 previous errors From 5d66bd7bb3fd701d70ec11217e3f89fabe5cb0a7 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Mon, 10 Aug 2020 23:38:58 +0200 Subject: [PATCH 384/526] Avoid or_fun_call for const_fn with no args --- clippy_lints/src/utils/mod.rs | 9 +++++++++ tests/ui/or_fun_call.fixed | 8 ++++++++ tests/ui/or_fun_call.rs | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 9f967d59c8b..223628cc610 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -43,6 +43,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::ty::{self, layout::IntegerExt, subst::GenericArg, Ty, TyCtxt, TypeFoldable}; +use rustc_mir::const_eval; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::original_sp; use rustc_span::symbol::{self, kw, Symbol}; @@ -868,11 +869,19 @@ pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { /// Checks if an expression is constructing a tuple-like enum variant or struct pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + fn has_no_arguments(cx: &LateContext<'_>, def_id: DefId) -> bool { + cx.tcx.fn_sig(def_id).skip_binder().inputs().is_empty() + } + if let ExprKind::Call(ref fun, _) = expr.kind { if let ExprKind::Path(ref qp) = fun.kind { let res = cx.qpath_res(qp, fun.hir_id); return match res { def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true, + // FIXME: check the constness of the arguments, see https://github.com/rust-lang/rust-clippy/pull/5682#issuecomment-638681210 + def::Res::Def(DefKind::Fn, def_id) if has_no_arguments(cx, def_id) => { + const_eval::is_const_fn(cx.tcx, def_id) + }, def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id), _ => false, }; diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index 2045ffdb5f0..67faa8bd4a0 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -116,4 +116,12 @@ fn f() -> Option<()> { Some(()) } +// Issue 5886 - const fn (with no arguments) +pub fn skip_const_fn_with_no_args() { + const fn foo() -> Option<i32> { + Some(42) + } + let _ = None.or(foo()); +} + fn main() {} diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 522f31b72d0..9867e2eedcf 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -116,4 +116,12 @@ fn f() -> Option<()> { Some(()) } +// Issue 5886 - const fn (with no arguments) +pub fn skip_const_fn_with_no_args() { + const fn foo() -> Option<i32> { + Some(42) + } + let _ = None.or(foo()); +} + fn main() {} From 9b7ab1d38b13ad8af555793cdf7ce08c12c22595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 16:58:20 +0200 Subject: [PATCH 385/526] checked-conversions: make lint adhere to lint message convention --- clippy_lints/src/checked_conversions.rs | 2 +- tests/ui/checked_conversions.stderr | 32 ++++++++++++------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index 841902943f0..28c1a54d2c5 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for CheckedConversions { cx, CHECKED_CONVERSIONS, item.span, - "Checked cast can be simplified.", + "checked cast can be simplified", "try", format!("{}::try_from({}).is_ok()", to_type, snippet), applicability, diff --git a/tests/ui/checked_conversions.stderr b/tests/ui/checked_conversions.stderr index 648ba3ccd01..18518def0ac 100644 --- a/tests/ui/checked_conversions.stderr +++ b/tests/ui/checked_conversions.stderr @@ -1,4 +1,4 @@ -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:17:13 | LL | let _ = value <= (u32::max_value() as i64) && value >= 0; @@ -6,91 +6,91 @@ LL | let _ = value <= (u32::max_value() as i64) && value >= 0; | = note: `-D clippy::checked-conversions` implied by `-D warnings` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:18:13 | LL | let _ = value <= (u32::MAX as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:22:13 | LL | let _ = value <= i64::from(u16::max_value()) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:23:13 | LL | let _ = value <= i64::from(u16::MAX) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:27:13 | LL | let _ = value <= (u8::max_value() as isize) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:28:13 | LL | let _ = value <= (u8::MAX as isize) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:34:13 | LL | let _ = value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:35:13 | LL | let _ = value <= (i32::MAX as i64) && value >= (i32::MIN as i64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:39:13 | LL | let _ = value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:40:13 | LL | let _ = value <= i64::from(i16::MAX) && value >= i64::from(i16::MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:46:13 | LL | let _ = value <= i32::max_value() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:47:13 | LL | let _ = value <= i32::MAX as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:51:13 | LL | let _ = value <= isize::max_value() as usize && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:52:13 | LL | let _ = value <= isize::MAX as usize && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:56:13 | LL | let _ = value <= u16::max_value() as u32 && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` -error: Checked cast can be simplified. +error: checked cast can be simplified --> $DIR/checked_conversions.rs:57:13 | LL | let _ = value <= u16::MAX as u32 && value as i32 == 5; From 8679dd375b928a3a5d8420401ed80057eea6f198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 17:06:29 +0200 Subject: [PATCH 386/526] unnecessary_unwrap, panicking_unwrap: make lints adhere to lint message convention --- clippy_lints/src/unwrap.rs | 6 +-- .../complex_conditionals.stderr | 40 +++++++++---------- .../complex_conditionals_nested.stderr | 4 +- .../checked_unwrap/simple_conditionals.stderr | 26 ++++++------ 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index f2bbde28c2a..fd755dcc790 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -181,8 +181,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { self.cx, UNNECESSARY_UNWRAP, expr.span, - &format!("You checked before that `{}()` cannot fail. \ - Instead of checking and unwrapping, it's better to use `if let` or `match`.", + &format!("you checked before that `{}()` cannot fail. \ + Instead of checking and unwrapping, it's better to use `if let` or `match`", method_name.ident.name), |diag| { diag.span_label(unwrappable.check.span, "the check is happening here"); }, ); @@ -191,7 +191,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { self.cx, PANICKING_UNWRAP, expr.span, - &format!("This call to `{}()` will always panic.", + &format!("this call to `{}()` will always panic", method_name.ident.name), |diag| { diag.span_label(unwrappable.check.span, "because of this check"); }, ); diff --git a/tests/ui/checked_unwrap/complex_conditionals.stderr b/tests/ui/checked_unwrap/complex_conditionals.stderr index dc666bab460..5b62dca629f 100644 --- a/tests/ui/checked_unwrap/complex_conditionals.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals.stderr @@ -1,4 +1,4 @@ -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:8:9 | LL | if x.is_ok() && y.is_err() { @@ -12,7 +12,7 @@ note: the lint level is defined here LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: This call to `unwrap_err()` will always panic. +error: this call to `unwrap_err()` will always panic --> $DIR/complex_conditionals.rs:9:9 | LL | if x.is_ok() && y.is_err() { @@ -27,7 +27,7 @@ note: the lint level is defined here LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/complex_conditionals.rs:10:9 | LL | if x.is_ok() && y.is_err() { @@ -36,7 +36,7 @@ LL | if x.is_ok() && y.is_err() { LL | y.unwrap(); // will panic | ^^^^^^^^^^ -error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:11:9 | LL | if x.is_ok() && y.is_err() { @@ -45,7 +45,7 @@ LL | if x.is_ok() && y.is_err() { LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/complex_conditionals.rs:25:9 | LL | if x.is_ok() || y.is_ok() { @@ -54,7 +54,7 @@ LL | if x.is_ok() || y.is_ok() { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:26:9 | LL | if x.is_ok() || y.is_ok() { @@ -63,7 +63,7 @@ LL | if x.is_ok() || y.is_ok() { LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/complex_conditionals.rs:27:9 | LL | if x.is_ok() || y.is_ok() { @@ -72,7 +72,7 @@ LL | if x.is_ok() || y.is_ok() { LL | y.unwrap(); // will panic | ^^^^^^^^^^ -error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:28:9 | LL | if x.is_ok() || y.is_ok() { @@ -81,7 +81,7 @@ LL | if x.is_ok() || y.is_ok() { LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:32:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { @@ -89,7 +89,7 @@ LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ -error: This call to `unwrap_err()` will always panic. +error: this call to `unwrap_err()` will always panic --> $DIR/complex_conditionals.rs:33:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { @@ -98,7 +98,7 @@ LL | x.unwrap(); // unnecessary LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/complex_conditionals.rs:34:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { @@ -107,7 +107,7 @@ LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { LL | y.unwrap(); // will panic | ^^^^^^^^^^ -error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:35:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { @@ -116,7 +116,7 @@ LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:36:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { @@ -125,7 +125,7 @@ LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { LL | z.unwrap(); // unnecessary | ^^^^^^^^^^ -error: This call to `unwrap_err()` will always panic. +error: this call to `unwrap_err()` will always panic --> $DIR/complex_conditionals.rs:37:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { @@ -134,7 +134,7 @@ LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { LL | z.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/complex_conditionals.rs:45:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { @@ -143,7 +143,7 @@ LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:46:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { @@ -152,7 +152,7 @@ LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:47:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { @@ -161,7 +161,7 @@ LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { LL | y.unwrap(); // unnecessary | ^^^^^^^^^^ -error: This call to `unwrap_err()` will always panic. +error: this call to `unwrap_err()` will always panic --> $DIR/complex_conditionals.rs:48:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { @@ -170,7 +170,7 @@ LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { LL | y.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/complex_conditionals.rs:49:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { @@ -179,7 +179,7 @@ LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { LL | z.unwrap(); // will panic | ^^^^^^^^^^ -error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:50:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr index e4d085470c3..46ffc16c23e 100644 --- a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr @@ -1,4 +1,4 @@ -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals_nested.rs:8:13 | LL | if x.is_some() { @@ -12,7 +12,7 @@ note: the lint level is defined here LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/complex_conditionals_nested.rs:10:13 | LL | if x.is_some() { diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr index 4013d1ed667..bf4b6c93098 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -1,4 +1,4 @@ -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:39:9 | LL | if x.is_some() { @@ -12,7 +12,7 @@ note: the lint level is defined here LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/simple_conditionals.rs:41:9 | LL | if x.is_some() { @@ -27,7 +27,7 @@ note: the lint level is defined here LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/simple_conditionals.rs:44:9 | LL | if x.is_none() { @@ -35,7 +35,7 @@ LL | if x.is_none() { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:46:9 | LL | if x.is_none() { @@ -44,7 +44,7 @@ LL | if x.is_none() { LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:7:13 | LL | if $a.is_some() { @@ -57,7 +57,7 @@ LL | m!(x); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:54:9 | LL | if x.is_ok() { @@ -65,7 +65,7 @@ LL | if x.is_ok() { LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ -error: This call to `unwrap_err()` will always panic. +error: this call to `unwrap_err()` will always panic --> $DIR/simple_conditionals.rs:55:9 | LL | if x.is_ok() { @@ -74,7 +74,7 @@ LL | x.unwrap(); // unnecessary LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/simple_conditionals.rs:57:9 | LL | if x.is_ok() { @@ -83,7 +83,7 @@ LL | if x.is_ok() { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:58:9 | LL | if x.is_ok() { @@ -92,7 +92,7 @@ LL | if x.is_ok() { LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. +error: this call to `unwrap()` will always panic --> $DIR/simple_conditionals.rs:61:9 | LL | if x.is_err() { @@ -100,7 +100,7 @@ LL | if x.is_err() { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:62:9 | LL | if x.is_err() { @@ -109,7 +109,7 @@ LL | x.unwrap(); // will panic LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. +error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:64:9 | LL | if x.is_err() { @@ -118,7 +118,7 @@ LL | if x.is_err() { LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ -error: This call to `unwrap_err()` will always panic. +error: this call to `unwrap_err()` will always panic --> $DIR/simple_conditionals.rs:65:9 | LL | if x.is_err() { From 3d592b515492c8d054583078163c1986c44e222a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 19:21:31 +0200 Subject: [PATCH 387/526] cmp_null: make lint adhere to lint message convention --- clippy_lints/src/ptr.rs | 2 +- tests/ui/cmp_null.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 7b6bd69ffca..460d631fab0 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -145,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { cx, CMP_NULL, expr.span, - "Comparing with null is better expressed by the `.is_null()` method", + "comparing with null is better expressed by the `.is_null()` method", ); } } diff --git a/tests/ui/cmp_null.stderr b/tests/ui/cmp_null.stderr index b563a2ebec2..a1f4c70fb27 100644 --- a/tests/ui/cmp_null.stderr +++ b/tests/ui/cmp_null.stderr @@ -1,4 +1,4 @@ -error: Comparing with null is better expressed by the `.is_null()` method +error: comparing with null is better expressed by the `.is_null()` method --> $DIR/cmp_null.rs:9:8 | LL | if p == ptr::null() { @@ -6,7 +6,7 @@ LL | if p == ptr::null() { | = note: `-D clippy::cmp-null` implied by `-D warnings` -error: Comparing with null is better expressed by the `.is_null()` method +error: comparing with null is better expressed by the `.is_null()` method --> $DIR/cmp_null.rs:14:8 | LL | if m == ptr::null_mut() { From 6b0a6a70f8dfa743707c440fdf908b9aceb1b8ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 19:39:35 +0200 Subject: [PATCH 388/526] default-trait-access: make lint adhere to lint message convention --- clippy_lints/src/default_trait_access.rs | 2 +- tests/ui/default_trait_access.stderr | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index ea244768129..874e19d9e9f 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess { cx, DEFAULT_TRAIT_ACCESS, expr.span, - &format!("Calling `{}` is more clear than this expression", replacement), + &format!("calling `{}` is more clear than this expression", replacement), "try", replacement, Applicability::Unspecified, // First resolve the TODO above diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index 453760c6b92..26b2057548b 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -1,4 +1,4 @@ -error: Calling `std::string::String::default()` is more clear than this expression +error: calling `std::string::String::default()` is more clear than this expression --> $DIR/default_trait_access.rs:8:22 | LL | let s1: String = Default::default(); @@ -6,43 +6,43 @@ LL | let s1: String = Default::default(); | = note: `-D clippy::default-trait-access` implied by `-D warnings` -error: Calling `std::string::String::default()` is more clear than this expression +error: calling `std::string::String::default()` is more clear than this expression --> $DIR/default_trait_access.rs:12:22 | LL | let s3: String = D2::default(); | ^^^^^^^^^^^^^ help: try: `std::string::String::default()` -error: Calling `std::string::String::default()` is more clear than this expression +error: calling `std::string::String::default()` is more clear than this expression --> $DIR/default_trait_access.rs:14:22 | LL | let s4: String = std::default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` -error: Calling `std::string::String::default()` is more clear than this expression +error: calling `std::string::String::default()` is more clear than this expression --> $DIR/default_trait_access.rs:18:22 | LL | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` -error: Calling `GenericDerivedDefault<std::string::String>::default()` is more clear than this expression +error: calling `GenericDerivedDefault<std::string::String>::default()` is more clear than this expression --> $DIR/default_trait_access.rs:28:46 | LL | let s11: GenericDerivedDefault<String> = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault<std::string::String>::default()` -error: Calling `TupleDerivedDefault::default()` is more clear than this expression +error: calling `TupleDerivedDefault::default()` is more clear than this expression --> $DIR/default_trait_access.rs:34:36 | LL | let s14: TupleDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` -error: Calling `ArrayDerivedDefault::default()` is more clear than this expression +error: calling `ArrayDerivedDefault::default()` is more clear than this expression --> $DIR/default_trait_access.rs:36:36 | LL | let s15: ArrayDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` -error: Calling `TupleStructDerivedDefault::default()` is more clear than this expression +error: calling `TupleStructDerivedDefault::default()` is more clear than this expression --> $DIR/default_trait_access.rs:40:42 | LL | let s17: TupleStructDerivedDefault = Default::default(); From ba7a01a6a8709eaff32f88d47382c940b24a3c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 19:50:28 +0200 Subject: [PATCH 389/526] double-comparisons: make lint adhere to lint message convention --- clippy_lints/src/double_comparison.rs | 2 +- tests/ui/double_comparison.stderr | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 5d16192b754..bae7c4647d4 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -60,7 +60,7 @@ impl<'tcx> DoubleComparisons { cx, DOUBLE_COMPARISONS, span, - "This binary expression can be simplified", + "this binary expression can be simplified", "try", sugg, applicability, diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index 5dcda7b3af4..05ef4e25f7f 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -1,4 +1,4 @@ -error: This binary expression can be simplified +error: this binary expression can be simplified --> $DIR/double_comparison.rs:6:8 | LL | if x == y || x < y { @@ -6,43 +6,43 @@ LL | if x == y || x < y { | = note: `-D clippy::double-comparisons` implied by `-D warnings` -error: This binary expression can be simplified +error: this binary expression can be simplified --> $DIR/double_comparison.rs:9:8 | LL | if x < y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` -error: This binary expression can be simplified +error: this binary expression can be simplified --> $DIR/double_comparison.rs:12:8 | LL | if x == y || x > y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` -error: This binary expression can be simplified +error: this binary expression can be simplified --> $DIR/double_comparison.rs:15:8 | LL | if x > y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` -error: This binary expression can be simplified +error: this binary expression can be simplified --> $DIR/double_comparison.rs:18:8 | LL | if x < y || x > y { | ^^^^^^^^^^^^^^ help: try: `x != y` -error: This binary expression can be simplified +error: this binary expression can be simplified --> $DIR/double_comparison.rs:21:8 | LL | if x > y || x < y { | ^^^^^^^^^^^^^^ help: try: `x != y` -error: This binary expression can be simplified +error: this binary expression can be simplified --> $DIR/double_comparison.rs:24:8 | LL | if x <= y && x >= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` -error: This binary expression can be simplified +error: this binary expression can be simplified --> $DIR/double_comparison.rs:27:8 | LL | if x >= y && x <= y { From 590b91d8d4250bd6e30e2396a36c54cdbae3780f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 19:56:01 +0200 Subject: [PATCH 390/526] double-parens: make lint adhere to lint message convention and do minor refactoring --- clippy_lints/src/double_parens.rs | 23 +++++------------------ tests/ui/double_parens.stderr | 12 ++++++------ 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 1eb380a22cc..abbcaf43f41 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -45,15 +45,12 @@ impl EarlyLintPass for DoubleParens { return; } + let msg: &str = "consider removing unnecessary double parentheses"; + match expr.kind { ExprKind::Paren(ref in_paren) => match in_paren.kind { ExprKind::Paren(_) | ExprKind::Tup(_) => { - span_lint( - cx, - DOUBLE_PARENS, - expr.span, - "Consider removing unnecessary double parentheses", - ); + span_lint(cx, DOUBLE_PARENS, expr.span, &msg); }, _ => {}, }, @@ -61,12 +58,7 @@ impl EarlyLintPass for DoubleParens { if params.len() == 1 { let param = ¶ms[0]; if let ExprKind::Paren(_) = param.kind { - span_lint( - cx, - DOUBLE_PARENS, - param.span, - "Consider removing unnecessary double parentheses", - ); + span_lint(cx, DOUBLE_PARENS, param.span, &msg); } } }, @@ -74,12 +66,7 @@ impl EarlyLintPass for DoubleParens { if params.len() == 2 { let param = ¶ms[1]; if let ExprKind::Paren(_) = param.kind { - span_lint( - cx, - DOUBLE_PARENS, - param.span, - "Consider removing unnecessary double parentheses", - ); + span_lint(cx, DOUBLE_PARENS, param.span, &msg); } } }, diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index 0e4c9b5682d..40fcad2ab1d 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -1,4 +1,4 @@ -error: Consider removing unnecessary double parentheses +error: consider removing unnecessary double parentheses --> $DIR/double_parens.rs:15:5 | LL | ((0)) @@ -6,31 +6,31 @@ LL | ((0)) | = note: `-D clippy::double-parens` implied by `-D warnings` -error: Consider removing unnecessary double parentheses +error: consider removing unnecessary double parentheses --> $DIR/double_parens.rs:19:14 | LL | dummy_fn((0)); | ^^^ -error: Consider removing unnecessary double parentheses +error: consider removing unnecessary double parentheses --> $DIR/double_parens.rs:23:20 | LL | x.dummy_method((0)); | ^^^ -error: Consider removing unnecessary double parentheses +error: consider removing unnecessary double parentheses --> $DIR/double_parens.rs:27:5 | LL | ((1, 2)) | ^^^^^^^^ -error: Consider removing unnecessary double parentheses +error: consider removing unnecessary double parentheses --> $DIR/double_parens.rs:31:5 | LL | (()) | ^^^^ -error: Consider removing unnecessary double parentheses +error: consider removing unnecessary double parentheses --> $DIR/double_parens.rs:53:16 | LL | assert_eq!(((1, 2)), (1, 2), "Error"); From 0db5cb13934bff7a561dde2e13c3455120dc1bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 20:05:42 +0200 Subject: [PATCH 391/526] drop_bounds: make lint adhere to lint message convention --- clippy_lints/src/drop_bounds.rs | 6 +++--- tests/ui/drop_bounds.stderr | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/drop_bounds.rs b/clippy_lints/src/drop_bounds.rs index 4afbd1ed0e5..ec3b6afa630 100644 --- a/clippy_lints/src/drop_bounds.rs +++ b/clippy_lints/src/drop_bounds.rs @@ -33,11 +33,11 @@ declare_clippy_lint! { /// ``` pub DROP_BOUNDS, correctness, - "Bounds of the form `T: Drop` are useless" + "bounds of the form `T: Drop` are useless" } -const DROP_BOUNDS_SUMMARY: &str = "Bounds of the form `T: Drop` are useless. \ - Use `std::mem::needs_drop` to detect if a type has drop glue."; +const DROP_BOUNDS_SUMMARY: &str = "bounds of the form `T: Drop` are useless, \ + use `std::mem::needs_drop` to detect if a type has drop glue"; declare_lint_pass!(DropBounds => [DROP_BOUNDS]); diff --git a/tests/ui/drop_bounds.stderr b/tests/ui/drop_bounds.stderr index 5d360ef30a1..8208c0ed7e3 100644 --- a/tests/ui/drop_bounds.stderr +++ b/tests/ui/drop_bounds.stderr @@ -1,4 +1,4 @@ -error: Bounds of the form `T: Drop` are useless. Use `std::mem::needs_drop` to detect if a type has drop glue. +error: bounds of the form `T: Drop` are useless, use `std::mem::needs_drop` to detect if a type has drop glue --> $DIR/drop_bounds.rs:2:11 | LL | fn foo<T: Drop>() {} @@ -6,7 +6,7 @@ LL | fn foo<T: Drop>() {} | = note: `#[deny(clippy::drop_bounds)]` on by default -error: Bounds of the form `T: Drop` are useless. Use `std::mem::needs_drop` to detect if a type has drop glue. +error: bounds of the form `T: Drop` are useless, use `std::mem::needs_drop` to detect if a type has drop glue --> $DIR/drop_bounds.rs:5:8 | LL | T: Drop, From 2792260636f720a44921c5f6571535e887aa6047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 22:40:50 +0200 Subject: [PATCH 392/526] empty-liner-after-outer-attr: make lint adhere to lint message convention --- clippy_lints/src/attrs.rs | 2 +- tests/ui/empty_line_after_outer_attribute.stderr | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 3ce110e8e0f..376ac55f9c9 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -605,7 +605,7 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::as cx, EMPTY_LINE_AFTER_OUTER_ATTR, begin_of_attr_to_item, - "Found an empty line after an outer attribute. \ + "found an empty line after an outer attribute. \ Perhaps you forgot to add a `!` to make it an inner attribute?", ); } diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr index bf753a732f0..594fca44a32 100644 --- a/tests/ui/empty_line_after_outer_attribute.stderr +++ b/tests/ui/empty_line_after_outer_attribute.stderr @@ -1,4 +1,4 @@ -error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? +error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:11:1 | LL | / #[crate_type = "lib"] @@ -9,7 +9,7 @@ LL | | fn with_one_newline_and_comment() { assert!(true) } | = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings` -error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? +error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:23:1 | LL | / #[crate_type = "lib"] @@ -17,7 +17,7 @@ LL | | LL | | fn with_one_newline() { assert!(true) } | |_ -error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? +error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:28:1 | LL | / #[crate_type = "lib"] @@ -26,7 +26,7 @@ LL | | LL | | fn with_two_newlines() { assert!(true) } | |_ -error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? +error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:35:1 | LL | / #[crate_type = "lib"] @@ -34,7 +34,7 @@ LL | | LL | | enum Baz { | |_ -error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? +error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:43:1 | LL | / #[crate_type = "lib"] @@ -42,7 +42,7 @@ LL | | LL | | struct Foo { | |_ -error: Found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? +error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute? --> $DIR/empty_line_after_outer_attribute.rs:51:1 | LL | / #[crate_type = "lib"] From 4418ff122fdc65d642dd4adb709634c4f879171e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 23:31:33 +0200 Subject: [PATCH 393/526] unneeded-field-pattern: make lint adhere to lint message convention --- clippy_lints/src/misc_early.rs | 10 +++++----- tests/ui/unneeded_field_pattern.stderr | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 38b11c5e733..02789735c17 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -298,9 +298,9 @@ impl EarlyLintPass for MiscEarlyLints { cx, UNNEEDED_FIELD_PATTERN, pat.span, - "All the struct fields are matched to a wildcard pattern, consider using `..`.", + "all the struct fields are matched to a wildcard pattern, consider using `..`", None, - &format!("Try with `{} {{ .. }}` instead", type_name), + &format!("try with `{} {{ .. }}` instead", type_name), ); return; } @@ -313,7 +313,7 @@ impl EarlyLintPass for MiscEarlyLints { cx, UNNEEDED_FIELD_PATTERN, field.span, - "You matched a field with a wildcard pattern. Consider using `..` instead", + "you matched a field with a wildcard pattern, consider using `..` instead", ); } else { let mut normal = vec![]; @@ -333,10 +333,10 @@ impl EarlyLintPass for MiscEarlyLints { cx, UNNEEDED_FIELD_PATTERN, field.span, - "You matched a field with a wildcard pattern. Consider using `..` \ + "you matched a field with a wildcard pattern, consider using `..` \ instead", None, - &format!("Try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")), + &format!("try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")), ); } } diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index e7b92ce1e19..b8d3c294532 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -1,19 +1,19 @@ -error: You matched a field with a wildcard pattern. Consider using `..` instead +error: you matched a field with a wildcard pattern, consider using `..` instead --> $DIR/unneeded_field_pattern.rs:14:15 | LL | Foo { a: _, b: 0, .. } => {}, | ^^^^ | = note: `-D clippy::unneeded-field-pattern` implied by `-D warnings` - = help: Try with `Foo { b: 0, .. }` + = help: try with `Foo { b: 0, .. }` -error: All the struct fields are matched to a wildcard pattern, consider using `..`. +error: all the struct fields are matched to a wildcard pattern, consider using `..` --> $DIR/unneeded_field_pattern.rs:16:9 | LL | Foo { a: _, b: _, c: _ } => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: Try with `Foo { .. }` instead + = help: try with `Foo { .. }` instead error: aborting due to 2 previous errors From b36a6c9594ffb7e225a3d8872d8de2889ea0bac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 23:36:20 +0200 Subject: [PATCH 394/526] ref_in_deref: make lint adhere to lint message convention --- clippy_lints/src/reference.rs | 2 +- tests/ui/unnecessary_ref.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index fe457aad50e..3fda00403c6 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -92,7 +92,7 @@ impl EarlyLintPass for RefInDeref { cx, REF_IN_DEREF, object.span, - "Creating a reference that is immediately dereferenced.", + "creating a reference that is immediately dereferenced", "try this", snippet_with_applicability(cx, inner.span, "_", &mut applicability).to_string(), applicability, diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr index 34ba167a947..d0a0f219097 100644 --- a/tests/ui/unnecessary_ref.stderr +++ b/tests/ui/unnecessary_ref.stderr @@ -1,4 +1,4 @@ -error: Creating a reference that is immediately dereferenced. +error: creating a reference that is immediately dereferenced --> $DIR/unnecessary_ref.rs:13:17 | LL | let inner = (&outer).inner; From 7954c22a99275a8b7be79c14d2bb882750de53ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 23:37:16 +0200 Subject: [PATCH 395/526] unknown: make lint adhere to lint message convention --- clippy_lints/src/utils/attrs.rs | 2 +- tests/ui/unknown_attribute.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/attrs.rs b/clippy_lints/src/utils/attrs.rs index 407527251da..234ae37612b 100644 --- a/clippy_lints/src/utils/attrs.rs +++ b/clippy_lints/src/utils/attrs.rs @@ -75,7 +75,7 @@ pub fn get_attr<'a>( }) .map_or_else( || { - sess.span_err(attr_segments[1].ident.span, "Usage of unknown attribute"); + sess.span_err(attr_segments[1].ident.span, "usage of unknown attribute"); false }, |deprecation_status| { diff --git a/tests/ui/unknown_attribute.stderr b/tests/ui/unknown_attribute.stderr index 47e37aed246..618c5980d64 100644 --- a/tests/ui/unknown_attribute.stderr +++ b/tests/ui/unknown_attribute.stderr @@ -1,4 +1,4 @@ -error: Usage of unknown attribute +error: usage of unknown attribute --> $DIR/unknown_attribute.rs:1:11 | LL | #[clippy::unknown] From fe37ddbd11dd3f2cb2e529846492b312e44ed1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 23:45:24 +0200 Subject: [PATCH 396/526] suspicious-arithmetic-impl: make lint adhere to lint message convention --- clippy_lints/src/suspicious_trait_impl.rs | 4 ++-- tests/ui/suspicious_arithmetic_impl.stderr | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 502fffc5e6c..4e335a0222f 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { cx, SUSPICIOUS_ARITHMETIC_IMPL, binop.span, - &format!(r#"Suspicious use of binary operator in `{}` impl"#, impl_trait), + &format!("suspicious use of binary operator in `{}` impl", impl_trait), ); } @@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { cx, SUSPICIOUS_OP_ASSIGN_IMPL, binop.span, - &format!(r#"Suspicious use of binary operator in `{}` impl"#, impl_trait), + &format!("suspicious use of binary operator in `{}` impl", impl_trait), ); } } diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 7e42d72c30b..23d47e3f1ff 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -1,4 +1,4 @@ -error: Suspicious use of binary operator in `Add` impl +error: suspicious use of binary operator in `Add` impl --> $DIR/suspicious_arithmetic_impl.rs:11:20 | LL | Foo(self.0 - other.0) @@ -6,7 +6,7 @@ LL | Foo(self.0 - other.0) | = note: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings` -error: Suspicious use of binary operator in `AddAssign` impl +error: suspicious use of binary operator in `AddAssign` impl --> $DIR/suspicious_arithmetic_impl.rs:17:23 | LL | *self = *self - other; @@ -14,7 +14,7 @@ LL | *self = *self - other; | = note: `#[deny(clippy::suspicious_op_assign_impl)]` on by default -error: Suspicious use of binary operator in `MulAssign` impl +error: suspicious use of binary operator in `MulAssign` impl --> $DIR/suspicious_arithmetic_impl.rs:30:16 | LL | self.0 /= other.0; From 5d69ca5e114a1e44be08c835394b82ffc9cc7f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 23:46:52 +0200 Subject: [PATCH 397/526] also change "deprecated-attribute" message --- clippy_lints/src/utils/attrs.rs | 2 +- tests/ui/renamed_builtin_attr.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/attrs.rs b/clippy_lints/src/utils/attrs.rs index 234ae37612b..a3975683cb3 100644 --- a/clippy_lints/src/utils/attrs.rs +++ b/clippy_lints/src/utils/attrs.rs @@ -80,7 +80,7 @@ pub fn get_attr<'a>( }, |deprecation_status| { let mut diag = - sess.struct_span_err(attr_segments[1].ident.span, "Usage of deprecated attribute"); + sess.struct_span_err(attr_segments[1].ident.span, "usage of deprecated attribute"); match *deprecation_status { DeprecationStatus::Deprecated => { diag.emit(); diff --git a/tests/ui/renamed_builtin_attr.stderr b/tests/ui/renamed_builtin_attr.stderr index a399ff52fb8..88046762483 100644 --- a/tests/ui/renamed_builtin_attr.stderr +++ b/tests/ui/renamed_builtin_attr.stderr @@ -1,4 +1,4 @@ -error: Usage of deprecated attribute +error: usage of deprecated attribute --> $DIR/renamed_builtin_attr.rs:3:11 | LL | #[clippy::cyclomatic_complexity = "1"] From 3e1e0c9bdb582b15c7804e354085b17f8b6c62d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Thu, 23 Jul 2020 23:54:34 +0200 Subject: [PATCH 398/526] redundant-static-lifetimes: make lint adhere to lint message convention --- .../src/redundant_static_lifetimes.rs | 4 +-- tests/ui/redundant_static_lifetimes.stderr | 32 +++++++++---------- ...redundant_static_lifetimes_multiple.stderr | 20 ++++++------ 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index c6f57298c26..7bbcc67aa2d 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -86,13 +86,13 @@ impl EarlyLintPass for RedundantStaticLifetimes { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { if !item.span.from_expansion() { if let ItemKind::Const(_, ref var_type, _) = item.kind { - self.visit_type(var_type, cx, "Constants have by default a `'static` lifetime"); + self.visit_type(var_type, cx, "constants have by default a `'static` lifetime"); // Don't check associated consts because `'static` cannot be elided on those (issue // #2438) } if let ItemKind::Static(ref var_type, _, _) = item.kind { - self.visit_type(var_type, cx, "Statics have by default a `'static` lifetime"); + self.visit_type(var_type, cx, "statics have by default a `'static` lifetime"); } } } diff --git a/tests/ui/redundant_static_lifetimes.stderr b/tests/ui/redundant_static_lifetimes.stderr index 3c3d2eacd8d..649831f9c06 100644 --- a/tests/ui/redundant_static_lifetimes.stderr +++ b/tests/ui/redundant_static_lifetimes.stderr @@ -1,4 +1,4 @@ -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:8:17 | LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. @@ -6,91 +6,91 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removin | = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:12:21 | LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:14:32 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:14:47 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:16:17 | LL | const VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:18:20 | LL | const VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:20:19 | LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:22:19 | LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:24:19 | LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:26:25 | LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:30:29 | LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:32:25 | LL | static STATIC_VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:34:28 | LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:36:27 | LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:38:27 | LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:40:27 | LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. diff --git a/tests/ui/redundant_static_lifetimes_multiple.stderr b/tests/ui/redundant_static_lifetimes_multiple.stderr index afc853dcfce..cc7e55a757a 100644 --- a/tests/ui/redundant_static_lifetimes_multiple.stderr +++ b/tests/ui/redundant_static_lifetimes_multiple.stderr @@ -1,4 +1,4 @@ -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:3:18 | LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static @@ -6,55 +6,55 @@ LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; | = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:3:30 | LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:5:29 | LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]` -error: Constants have by default a `'static` lifetime +error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:5:39 | LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^---- help: consider removing `'static`: `&str` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:7:40 | LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:7:55 | LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:9:26 | LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:9:38 | LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:11:37 | LL | static STATIC_VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]` -error: Statics have by default a `'static` lifetime +error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:11:47 | LL | static STATIC_VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; From 81f77a411e844ca553ba93adcc8be617d372ac30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Fri, 24 Jul 2020 00:12:21 +0200 Subject: [PATCH 399/526] range-zip-with-len: make lint adhere to lint message convention --- clippy_lints/src/ranges.rs | 2 +- tests/ui/range.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 4c1f2e8e01a..f88075798ca 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -160,7 +160,7 @@ impl<'tcx> LateLintPass<'tcx> for Ranges { span_lint(cx, RANGE_ZIP_WITH_LEN, expr.span, - &format!("It is more idiomatic to use `{}.iter().enumerate()`", + &format!("it is more idiomatic to use `{}.iter().enumerate()`", snippet(cx, iter_args[0].span, "_"))); } } diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index d53c1edecac..dcb5061371f 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -1,4 +1,4 @@ -error: It is more idiomatic to use `v1.iter().enumerate()` +error: it is more idiomatic to use `v1.iter().enumerate()` --> $DIR/range.rs:5:14 | LL | let _x = v1.iter().zip(0..v1.len()); From 9178363574625a6185ea779c4a231b8f18205261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Fri, 24 Jul 2020 00:16:28 +0200 Subject: [PATCH 400/526] path-buf-push-overwrite: make lint adhere to lint message convention --- clippy_lints/src/path_buf_push_overwrite.rs | 2 +- tests/ui/path_buf_push_overwrite.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/path_buf_push_overwrite.rs b/clippy_lints/src/path_buf_push_overwrite.rs index 66a145a7f14..b8583402928 100644 --- a/clippy_lints/src/path_buf_push_overwrite.rs +++ b/clippy_lints/src/path_buf_push_overwrite.rs @@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for PathBufPushOverwrite { cx, PATH_BUF_PUSH_OVERWRITE, lit.span, - "Calling `push` with '/' or '\\' (file system root) will overwrite the previous path definition", + "calling `push` with '/' or '\\' (file system root) will overwrite the previous path definition", "try", format!("\"{}\"", pushed_path_lit.trim_start_matches(|c| c == '/' || c == '\\')), Applicability::MachineApplicable, diff --git a/tests/ui/path_buf_push_overwrite.stderr b/tests/ui/path_buf_push_overwrite.stderr index 09b18d71baf..bb8dce2bbba 100644 --- a/tests/ui/path_buf_push_overwrite.stderr +++ b/tests/ui/path_buf_push_overwrite.stderr @@ -1,4 +1,4 @@ -error: Calling `push` with '/' or '/' (file system root) will overwrite the previous path definition +error: calling `push` with '/' or '/' (file system root) will overwrite the previous path definition --> $DIR/path_buf_push_overwrite.rs:7:12 | LL | x.push("/bar"); From e519bb3c850199d03eed7f2bd29637b3d5479551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Fri, 24 Jul 2020 00:18:34 +0200 Subject: [PATCH 401/526] overflow-check-conditional: make lint adhere to lint message convention --- clippy_lints/src/overflow_check_conditional.rs | 8 ++++---- tests/ui/overflow_check_conditional.stderr | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 4d4a9676654..3c041bac234 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -42,13 +42,13 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional { if let BinOpKind::Lt = op.node { if let BinOpKind::Add = op2.node { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "You are trying to use classic C overflow conditions that will fail in Rust."); + "you are trying to use classic C overflow conditions that will fail in Rust"); } } if let BinOpKind::Gt = op.node { if let BinOpKind::Sub = op2.node { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "You are trying to use classic C underflow conditions that will fail in Rust."); + "you are trying to use classic C underflow conditions that will fail in Rust"); } } } @@ -67,13 +67,13 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional { if let BinOpKind::Gt = op.node { if let BinOpKind::Add = op2.node { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "You are trying to use classic C overflow conditions that will fail in Rust."); + "you are trying to use classic C overflow conditions that will fail in Rust"); } } if let BinOpKind::Lt = op.node { if let BinOpKind::Sub = op2.node { span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "You are trying to use classic C underflow conditions that will fail in Rust."); + "you are trying to use classic C underflow conditions that will fail in Rust"); } } } diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index ad66135d326..19e843c2c0a 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -1,4 +1,4 @@ -error: You are trying to use classic C overflow conditions that will fail in Rust. +error: you are trying to use classic C overflow conditions that will fail in Rust --> $DIR/overflow_check_conditional.rs:8:8 | LL | if a + b < a {} @@ -6,43 +6,43 @@ LL | if a + b < a {} | = note: `-D clippy::overflow-check-conditional` implied by `-D warnings` -error: You are trying to use classic C overflow conditions that will fail in Rust. +error: you are trying to use classic C overflow conditions that will fail in Rust --> $DIR/overflow_check_conditional.rs:9:8 | LL | if a > a + b {} | ^^^^^^^^^ -error: You are trying to use classic C overflow conditions that will fail in Rust. +error: you are trying to use classic C overflow conditions that will fail in Rust --> $DIR/overflow_check_conditional.rs:10:8 | LL | if a + b < b {} | ^^^^^^^^^ -error: You are trying to use classic C overflow conditions that will fail in Rust. +error: you are trying to use classic C overflow conditions that will fail in Rust --> $DIR/overflow_check_conditional.rs:11:8 | LL | if b > a + b {} | ^^^^^^^^^ -error: You are trying to use classic C underflow conditions that will fail in Rust. +error: you are trying to use classic C underflow conditions that will fail in Rust --> $DIR/overflow_check_conditional.rs:12:8 | LL | if a - b > b {} | ^^^^^^^^^ -error: You are trying to use classic C underflow conditions that will fail in Rust. +error: you are trying to use classic C underflow conditions that will fail in Rust --> $DIR/overflow_check_conditional.rs:13:8 | LL | if b < a - b {} | ^^^^^^^^^ -error: You are trying to use classic C underflow conditions that will fail in Rust. +error: you are trying to use classic C underflow conditions that will fail in Rust --> $DIR/overflow_check_conditional.rs:14:8 | LL | if a - b > a {} | ^^^^^^^^^ -error: You are trying to use classic C underflow conditions that will fail in Rust. +error: you are trying to use classic C underflow conditions that will fail in Rust --> $DIR/overflow_check_conditional.rs:15:8 | LL | if a < a - b {} From 178da9b2ef9e8c94ab0fbe7812e11445664f67b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Fri, 24 Jul 2020 00:24:11 +0200 Subject: [PATCH 402/526] neg-multiply: make lint adhere to lint message convention --- clippy_lints/src/neg_multiply.rs | 2 +- tests/ui/neg_multiply.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 6b6c950e0ab..aa550510867 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -47,7 +47,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { if let Constant::Int(1) = consts::lit_to_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)); if cx.typeck_results().expr_ty(exp).is_integral(); then { - span_lint(cx, NEG_MULTIPLY, span, "Negation by multiplying with `-1`"); + span_lint(cx, NEG_MULTIPLY, span, "negation by multiplying with `-1`"); } } } diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index f08bbd6a12c..ad677f6d6fb 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -1,4 +1,4 @@ -error: Negation by multiplying with `-1` +error: negation by multiplying with `-1` --> $DIR/neg_multiply.rs:27:5 | LL | x * -1; @@ -6,7 +6,7 @@ LL | x * -1; | = note: `-D clippy::neg-multiply` implied by `-D warnings` -error: Negation by multiplying with `-1` +error: negation by multiplying with `-1` --> $DIR/neg_multiply.rs:29:5 | LL | -1 * x; From dabf9891954aa0d0c59b230ab0e7afcfd4142be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 28 Jul 2020 12:13:22 +0200 Subject: [PATCH 403/526] neg-cmp-op-on-partial-ord: make lint adhere to lint message convention --- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 2 +- tests/ui/neg_cmp_op_on_partial_ord.stderr | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 95613a1b82e..0f5d5ce3495 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -79,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { cx, NEG_CMP_OP_ON_PARTIAL_ORD, expr.span, - "The use of negated comparison operators on partially ordered \ + "the use of negated comparison operators on partially ordered \ types produces code that is hard to read and refactor. Please \ consider using the `partial_cmp` method instead, to make it \ clear that the two values could be incomparable." diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index 8c5d548222e..193d9f9bcea 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,4 +1,4 @@ -error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. +error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:16:21 | LL | let _not_less = !(a_value < another_value); @@ -6,19 +6,19 @@ LL | let _not_less = !(a_value < another_value); | = note: `-D clippy::neg-cmp-op-on-partial-ord` implied by `-D warnings` -error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. +error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:19:30 | LL | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. +error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:22:24 | LL | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: The use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. +error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. --> $DIR/neg_cmp_op_on_partial_ord.rs:25:33 | LL | let _not_greater_or_equal = !(a_value >= another_value); From c514ff0c93264e3cebd5eda9caf0b99fc8fd0daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Mon, 10 Aug 2020 23:50:40 +0200 Subject: [PATCH 404/526] Update clippy_lints/src/neg_cmp_op_on_partial_ord.rs Co-authored-by: Jane Lusby <jlusby42@gmail.com> --- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 0f5d5ce3495..4fb899125e8 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -80,9 +80,9 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { NEG_CMP_OP_ON_PARTIAL_ORD, expr.span, "the use of negated comparison operators on partially ordered \ - types produces code that is hard to read and refactor. Please \ + types produces code that is hard to read and refactor, please \ consider using the `partial_cmp` method instead, to make it \ - clear that the two values could be incomparable." + clear that the two values could be incomparable" ) } } From 1b46e485b28613426f7bebccc009effad50fcaf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Mon, 10 Aug 2020 23:50:52 +0200 Subject: [PATCH 405/526] Update clippy_lints/src/unwrap.rs Co-authored-by: Jane Lusby <jlusby42@gmail.com> --- clippy_lints/src/unwrap.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index fd755dcc790..ea4b8172c9c 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -181,8 +181,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { self.cx, UNNECESSARY_UNWRAP, expr.span, - &format!("you checked before that `{}()` cannot fail. \ - Instead of checking and unwrapping, it's better to use `if let` or `match`", + &format!("you checked before that `{}()` cannot fail, \ + instead of checking and unwrapping, it's better to use `if let` or `match`", method_name.ident.name), |diag| { diag.span_label(unwrappable.check.span, "the check is happening here"); }, ); From f59ec1945f887eeff17ae04008fc1e6e8b1fb4f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Mon, 10 Aug 2020 23:55:15 +0200 Subject: [PATCH 406/526] run cargo dev update-lints --- src/lintlist/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 6395b571504..dc8779748e0 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -412,7 +412,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ Lint { name: "drop_bounds", group: "correctness", - desc: "Bounds of the form `T: Drop` are useless", + desc: "bounds of the form `T: Drop` are useless", deprecation: None, module: "drop_bounds", }, From 6d0b5e24dfc8232123984fcefface485aa7fbc3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 00:27:55 +0200 Subject: [PATCH 407/526] update test stderr --- .../complex_conditionals.stderr | 20 +++++++++---------- .../complex_conditionals_nested.stderr | 2 +- .../checked_unwrap/simple_conditionals.stderr | 14 ++++++------- tests/ui/neg_cmp_op_on_partial_ord.stderr | 8 ++++---- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/ui/checked_unwrap/complex_conditionals.stderr b/tests/ui/checked_unwrap/complex_conditionals.stderr index 5b62dca629f..33bb5136ef8 100644 --- a/tests/ui/checked_unwrap/complex_conditionals.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals.stderr @@ -1,4 +1,4 @@ -error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:8:9 | LL | if x.is_ok() && y.is_err() { @@ -36,7 +36,7 @@ LL | if x.is_ok() && y.is_err() { LL | y.unwrap(); // will panic | ^^^^^^^^^^ -error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:11:9 | LL | if x.is_ok() && y.is_err() { @@ -54,7 +54,7 @@ LL | if x.is_ok() || y.is_ok() { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:26:9 | LL | if x.is_ok() || y.is_ok() { @@ -72,7 +72,7 @@ LL | if x.is_ok() || y.is_ok() { LL | y.unwrap(); // will panic | ^^^^^^^^^^ -error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:28:9 | LL | if x.is_ok() || y.is_ok() { @@ -81,7 +81,7 @@ LL | if x.is_ok() || y.is_ok() { LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:32:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { @@ -107,7 +107,7 @@ LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { LL | y.unwrap(); // will panic | ^^^^^^^^^^ -error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:35:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { @@ -116,7 +116,7 @@ LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:36:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { @@ -143,7 +143,7 @@ LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:46:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { @@ -152,7 +152,7 @@ LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:47:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { @@ -179,7 +179,7 @@ LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { LL | z.unwrap(); // will panic | ^^^^^^^^^^ -error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals.rs:50:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr index 46ffc16c23e..a01f7f956f6 100644 --- a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr @@ -1,4 +1,4 @@ -error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/complex_conditionals_nested.rs:8:13 | LL | if x.is_some() { diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr index bf4b6c93098..416ec1a01ab 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -1,4 +1,4 @@ -error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:39:9 | LL | if x.is_some() { @@ -35,7 +35,7 @@ LL | if x.is_none() { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:46:9 | LL | if x.is_none() { @@ -44,7 +44,7 @@ LL | if x.is_none() { LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ -error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:7:13 | LL | if $a.is_some() { @@ -57,7 +57,7 @@ LL | m!(x); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:54:9 | LL | if x.is_ok() { @@ -83,7 +83,7 @@ LL | if x.is_ok() { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:58:9 | LL | if x.is_ok() { @@ -100,7 +100,7 @@ LL | if x.is_err() { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: you checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:62:9 | LL | if x.is_err() { @@ -109,7 +109,7 @@ LL | x.unwrap(); // will panic LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: you checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match` +error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match` --> $DIR/simple_conditionals.rs:64:9 | LL | if x.is_err() { diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index 193d9f9bcea..c7856000721 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -1,4 +1,4 @@ -error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. +error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor, please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable --> $DIR/neg_cmp_op_on_partial_ord.rs:16:21 | LL | let _not_less = !(a_value < another_value); @@ -6,19 +6,19 @@ LL | let _not_less = !(a_value < another_value); | = note: `-D clippy::neg-cmp-op-on-partial-ord` implied by `-D warnings` -error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. +error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor, please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable --> $DIR/neg_cmp_op_on_partial_ord.rs:19:30 | LL | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. +error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor, please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable --> $DIR/neg_cmp_op_on_partial_ord.rs:22:24 | LL | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor. Please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable. +error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor, please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable --> $DIR/neg_cmp_op_on_partial_ord.rs:25:33 | LL | let _not_greater_or_equal = !(a_value >= another_value); From b8713e3854cb90b974eceaa1d50484831591619c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 12:35:55 +0200 Subject: [PATCH 408/526] unnecessary-mut-passed: make lint message say if fn is a function or a method. --- clippy_lints/src/mut_reference.rs | 13 ++++++++++--- tests/ui/mut_reference.stderr | 6 +++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index b8dc5081632..be3ae7ab380 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -39,6 +39,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { arguments, cx.typeck_results().expr_ty(fn_expr), &rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)), + "function", ); } }, @@ -46,14 +47,20 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap(); let substs = cx.typeck_results().node_substs(e.hir_id); let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs); - check_arguments(cx, arguments, method_type, &path.ident.as_str()) + check_arguments(cx, arguments, method_type, &path.ident.as_str(), "method") }, _ => (), } } } -fn check_arguments<'tcx>(cx: &LateContext<'tcx>, arguments: &[Expr<'_>], type_definition: Ty<'tcx>, name: &str) { +fn check_arguments<'tcx>( + cx: &LateContext<'tcx>, + arguments: &[Expr<'_>], + type_definition: Ty<'tcx>, + name: &str, + fn_kind: &str, +) { match type_definition.kind { ty::FnDef(..) | ty::FnPtr(_) => { let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs(); @@ -68,7 +75,7 @@ fn check_arguments<'tcx>(cx: &LateContext<'tcx>, arguments: &[Expr<'_>], type_de cx, UNNECESSARY_MUT_PASSED, argument.span, - &format!("The function/method `{}` doesn't need a mutable reference", name), + &format!("the {} `{}` doesn't need a mutable reference", fn_kind, name), ); } }, diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index fa8c82ae0f3..062d30b262c 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -1,4 +1,4 @@ -error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference +error: the function `takes_an_immutable_reference` doesn't need a mutable reference --> $DIR/mut_reference.rs:17:34 | LL | takes_an_immutable_reference(&mut 42); @@ -6,13 +6,13 @@ LL | takes_an_immutable_reference(&mut 42); | = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` -error: The function/method `as_ptr` doesn't need a mutable reference +error: the function `as_ptr` doesn't need a mutable reference --> $DIR/mut_reference.rs:19:12 | LL | as_ptr(&mut 42); | ^^^^^^^ -error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference +error: the method `takes_an_immutable_reference` doesn't need a mutable reference --> $DIR/mut_reference.rs:23:44 | LL | my_struct.takes_an_immutable_reference(&mut 42); From 9311c11d7c01d64d22dc7914e9dff4c5167adb49 Mon Sep 17 00:00:00 2001 From: flip1995 <hello@philkrones.com> Date: Tue, 11 Aug 2020 13:57:32 +0200 Subject: [PATCH 409/526] Fix sync fallout --- clippy_lints/src/transmute.rs | 12 ++--- tests/compile-test.rs | 7 +-- .../transmutes_expressible_as_ptr_casts.fixed | 38 ++++++---------- .../ui/transmutes_expressible_as_ptr_casts.rs | 38 ++++++---------- ...transmutes_expressible_as_ptr_casts.stderr | 44 +++++++++---------- 5 files changed, 59 insertions(+), 80 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index f077c146183..7b5e92eb5ee 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -61,12 +61,14 @@ declare_clippy_lint! { /// /// **Example:** /// - /// ```rust,ignore - /// core::intrinsics::transmute::<*const [i32], *const [u16]>(p) + /// ```rust + /// # let p: *const [i32] = &[]; + /// unsafe { std::mem::transmute::<*const [i32], *const [u16]>(p) }; /// ``` /// Use instead: /// ```rust - /// p as *const [u16] + /// # let p: *const [i32] = &[]; + /// p as *const [u16]; /// ``` pub TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, complexity, @@ -704,14 +706,14 @@ fn can_be_expressed_as_pointer_cast<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, ) -> bool { - use CastKind::*; + use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast}; matches!( check_cast(cx, e, from_ty, to_ty), Some(PtrPtrCast | PtrAddrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) ) } -/// If a cast from from_ty to to_ty is valid, returns an Ok containing the kind of +/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of /// the cast. In certain cases, including some invalid casts from array references /// to pointers, this may cause additional errors to be emitted and/or ICE error /// messages. This function will panic if that occurs. diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 26a47d23706..e662d608edf 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -147,9 +147,6 @@ fn run_ui_toml(config: &mut compiletest::Config) { } fn run_ui_cargo(config: &mut compiletest::Config) { - if cargo::is_rustc_test_suite() { - return; - } fn run_tests( config: &compiletest::Config, filter: &Option<String>, @@ -217,6 +214,10 @@ fn run_ui_cargo(config: &mut compiletest::Config) { Ok(result) } + if cargo::is_rustc_test_suite() { + return; + } + config.mode = TestMode::Ui; config.src_base = Path::new("tests").join("ui-cargo").canonicalize().unwrap(); diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/tests/ui/transmutes_expressible_as_ptr_casts.fixed index 98288dde6d8..b6f1e83181c 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -9,60 +9,48 @@ use std::mem::{size_of, transmute}; -// rustc_typeck::check::cast contains documentation about when a cast `e as U` is +// rustc_typeck::check::cast contains documentation about when a cast `e as U` is // valid, which we quote from below. fn main() { // We should see an error message for each transmute, and no error messages for // the casts, since the casts are the recommended fixes. // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast - let _ptr_i32_transmute = unsafe { - usize::MAX as *const i32 - }; + let _ptr_i32_transmute = unsafe { usize::MAX as *const i32 }; let ptr_i32 = usize::MAX as *const i32; // e has type *T, U is *U_0, and either U_0: Sized ... - let _ptr_i8_transmute = unsafe { - ptr_i32 as *const i8 - }; + let _ptr_i8_transmute = unsafe { ptr_i32 as *const i8 }; let _ptr_i8 = ptr_i32 as *const i8; - let slice_ptr = &[0,1,2,3] as *const [i32]; + let slice_ptr = &[0, 1, 2, 3] as *const [i32]; // ... or pointer_kind(T) = pointer_kind(U_0); ptr-ptr-cast - let _ptr_to_unsized_transmute = unsafe { - slice_ptr as *const [u16] - }; + let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u16] }; let _ptr_to_unsized = slice_ptr as *const [u16]; // TODO: We could try testing vtable casts here too, but maybe // we should wait until std::raw::TraitObject is stabilized? // e has type *T and U is a numeric type, while T: Sized; ptr-addr-cast - let _usize_from_int_ptr_transmute = unsafe { - ptr_i32 as usize - }; + let _usize_from_int_ptr_transmute = unsafe { ptr_i32 as usize }; let _usize_from_int_ptr = ptr_i32 as usize; - let array_ref: &[i32; 4] = &[1,2,3,4]; + let array_ref: &[i32; 4] = &[1, 2, 3, 4]; // e has type &[T; n] and U is *const T; array-ptr-cast - let _array_ptr_transmute = unsafe { - array_ref as *const [i32; 4] - }; + let _array_ptr_transmute = unsafe { array_ref as *const [i32; 4] }; let _array_ptr = array_ref as *const [i32; 4]; - fn foo(_: usize) -> u8 { 42 } + fn foo(_: usize) -> u8 { + 42 + } // e is a function pointer type and U has type *T, while T: Sized; fptr-ptr-cast - let _usize_ptr_transmute = unsafe { - foo as *const usize - }; + let _usize_ptr_transmute = unsafe { foo as *const usize }; let _usize_ptr_transmute = foo as *const usize; // e is a function pointer type and U is an integer; fptr-addr-cast - let _usize_from_fn_ptr_transmute = unsafe { - foo as usize - }; + let _usize_from_fn_ptr_transmute = unsafe { foo as usize }; let _usize_from_fn_ptr = foo as *const usize; } diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.rs b/tests/ui/transmutes_expressible_as_ptr_casts.rs index fd5055c08f6..0205d1ece60 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -9,60 +9,48 @@ use std::mem::{size_of, transmute}; -// rustc_typeck::check::cast contains documentation about when a cast `e as U` is +// rustc_typeck::check::cast contains documentation about when a cast `e as U` is // valid, which we quote from below. fn main() { // We should see an error message for each transmute, and no error messages for // the casts, since the casts are the recommended fixes. // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast - let _ptr_i32_transmute = unsafe { - transmute::<usize, *const i32>(usize::MAX) - }; + let _ptr_i32_transmute = unsafe { transmute::<usize, *const i32>(usize::MAX) }; let ptr_i32 = usize::MAX as *const i32; // e has type *T, U is *U_0, and either U_0: Sized ... - let _ptr_i8_transmute = unsafe { - transmute::<*const i32, *const i8>(ptr_i32) - }; + let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) }; let _ptr_i8 = ptr_i32 as *const i8; - let slice_ptr = &[0,1,2,3] as *const [i32]; + let slice_ptr = &[0, 1, 2, 3] as *const [i32]; // ... or pointer_kind(T) = pointer_kind(U_0); ptr-ptr-cast - let _ptr_to_unsized_transmute = unsafe { - transmute::<*const [i32], *const [u16]>(slice_ptr) - }; + let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u16]>(slice_ptr) }; let _ptr_to_unsized = slice_ptr as *const [u16]; // TODO: We could try testing vtable casts here too, but maybe // we should wait until std::raw::TraitObject is stabilized? // e has type *T and U is a numeric type, while T: Sized; ptr-addr-cast - let _usize_from_int_ptr_transmute = unsafe { - transmute::<*const i32, usize>(ptr_i32) - }; + let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, usize>(ptr_i32) }; let _usize_from_int_ptr = ptr_i32 as usize; - let array_ref: &[i32; 4] = &[1,2,3,4]; + let array_ref: &[i32; 4] = &[1, 2, 3, 4]; // e has type &[T; n] and U is *const T; array-ptr-cast - let _array_ptr_transmute = unsafe { - transmute::<&[i32; 4], *const [i32; 4]>(array_ref) - }; + let _array_ptr_transmute = unsafe { transmute::<&[i32; 4], *const [i32; 4]>(array_ref) }; let _array_ptr = array_ref as *const [i32; 4]; - fn foo(_: usize) -> u8 { 42 } + fn foo(_: usize) -> u8 { + 42 + } // e is a function pointer type and U has type *T, while T: Sized; fptr-ptr-cast - let _usize_ptr_transmute = unsafe { - transmute::<fn(usize) -> u8, *const usize>(foo) - }; + let _usize_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, *const usize>(foo) }; let _usize_ptr_transmute = foo as *const usize; // e is a function pointer type and U is an integer; fptr-addr-cast - let _usize_from_fn_ptr_transmute = unsafe { - transmute::<fn(usize) -> u8, usize>(foo) - }; + let _usize_from_fn_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, usize>(foo) }; let _usize_from_fn_ptr = foo as *const usize; } diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/tests/ui/transmutes_expressible_as_ptr_casts.stderr index 46597acc6c0..1157b179317 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -1,53 +1,53 @@ error: transmute from an integer to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:20:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:19:39 | -LL | transmute::<usize, *const i32>(usize::MAX) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `usize::MAX as *const i32` +LL | let _ptr_i32_transmute = unsafe { transmute::<usize, *const i32>(usize::MAX) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `usize::MAX as *const i32` | = note: `-D clippy::useless-transmute` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:26:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:23:38 | -LL | transmute::<*const i32, *const i8>(ptr_i32) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as *const i8` +LL | let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as *const i8` | = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:34:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:29:46 | -LL | transmute::<*const [i32], *const [u16]>(slice_ptr) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice_ptr as *const [u16]` +LL | let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u16]>(slice_ptr) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice_ptr as *const [u16]` error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead - --> $DIR/transmutes_expressible_as_ptr_casts.rs:42:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:35:50 | -LL | transmute::<*const i32, usize>(ptr_i32) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as usize` +LL | let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, usize>(ptr_i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as usize` | = note: `-D clippy::transmutes-expressible-as-ptr-casts` implied by `-D warnings` error: transmute from a reference to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:50:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:41:41 | -LL | transmute::<&[i32; 4], *const [i32; 4]>(array_ref) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `array_ref as *const [i32; 4]` +LL | let _array_ptr_transmute = unsafe { transmute::<&[i32; 4], *const [i32; 4]>(array_ref) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `array_ref as *const [i32; 4]` error: transmute from `fn(usize) -> u8 {main::foo}` to `*const usize` which could be expressed as a pointer cast instead - --> $DIR/transmutes_expressible_as_ptr_casts.rs:58:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:49:41 | -LL | transmute::<fn(usize) -> u8, *const usize>(foo) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as *const usize` +LL | let _usize_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, *const usize>(foo) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as *const usize` error: transmute from `fn(usize) -> u8 {main::foo}` to `usize` which could be expressed as a pointer cast instead - --> $DIR/transmutes_expressible_as_ptr_casts.rs:64:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:53:49 | -LL | transmute::<fn(usize) -> u8, usize>(foo) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize` +LL | let _usize_from_fn_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, usize>(foo) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize` error: transmute from a reference to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:77:14 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:65:14 | LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8` From c0a9d64818d7076b72fd6c3a9e6172eca659034b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 11:50:26 +0200 Subject: [PATCH 410/526] stable-sort-primitive: make lint adhere to lint message convention --- clippy_lints/src/stable_sort_primitive.rs | 6 +++--- tests/ui/stable_sort_primitive.stderr | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/stable_sort_primitive.rs b/clippy_lints/src/stable_sort_primitive.rs index cd7056620a2..22c49a20451 100644 --- a/clippy_lints/src/stable_sort_primitive.rs +++ b/clippy_lints/src/stable_sort_primitive.rs @@ -111,9 +111,9 @@ impl LateLintPass<'_> for StableSortPrimitive { STABLE_SORT_PRIMITIVE, expr.span, format!( - "Use {} instead of {}", - detection.method.unstable_name(), - detection.method.stable_name() + "used {} instead of {}", + detection.method.stable_name(), + detection.method.unstable_name() ) .as_str(), "try", diff --git a/tests/ui/stable_sort_primitive.stderr b/tests/ui/stable_sort_primitive.stderr index b0b729ede48..b73012a4691 100644 --- a/tests/ui/stable_sort_primitive.stderr +++ b/tests/ui/stable_sort_primitive.stderr @@ -1,4 +1,4 @@ -error: Use sort_unstable instead of sort +error: used sort instead of sort_unstable --> $DIR/stable_sort_primitive.rs:7:5 | LL | vec.sort(); @@ -6,37 +6,37 @@ LL | vec.sort(); | = note: `-D clippy::stable-sort-primitive` implied by `-D warnings` -error: Use sort_unstable instead of sort +error: used sort instead of sort_unstable --> $DIR/stable_sort_primitive.rs:9:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: Use sort_unstable instead of sort +error: used sort instead of sort_unstable --> $DIR/stable_sort_primitive.rs:11:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: Use sort_unstable instead of sort +error: used sort instead of sort_unstable --> $DIR/stable_sort_primitive.rs:13:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: Use sort_unstable instead of sort +error: used sort instead of sort_unstable --> $DIR/stable_sort_primitive.rs:15:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: Use sort_unstable instead of sort +error: used sort instead of sort_unstable --> $DIR/stable_sort_primitive.rs:17:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: Use sort_unstable instead of sort +error: used sort instead of sort_unstable --> $DIR/stable_sort_primitive.rs:19:5 | LL | arr.sort(); From ac194cafc124276d4614bf023ca7ea6e9be9c6ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 11:53:21 +0200 Subject: [PATCH 411/526] map_clone: make lint adhere to lint message convention --- clippy_lints/src/map_clone.rs | 12 ++++++------ tests/ui/map_clone.stderr | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 641e6a17043..1cd5b201292 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -111,8 +111,8 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) { cx, MAP_CLONE, root.trim_start(receiver).unwrap(), - "You are needlessly cloning iterator elements", - "Remove the `map` call", + "you are needlessly cloning iterator elements", + "remove the `map` call", String::new(), Applicability::MachineApplicable, ) @@ -125,8 +125,8 @@ fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) { cx, MAP_CLONE, replace, - "You are using an explicit closure for copying elements", - "Consider calling the dedicated `copied` method", + "you are using an explicit closure for copying elements", + "consider calling the dedicated `copied` method", format!( "{}.copied()", snippet_with_applicability(cx, root, "..", &mut applicability) @@ -138,8 +138,8 @@ fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) { cx, MAP_CLONE, replace, - "You are using an explicit closure for cloning elements", - "Consider calling the dedicated `cloned` method", + "you are using an explicit closure for cloning elements", + "consider calling the dedicated `cloned` method", format!( "{}.cloned()", snippet_with_applicability(cx, root, "..", &mut applicability) diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index 9eec6928e8c..4f43cff5024 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -1,40 +1,40 @@ -error: You are using an explicit closure for copying elements +error: you are using an explicit closure for copying elements --> $DIR/map_clone.rs:10:22 | LL | let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `copied` method: `vec![5_i8; 6].iter().copied()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![5_i8; 6].iter().copied()` | = note: `-D clippy::map-clone` implied by `-D warnings` -error: You are using an explicit closure for cloning elements +error: you are using an explicit closure for cloning elements --> $DIR/map_clone.rs:11:26 | LL | let _: Vec<String> = vec![String::new()].iter().map(|x| x.clone()).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` -error: You are using an explicit closure for copying elements +error: you are using an explicit closure for copying elements --> $DIR/map_clone.rs:12:23 | LL | let _: Vec<u32> = vec![42, 43].iter().map(|&x| x).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()` -error: You are using an explicit closure for copying elements +error: you are using an explicit closure for copying elements --> $DIR/map_clone.rs:14:26 | LL | let _: Option<u64> = Some(&16).map(|b| *b); - | ^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `copied` method: `Some(&16).copied()` + | ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&16).copied()` -error: You are using an explicit closure for copying elements +error: you are using an explicit closure for copying elements --> $DIR/map_clone.rs:15:25 | LL | let _: Option<u8> = Some(&1).map(|x| x.clone()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `copied` method: `Some(&1).copied()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&1).copied()` -error: You are needlessly cloning iterator elements +error: you are needlessly cloning iterator elements --> $DIR/map_clone.rs:26:29 | LL | let _ = std::env::args().map(|v| v.clone()); - | ^^^^^^^^^^^^^^^^^^^ help: Remove the `map` call + | ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call error: aborting due to 6 previous errors From 04867e004ebc0f2edf66d0a457e785848451f13a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 12:10:42 +0200 Subject: [PATCH 412/526] mutex-atomic: make lint adhere to lint message convention --- clippy_lints/src/mutex_atomic.rs | 4 ++-- tests/ui/mutex_atomic.stderr | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 568898aa5c9..21efee71269 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -72,8 +72,8 @@ impl<'tcx> LateLintPass<'tcx> for Mutex { let mutex_param = subst.type_at(0); if let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = format!( - "Consider using an `{}` instead of a `Mutex` here. If you just want the locking \ - behavior and not the internal type, consider using `Mutex<()>`.", + "consider using an `{}` instead of a `Mutex` here; if you just want the locking \ + behavior and not the internal type, consider using `Mutex<()>`", atomic_name ); match mutex_param.kind { diff --git a/tests/ui/mutex_atomic.stderr b/tests/ui/mutex_atomic.stderr index 7dac0865855..a3511ba708a 100644 --- a/tests/ui/mutex_atomic.stderr +++ b/tests/ui/mutex_atomic.stderr @@ -1,4 +1,4 @@ -error: Consider using an `AtomicBool` instead of a `Mutex` here. If you just want the locking behavior and not the internal type, consider using `Mutex<()>`. +error: consider using an `AtomicBool` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` --> $DIR/mutex_atomic.rs:6:5 | LL | Mutex::new(true); @@ -6,31 +6,31 @@ LL | Mutex::new(true); | = note: `-D clippy::mutex-atomic` implied by `-D warnings` -error: Consider using an `AtomicUsize` instead of a `Mutex` here. If you just want the locking behavior and not the internal type, consider using `Mutex<()>`. +error: consider using an `AtomicUsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` --> $DIR/mutex_atomic.rs:7:5 | LL | Mutex::new(5usize); | ^^^^^^^^^^^^^^^^^^ -error: Consider using an `AtomicIsize` instead of a `Mutex` here. If you just want the locking behavior and not the internal type, consider using `Mutex<()>`. +error: consider using an `AtomicIsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` --> $DIR/mutex_atomic.rs:8:5 | LL | Mutex::new(9isize); | ^^^^^^^^^^^^^^^^^^ -error: Consider using an `AtomicPtr` instead of a `Mutex` here. If you just want the locking behavior and not the internal type, consider using `Mutex<()>`. +error: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` --> $DIR/mutex_atomic.rs:10:5 | LL | Mutex::new(&x as *const u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Consider using an `AtomicPtr` instead of a `Mutex` here. If you just want the locking behavior and not the internal type, consider using `Mutex<()>`. +error: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` --> $DIR/mutex_atomic.rs:11:5 | LL | Mutex::new(&mut x as *mut u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Consider using an `AtomicUsize` instead of a `Mutex` here. If you just want the locking behavior and not the internal type, consider using `Mutex<()>`. +error: consider using an `AtomicUsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` --> $DIR/mutex_atomic.rs:12:5 | LL | Mutex::new(0u32); @@ -38,7 +38,7 @@ LL | Mutex::new(0u32); | = note: `-D clippy::mutex-integer` implied by `-D warnings` -error: Consider using an `AtomicIsize` instead of a `Mutex` here. If you just want the locking behavior and not the internal type, consider using `Mutex<()>`. +error: consider using an `AtomicIsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` --> $DIR/mutex_atomic.rs:13:5 | LL | Mutex::new(0i32); From 6af297f80e59050c87078f1ba6f05c97d6f90fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 12:42:50 +0200 Subject: [PATCH 413/526] iter-next-slice: make lint adhere to lint message convention --- clippy_lints/src/methods/mod.rs | 4 ++-- tests/ui/iter_next_slice.stderr | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 570ae66d595..f4eb9c4516f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2280,7 +2280,7 @@ fn lint_iter_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, iter_ cx, ITER_NEXT_SLICE, expr.span, - "Using `.iter().next()` on a Slice without end index.", + "using `.iter().next()` on a Slice without end index", "try calling", format!("{}.get({})", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability), start_idx), applicability, @@ -2299,7 +2299,7 @@ fn lint_iter_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, iter_ cx, ITER_NEXT_SLICE, expr.span, - "Using `.iter().next()` on an array", + "using `.iter().next()` on an array", "try calling", format!( "{}.get(0)", diff --git a/tests/ui/iter_next_slice.stderr b/tests/ui/iter_next_slice.stderr index bbf61df0cda..8c10a252ee0 100644 --- a/tests/ui/iter_next_slice.stderr +++ b/tests/ui/iter_next_slice.stderr @@ -1,4 +1,4 @@ -error: Using `.iter().next()` on an array +error: using `.iter().next()` on an array --> $DIR/iter_next_slice.rs:9:5 | LL | s.iter().next(); @@ -6,19 +6,19 @@ LL | s.iter().next(); | = note: `-D clippy::iter-next-slice` implied by `-D warnings` -error: Using `.iter().next()` on a Slice without end index. +error: using `.iter().next()` on a Slice without end index --> $DIR/iter_next_slice.rs:12:5 | LL | s[2..].iter().next(); | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)` -error: Using `.iter().next()` on a Slice without end index. +error: using `.iter().next()` on a Slice without end index --> $DIR/iter_next_slice.rs:15:5 | LL | v[5..].iter().next(); | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)` -error: Using `.iter().next()` on an array +error: using `.iter().next()` on an array --> $DIR/iter_next_slice.rs:18:5 | LL | v.iter().next(); From f171f89aed11043e459c3baab305e7f859debb94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 15:14:32 +0200 Subject: [PATCH 414/526] int_plus_one: make lint adhere to lint message convention --- clippy_lints/src/int_plus_one.rs | 6 +++--- tests/ui/int_plus_one.stderr | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index e91fb0c2f27..c629ee05ab9 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -152,7 +152,7 @@ impl IntPlusOne { cx, INT_PLUS_ONE, block.span, - "Unnecessary `>= y + 1` or `x - 1 >=`", + "unnecessary `>= y + 1` or `x - 1 >=`", "change it to", recommendation, Applicability::MachineApplicable, // snippet @@ -163,8 +163,8 @@ impl IntPlusOne { impl EarlyLintPass for IntPlusOne { fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.kind { - if let Some(ref rec) = Self::check_binop(cx, kind.node, lhs, rhs) { - Self::emit_warning(cx, item, rec.clone()); + if let Some(rec) = Self::check_binop(cx, kind.node, lhs, rhs) { + Self::emit_warning(cx, item, rec); } } } diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 29a6914761c..c5b020ba8ce 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -1,4 +1,4 @@ -error: Unnecessary `>= y + 1` or `x - 1 >=` +error: unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:9:13 | LL | let _ = x >= y + 1; @@ -6,19 +6,19 @@ LL | let _ = x >= y + 1; | = note: `-D clippy::int-plus-one` implied by `-D warnings` -error: Unnecessary `>= y + 1` or `x - 1 >=` +error: unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:10:13 | LL | let _ = y + 1 <= x; | ^^^^^^^^^^ help: change it to: `y < x` -error: Unnecessary `>= y + 1` or `x - 1 >=` +error: unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:12:13 | LL | let _ = x - 1 >= y; | ^^^^^^^^^^ help: change it to: `x > y` -error: Unnecessary `>= y + 1` or `x - 1 >=` +error: unnecessary `>= y + 1` or `x - 1 >=` --> $DIR/int_plus_one.rs:13:13 | LL | let _ = y <= x - 1; From bdf4dc3abd9a49f699d9de209a1f4d55ce770191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 15:22:59 +0200 Subject: [PATCH 415/526] implicit-saturating-sub: make lint adhere to lint message convention --- clippy_lints/src/implicit_saturating_sub.rs | 4 +- tests/ui/implicit_saturating_sub.stderr | 46 ++++++++++----------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 5f931a0adde..b57fe8dc426 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -158,9 +158,9 @@ fn print_lint_and_sugg(cx: &LateContext<'_>, var_name: &str, expr: &Expr<'_>) { cx, IMPLICIT_SATURATING_SUB, expr.span, - "Implicitly performing saturating subtraction", + "implicitly performing saturating subtraction", "try", - format!("{} = {}.saturating_sub({});", var_name, var_name, 1.to_string()), + format!("{} = {}.saturating_sub({});", var_name, var_name, '1'), Applicability::MachineApplicable, ); } diff --git a/tests/ui/implicit_saturating_sub.stderr b/tests/ui/implicit_saturating_sub.stderr index 2eb2023b3b9..5bb9a606422 100644 --- a/tests/ui/implicit_saturating_sub.stderr +++ b/tests/ui/implicit_saturating_sub.stderr @@ -1,4 +1,4 @@ -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:13:5 | LL | / if u_8 > 0 { @@ -8,7 +8,7 @@ LL | | } | = note: `-D clippy::implicit-saturating-sub` implied by `-D warnings` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:20:13 | LL | / if u_8 > 0 { @@ -16,7 +16,7 @@ LL | | u_8 -= 1; LL | | } | |_____________^ help: try: `u_8 = u_8.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:34:5 | LL | / if u_16 > 0 { @@ -24,7 +24,7 @@ LL | | u_16 -= 1; LL | | } | |_____^ help: try: `u_16 = u_16.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:44:5 | LL | / if u_32 != 0 { @@ -32,7 +32,7 @@ LL | | u_32 -= 1; LL | | } | |_____^ help: try: `u_32 = u_32.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:65:5 | LL | / if u_64 > 0 { @@ -40,7 +40,7 @@ LL | | u_64 -= 1; LL | | } | |_____^ help: try: `u_64 = u_64.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:70:5 | LL | / if 0 < u_64 { @@ -48,7 +48,7 @@ LL | | u_64 -= 1; LL | | } | |_____^ help: try: `u_64 = u_64.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:75:5 | LL | / if 0 != u_64 { @@ -56,7 +56,7 @@ LL | | u_64 -= 1; LL | | } | |_____^ help: try: `u_64 = u_64.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:96:5 | LL | / if u_usize > 0 { @@ -64,7 +64,7 @@ LL | | u_usize -= 1; LL | | } | |_____^ help: try: `u_usize = u_usize.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:108:5 | LL | / if i_8 > i8::MIN { @@ -72,7 +72,7 @@ LL | | i_8 -= 1; LL | | } | |_____^ help: try: `i_8 = i_8.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:113:5 | LL | / if i_8 > i8::MIN { @@ -80,7 +80,7 @@ LL | | i_8 -= 1; LL | | } | |_____^ help: try: `i_8 = i_8.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:118:5 | LL | / if i_8 != i8::MIN { @@ -88,7 +88,7 @@ LL | | i_8 -= 1; LL | | } | |_____^ help: try: `i_8 = i_8.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:123:5 | LL | / if i_8 != i8::MIN { @@ -96,7 +96,7 @@ LL | | i_8 -= 1; LL | | } | |_____^ help: try: `i_8 = i_8.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:133:5 | LL | / if i_16 > i16::MIN { @@ -104,7 +104,7 @@ LL | | i_16 -= 1; LL | | } | |_____^ help: try: `i_16 = i_16.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:138:5 | LL | / if i_16 > i16::MIN { @@ -112,7 +112,7 @@ LL | | i_16 -= 1; LL | | } | |_____^ help: try: `i_16 = i_16.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:143:5 | LL | / if i_16 != i16::MIN { @@ -120,7 +120,7 @@ LL | | i_16 -= 1; LL | | } | |_____^ help: try: `i_16 = i_16.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:148:5 | LL | / if i_16 != i16::MIN { @@ -128,7 +128,7 @@ LL | | i_16 -= 1; LL | | } | |_____^ help: try: `i_16 = i_16.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:158:5 | LL | / if i_32 > i32::MIN { @@ -136,7 +136,7 @@ LL | | i_32 -= 1; LL | | } | |_____^ help: try: `i_32 = i_32.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:163:5 | LL | / if i_32 > i32::MIN { @@ -144,7 +144,7 @@ LL | | i_32 -= 1; LL | | } | |_____^ help: try: `i_32 = i_32.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:168:5 | LL | / if i_32 != i32::MIN { @@ -152,7 +152,7 @@ LL | | i_32 -= 1; LL | | } | |_____^ help: try: `i_32 = i_32.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:173:5 | LL | / if i_32 != i32::MIN { @@ -160,7 +160,7 @@ LL | | i_32 -= 1; LL | | } | |_____^ help: try: `i_32 = i_32.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:183:5 | LL | / if i64::MIN < i_64 { @@ -168,7 +168,7 @@ LL | | i_64 -= 1; LL | | } | |_____^ help: try: `i_64 = i_64.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:188:5 | LL | / if i64::MIN != i_64 { @@ -176,7 +176,7 @@ LL | | i_64 -= 1; LL | | } | |_____^ help: try: `i_64 = i_64.saturating_sub(1);` -error: Implicitly performing saturating subtraction +error: implicitly performing saturating subtraction --> $DIR/implicit_saturating_sub.rs:193:5 | LL | / if i64::MIN < i_64 { From 1f17c3b02bce95c7c95a320e9e6e8e88b216d235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 15:28:51 +0200 Subject: [PATCH 416/526] multiple_inherent_impl: make lint adhere to lint message convention --- clippy_lints/src/inherent_impl.rs | 4 ++-- tests/ui/impl.stderr | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 9fb10c7f627..4e6bb604785 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -81,9 +81,9 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { cx, MULTIPLE_INHERENT_IMPL, *additional_span, - "Multiple implementations of this structure", + "multiple implementations of this structure", |diag| { - diag.span_note(*initial_span, "First implementation here"); + diag.span_note(*initial_span, "first implementation here"); }, ) }) diff --git a/tests/ui/impl.stderr b/tests/ui/impl.stderr index 585d32845d2..aab688cc2d8 100644 --- a/tests/ui/impl.stderr +++ b/tests/ui/impl.stderr @@ -1,4 +1,4 @@ -error: Multiple implementations of this structure +error: multiple implementations of this structure --> $DIR/impl.rs:10:1 | LL | / impl MyStruct { @@ -7,7 +7,7 @@ LL | | } | |_^ | = note: `-D clippy::multiple-inherent-impl` implied by `-D warnings` -note: First implementation here +note: first implementation here --> $DIR/impl.rs:6:1 | LL | / impl MyStruct { @@ -15,7 +15,7 @@ LL | | fn first() {} LL | | } | |_^ -error: Multiple implementations of this structure +error: multiple implementations of this structure --> $DIR/impl.rs:24:5 | LL | / impl super::MyStruct { @@ -23,7 +23,7 @@ LL | | fn third() {} LL | | } | |_____^ | -note: First implementation here +note: first implementation here --> $DIR/impl.rs:6:1 | LL | / impl MyStruct { From 423615693ba27f77f2e01a82948bbe592f48f6d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 16:28:05 +0200 Subject: [PATCH 417/526] pub-enum-variant-names: make lint adhere to lint message convention --- clippy_lints/src/enum_variants.rs | 2 +- tests/ui/enum_variants.stderr | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index cb0fd59a2d4..d73d0f1752e 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -227,7 +227,7 @@ fn check_variant( cx, lint, span, - &format!("All variants have the same {}fix: `{}`", what, value), + &format!("all variants have the same {}fix: `{}`", what, value), None, &format!( "remove the {}fixes and use full paths to \ diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index 2835391de7f..3aa0e4ddcfe 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -24,7 +24,7 @@ error: Variant name starts with the enum's name LL | FoodBad, | ^^^^^^^ -error: All variants have the same prefix: `Food` +error: all variants have the same prefix: `Food` --> $DIR/enum_variants.rs:26:1 | LL | / enum Food { @@ -36,7 +36,7 @@ LL | | } | = help: remove the prefixes and use full paths to the variants instead of glob imports -error: All variants have the same prefix: `CallType` +error: all variants have the same prefix: `CallType` --> $DIR/enum_variants.rs:36:1 | LL | / enum BadCallType { @@ -48,7 +48,7 @@ LL | | } | = help: remove the prefixes and use full paths to the variants instead of glob imports -error: All variants have the same prefix: `Constant` +error: all variants have the same prefix: `Constant` --> $DIR/enum_variants.rs:48:1 | LL | / enum Consts { @@ -60,7 +60,7 @@ LL | | } | = help: remove the prefixes and use full paths to the variants instead of glob imports -error: All variants have the same prefix: `With` +error: all variants have the same prefix: `With` --> $DIR/enum_variants.rs:82:1 | LL | / enum Seallll { @@ -72,7 +72,7 @@ LL | | } | = help: remove the prefixes and use full paths to the variants instead of glob imports -error: All variants have the same prefix: `Prefix` +error: all variants have the same prefix: `Prefix` --> $DIR/enum_variants.rs:88:1 | LL | / enum NonCaps { @@ -84,7 +84,7 @@ LL | | } | = help: remove the prefixes and use full paths to the variants instead of glob imports -error: All variants have the same prefix: `With` +error: all variants have the same prefix: `With` --> $DIR/enum_variants.rs:94:1 | LL | / pub enum PubSeall { From 2de290d5c5e1d2f0c0f112a51f0cba2e0cb91636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 16:31:02 +0200 Subject: [PATCH 418/526] duration-subsec: make lint adhere to lint message convention --- clippy_lints/src/duration_subsec.rs | 2 +- tests/ui/duration_subsec.stderr | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 1dfb2eaa579..8ece44878fe 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for DurationSubsec { cx, DURATION_SUBSEC, expr.span, - &format!("Calling `{}()` is more concise than this calculation", suggested_fn), + &format!("calling `{}()` is more concise than this calculation", suggested_fn), "try", format!( "{}.{}()", diff --git a/tests/ui/duration_subsec.stderr b/tests/ui/duration_subsec.stderr index bd8adc2c570..cdbeff6a037 100644 --- a/tests/ui/duration_subsec.stderr +++ b/tests/ui/duration_subsec.stderr @@ -1,4 +1,4 @@ -error: Calling `subsec_millis()` is more concise than this calculation +error: calling `subsec_millis()` is more concise than this calculation --> $DIR/duration_subsec.rs:10:24 | LL | let bad_millis_1 = dur.subsec_micros() / 1_000; @@ -6,25 +6,25 @@ LL | let bad_millis_1 = dur.subsec_micros() / 1_000; | = note: `-D clippy::duration-subsec` implied by `-D warnings` -error: Calling `subsec_millis()` is more concise than this calculation +error: calling `subsec_millis()` is more concise than this calculation --> $DIR/duration_subsec.rs:11:24 | LL | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` -error: Calling `subsec_micros()` is more concise than this calculation +error: calling `subsec_micros()` is more concise than this calculation --> $DIR/duration_subsec.rs:16:22 | LL | let bad_micros = dur.subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` -error: Calling `subsec_micros()` is more concise than this calculation +error: calling `subsec_micros()` is more concise than this calculation --> $DIR/duration_subsec.rs:21:13 | LL | let _ = (&dur).subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&dur).subsec_micros()` -error: Calling `subsec_micros()` is more concise than this calculation +error: calling `subsec_micros()` is more concise than this calculation --> $DIR/duration_subsec.rs:25:13 | LL | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; From db390f5e6a2e68a0f9e0d235f2b734e907cafef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 16:35:09 +0200 Subject: [PATCH 419/526] enum-clike-unportable-variant: tweak message a bit (Clike -> C-like) --- clippy_lints/src/enum_clike.rs | 2 +- tests/ui/enum_clike_unportable_variant.stderr | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 91214f277be..48caf48dbdb 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { cx, ENUM_CLIKE_UNPORTABLE_VARIANT, var.span, - "Clike enum variant discriminant is not portable to 32-bit targets", + "C-like enum variant discriminant is not portable to 32-bit targets", ); }; } diff --git a/tests/ui/enum_clike_unportable_variant.stderr b/tests/ui/enum_clike_unportable_variant.stderr index 71f3f5e083e..5935eea5e03 100644 --- a/tests/ui/enum_clike_unportable_variant.stderr +++ b/tests/ui/enum_clike_unportable_variant.stderr @@ -1,4 +1,4 @@ -error: Clike enum variant discriminant is not portable to 32-bit targets +error: C-like enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:8:5 | LL | X = 0x1_0000_0000, @@ -6,49 +6,49 @@ LL | X = 0x1_0000_0000, | = note: `-D clippy::enum-clike-unportable-variant` implied by `-D warnings` -error: Clike enum variant discriminant is not portable to 32-bit targets +error: C-like enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:15:5 | LL | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ -error: Clike enum variant discriminant is not portable to 32-bit targets +error: C-like enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:18:5 | LL | A = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ -error: Clike enum variant discriminant is not portable to 32-bit targets +error: C-like enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:25:5 | LL | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ -error: Clike enum variant discriminant is not portable to 32-bit targets +error: C-like enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:26:5 | LL | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ -error: Clike enum variant discriminant is not portable to 32-bit targets +error: C-like enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:28:5 | LL | C = (i32::MIN as isize) - 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Clike enum variant discriminant is not portable to 32-bit targets +error: C-like enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:34:5 | LL | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ -error: Clike enum variant discriminant is not portable to 32-bit targets +error: C-like enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:35:5 | LL | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ -error: Clike enum variant discriminant is not portable to 32-bit targets +error: C-like enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:40:5 | LL | X = <usize as Trait>::Number, From 89591a78b83df30830bcc8f6fe57f6fe1fbf918e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 16:38:20 +0200 Subject: [PATCH 420/526] enum-variant-names: make lint adhere to lint message convention --- clippy_lints/src/enum_variants.rs | 4 ++-- tests/ui/enum_variants.stderr | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index d73d0f1752e..a9294a87f15 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -183,10 +183,10 @@ fn check_variant( && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase()) && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric()) { - span_lint(cx, lint, var.span, "Variant name starts with the enum's name"); + span_lint(cx, lint, var.span, "variant name starts with the enum's name"); } if partial_rmatch(item_name, &name) == item_name_chars { - span_lint(cx, lint, var.span, "Variant name ends with the enum's name"); + span_lint(cx, lint, var.span, "variant name ends with the enum's name"); } } let first = &def.variants[0].ident.name.as_str(); diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index 3aa0e4ddcfe..b1d481190ff 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -1,4 +1,4 @@ -error: Variant name ends with the enum's name +error: variant name ends with the enum's name --> $DIR/enum_variants.rs:16:5 | LL | cFoo, @@ -6,19 +6,19 @@ LL | cFoo, | = note: `-D clippy::enum-variant-names` implied by `-D warnings` -error: Variant name starts with the enum's name +error: variant name starts with the enum's name --> $DIR/enum_variants.rs:27:5 | LL | FoodGood, | ^^^^^^^^ -error: Variant name starts with the enum's name +error: variant name starts with the enum's name --> $DIR/enum_variants.rs:28:5 | LL | FoodMiddle, | ^^^^^^^^^^ -error: Variant name starts with the enum's name +error: variant name starts with the enum's name --> $DIR/enum_variants.rs:29:5 | LL | FoodBad, From 605e027fda4420669784864940abcbabef5b0efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 16:40:45 +0200 Subject: [PATCH 421/526] if_let_some_result: make lint adhere to lint message convention --- clippy_lints/src/if_let_some_result.rs | 4 ++-- tests/ui/if_let_some_result.stderr | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/if_let_some_result.rs b/clippy_lints/src/if_let_some_result.rs index 5b22df5fe49..28b20cdeac3 100644 --- a/clippy_lints/src/if_let_some_result.rs +++ b/clippy_lints/src/if_let_some_result.rs @@ -61,8 +61,8 @@ impl<'tcx> LateLintPass<'tcx> for OkIfLet { cx, IF_LET_SOME_RESULT, expr.span.with_hi(op.span.hi()), - "Matching on `Some` with `ok()` is redundant", - &format!("Consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string), + "matching on `Some` with `ok()` is redundant", + &format!("consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string), sugg, applicability, ); diff --git a/tests/ui/if_let_some_result.stderr b/tests/ui/if_let_some_result.stderr index 334ccb01016..6afee0f36b9 100644 --- a/tests/ui/if_let_some_result.stderr +++ b/tests/ui/if_let_some_result.stderr @@ -1,22 +1,22 @@ -error: Matching on `Some` with `ok()` is redundant +error: matching on `Some` with `ok()` is redundant --> $DIR/if_let_some_result.rs:6:5 | LL | if let Some(y) = x.parse().ok() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::if-let-some-result` implied by `-D warnings` -help: Consider matching on `Ok(y)` and removing the call to `ok` instead +help: consider matching on `Ok(y)` and removing the call to `ok` instead | LL | if let Ok(y) = x.parse() { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: Matching on `Some` with `ok()` is redundant +error: matching on `Some` with `ok()` is redundant --> $DIR/if_let_some_result.rs:24:9 | LL | if let Some(y) = x . parse() . ok () { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: Consider matching on `Ok(y)` and removing the call to `ok` instead +help: consider matching on `Ok(y)` and removing the call to `ok` instead | LL | if let Ok(y) = x . parse() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From be3e695b60b07e911a88f6cb660c5617836c5365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Tue, 11 Aug 2020 16:43:53 +0200 Subject: [PATCH 422/526] if_not_else: make lint adhere to lint message convention --- clippy_lints/src/if_not_else.rs | 4 ++-- clippy_lints/src/use_self.rs | 2 +- src/lintlist/mod.rs | 2 +- tests/ui/if_not_else.stderr | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index c11e291f98e..b86d2e76656 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -60,7 +60,7 @@ impl EarlyLintPass for IfNotElse { cx, IF_NOT_ELSE, item.span, - "Unnecessary boolean `not` operation", + "unnecessary boolean `not` operation", None, "remove the `!` and swap the blocks of the `if`/`else`", ); @@ -70,7 +70,7 @@ impl EarlyLintPass for IfNotElse { cx, IF_NOT_ELSE, item.span, - "Unnecessary `!=` operation", + "unnecessary `!=` operation", None, "change to `==` and swap the blocks of the `if`/`else`", ); diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 776c6bc57ca..427a1b65773 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -50,7 +50,7 @@ declare_clippy_lint! { /// ``` pub USE_SELF, nursery, - "Unnecessary structure name repetition whereas `Self` is applicable" + "unnecessary structure name repetition whereas `Self` is applicable" } declare_lint_pass!(UseSelf => [USE_SELF]); diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index bbb300296be..ccc9e250952 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2498,7 +2498,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ Lint { name: "use_self", group: "nursery", - desc: "Unnecessary structure name repetition whereas `Self` is applicable", + desc: "unnecessary structure name repetition whereas `Self` is applicable", deprecation: None, module: "use_self", }, diff --git a/tests/ui/if_not_else.stderr b/tests/ui/if_not_else.stderr index 78bc4d4bd20..53d1b86d02a 100644 --- a/tests/ui/if_not_else.stderr +++ b/tests/ui/if_not_else.stderr @@ -1,4 +1,4 @@ -error: Unnecessary boolean `not` operation +error: unnecessary boolean `not` operation --> $DIR/if_not_else.rs:9:5 | LL | / if !bla() { @@ -11,7 +11,7 @@ LL | | } = note: `-D clippy::if-not-else` implied by `-D warnings` = help: remove the `!` and swap the blocks of the `if`/`else` -error: Unnecessary `!=` operation +error: unnecessary `!=` operation --> $DIR/if_not_else.rs:14:5 | LL | / if 4 != 5 { From 8a96b9cdfe408106fff94745fee1223b2e3ddb26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Wed, 12 Aug 2020 14:27:06 +0200 Subject: [PATCH 423/526] write.rs: don't clone TokenStream --- clippy_lints/src/write.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 063f94582b9..5f88dcb188a 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -237,7 +237,7 @@ impl EarlyLintPass for Write { fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &MacCall) { if mac.path == sym!(println) { span_lint(cx, PRINT_STDOUT, mac.span(), "use of `println!`"); - if let (Some(fmt_str), _) = self.check_tts(cx, &mac.args.inner_tokens(), false) { + if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) { if fmt_str.symbol == Symbol::intern("") { span_lint_and_sugg( cx, @@ -252,7 +252,7 @@ impl EarlyLintPass for Write { } } else if mac.path == sym!(print) { span_lint(cx, PRINT_STDOUT, mac.span(), "use of `print!`"); - if let (Some(fmt_str), _) = self.check_tts(cx, &mac.args.inner_tokens(), false) { + if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) { if check_newlines(&fmt_str) { span_lint_and_then( cx, @@ -273,7 +273,7 @@ impl EarlyLintPass for Write { } } } else if mac.path == sym!(write) { - if let (Some(fmt_str), _) = self.check_tts(cx, &mac.args.inner_tokens(), true) { + if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), true) { if check_newlines(&fmt_str) { span_lint_and_then( cx, @@ -294,7 +294,7 @@ impl EarlyLintPass for Write { } } } else if mac.path == sym!(writeln) { - if let (Some(fmt_str), expr) = self.check_tts(cx, &mac.args.inner_tokens(), true) { + if let (Some(fmt_str), expr) = self.check_tts(cx, mac.args.inner_tokens(), true) { if fmt_str.symbol == Symbol::intern("") { let mut applicability = Applicability::MachineApplicable; let suggestion = expr.map_or_else( @@ -364,17 +364,11 @@ impl Write { /// (Some("string to write: {}"), Some(buf)) /// ``` #[allow(clippy::too_many_lines)] - fn check_tts<'a>( - &self, - cx: &EarlyContext<'a>, - tts: &TokenStream, - is_write: bool, - ) -> (Option<StrLit>, Option<Expr>) { + fn check_tts<'a>(&self, cx: &EarlyContext<'a>, tts: TokenStream, is_write: bool) -> (Option<StrLit>, Option<Expr>) { use rustc_parse_format::{ AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec, ParseMode, Parser, Piece, }; - let tts = tts.clone(); let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, false, None); let mut expr: Option<Expr> = None; From 7d2e42daec1a56ad8f70a2b146bd842e98e0430d Mon Sep 17 00:00:00 2001 From: Ryan Wiedemann <Ryan1729@gmail.com> Date: Wed, 12 Aug 2020 08:54:32 -0600 Subject: [PATCH 424/526] fix typo pointed out in review comment Co-authored-by: Philipp Krones <hello@philkrones.com> --- clippy_lints/src/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 7f58a381adc..31da45f6b8a 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -37,7 +37,7 @@ declare_clippy_lint! { /// this lint on them will fix the problem, but they may be in other crates. /// /// One notable example of a function that may cause issues, and which cannot - /// easily be changed due to beinng in the standard library is `Vec::contains`. + /// easily be changed due to being in the standard library is `Vec::contains`. /// when called on a `Vec<Vec<T>>`. If a `&Vec` is passed to that method then /// it will compile, but if a `&[T]` is passed then it will not compile. /// From 0fc61becb5f1b9a183311c8b053d996b8695a071 Mon Sep 17 00:00:00 2001 From: Ryan Wiedemann <Ryan1729@gmail.com> Date: Mon, 10 Aug 2020 07:30:55 -0600 Subject: [PATCH 425/526] Add the other overloadable operations to suspicious_arithmetic_impl In #2268 I idly mused that the other user-overloadable operations could be added to this lint. Knowing that the lint was arguably incomplete was gnawing at the back of my mind, so I figured that I might as well make this PR, particularly given the change needed was so small. --- clippy_lints/src/suspicious_trait_impl.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 4e335a0222f..e026f27d9a7 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -86,12 +86,18 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { cx, expr, binop.node, - &["Add", "Sub", "Mul", "Div"], + &["Add", "Sub", "Mul", "Div", "Rem", "BitAnd", "BitOr", "BitXor", "Shl", "Shr"], &[ hir::BinOpKind::Add, hir::BinOpKind::Sub, hir::BinOpKind::Mul, hir::BinOpKind::Div, + hir::BinOpKind::Rem, + hir::BinOpKind::BitAnd, + hir::BinOpKind::BitOr, + hir::BinOpKind::BitXor, + hir::BinOpKind::Shl, + hir::BinOpKind::Shr, ], ) { span_lint( From 616682deb72aa3760b1af3c701090e894f227ac7 Mon Sep 17 00:00:00 2001 From: Ryan Wiedemann <Ryan1729@gmail.com> Date: Mon, 10 Aug 2020 09:18:16 -0600 Subject: [PATCH 426/526] formatting --- clippy_lints/src/suspicious_trait_impl.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index e026f27d9a7..596d4eb6141 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -86,7 +86,9 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { cx, expr, binop.node, - &["Add", "Sub", "Mul", "Div", "Rem", "BitAnd", "BitOr", "BitXor", "Shl", "Shr"], + &[ + "Add", "Sub", "Mul", "Div", "Rem", "BitAnd", "BitOr", "BitXor", "Shl", "Shr" + ], &[ hir::BinOpKind::Add, hir::BinOpKind::Sub, From c70581732de89a1b4f064818edeca9a18913ded2 Mon Sep 17 00:00:00 2001 From: Ryan Wiedemann <Ryan1729@gmail.com> Date: Mon, 10 Aug 2020 09:21:20 -0600 Subject: [PATCH 427/526] trailing comma Should have actually ran rustfmt on it, rather than attempting to fix it manually --- clippy_lints/src/suspicious_trait_impl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 596d4eb6141..3a688a7bbef 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -87,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { expr, binop.node, &[ - "Add", "Sub", "Mul", "Div", "Rem", "BitAnd", "BitOr", "BitXor", "Shl", "Shr" + "Add", "Sub", "Mul", "Div", "Rem", "BitAnd", "BitOr", "BitXor", "Shl", "Shr", ], &[ hir::BinOpKind::Add, From f4eeff99b6f2d5a01f7af1eae46e1b84525bf95a Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Wed, 12 Aug 2020 09:17:40 -0600 Subject: [PATCH 428/526] add tests for Rem, BitAnd, BitOr, BitXor, Shl, and Shr --- tests/ui/suspicious_arithmetic_impl.rs | 52 +++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index 60c2f3ec9b6..5c280efac1a 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -1,5 +1,7 @@ #![warn(clippy::suspicious_arithmetic_impl)] -use std::ops::{Add, AddAssign, BitOrAssign, Div, DivAssign, Mul, MulAssign, Sub}; +use std::ops::{ + Add, AddAssign, BitAnd, BitOr, BitOrAssign, BitXor, Div, DivAssign, Mul, MulAssign, Rem, Shl, Shr, Sub, +}; #[derive(Copy, Clone)] struct Foo(u32); @@ -61,6 +63,54 @@ impl Div for Foo { } } +impl Rem for Foo { + type Output = Foo; + + fn rem(self, other: Self) -> Self { + Foo(self.0 / other.0) + } +} + +impl BitAnd for Foo { + type Output = Foo; + + fn bitand(self, other: Self) -> Self { + Foo(self.0 | other.0) + } +} + +impl BitOr for Foo { + type Output = Foo; + + fn bitor(self, other: Self) -> Self { + Foo(self.0 ^ other.0) + } +} + +impl BitXor for Foo { + type Output = Foo; + + fn bitxor(self, other: Self) -> Self { + Foo(self.0 & other.0) + } +} + +impl Shl for Foo { + type Output = Foo; + + fn shl(self, other: Self) -> Self { + Foo(self.0 >> other.0) + } +} + +impl Shr for Foo { + type Output = Foo; + + fn shr(self, other: Self) -> Self { + Foo(self.0 << other.0) + } +} + struct Bar(i32); impl Add for Bar { From 7bd7a46331fbaa8b8ebbaacf178c988498df9f13 Mon Sep 17 00:00:00 2001 From: Ryan1729 <Ryan1729@gmail.com> Date: Wed, 12 Aug 2020 10:49:12 -0600 Subject: [PATCH 429/526] run tests/ui/update-references.sh to update 'suspicious_arithmetic_impl.rs' --- tests/ui/suspicious_arithmetic_impl.stderr | 44 ++++++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 23d47e3f1ff..388fc740082 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -1,5 +1,5 @@ error: suspicious use of binary operator in `Add` impl - --> $DIR/suspicious_arithmetic_impl.rs:11:20 + --> $DIR/suspicious_arithmetic_impl.rs:13:20 | LL | Foo(self.0 - other.0) | ^ @@ -7,7 +7,7 @@ LL | Foo(self.0 - other.0) = note: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings` error: suspicious use of binary operator in `AddAssign` impl - --> $DIR/suspicious_arithmetic_impl.rs:17:23 + --> $DIR/suspicious_arithmetic_impl.rs:19:23 | LL | *self = *self - other; | ^ @@ -15,10 +15,46 @@ LL | *self = *self - other; = note: `#[deny(clippy::suspicious_op_assign_impl)]` on by default error: suspicious use of binary operator in `MulAssign` impl - --> $DIR/suspicious_arithmetic_impl.rs:30:16 + --> $DIR/suspicious_arithmetic_impl.rs:32:16 | LL | self.0 /= other.0; | ^^ -error: aborting due to 3 previous errors +error: suspicious use of binary operator in `Rem` impl + --> $DIR/suspicious_arithmetic_impl.rs:70:20 + | +LL | Foo(self.0 / other.0) + | ^ + +error: suspicious use of binary operator in `BitAnd` impl + --> $DIR/suspicious_arithmetic_impl.rs:78:20 + | +LL | Foo(self.0 | other.0) + | ^ + +error: suspicious use of binary operator in `BitOr` impl + --> $DIR/suspicious_arithmetic_impl.rs:86:20 + | +LL | Foo(self.0 ^ other.0) + | ^ + +error: suspicious use of binary operator in `BitXor` impl + --> $DIR/suspicious_arithmetic_impl.rs:94:20 + | +LL | Foo(self.0 & other.0) + | ^ + +error: suspicious use of binary operator in `Shl` impl + --> $DIR/suspicious_arithmetic_impl.rs:102:20 + | +LL | Foo(self.0 >> other.0) + | ^^ + +error: suspicious use of binary operator in `Shr` impl + --> $DIR/suspicious_arithmetic_impl.rs:110:20 + | +LL | Foo(self.0 << other.0) + | ^^ + +error: aborting due to 9 previous errors From 480ccc3dbec4440bea0aa1f47d2ad21ebcdd578e Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Tue, 11 Aug 2020 18:01:10 -0700 Subject: [PATCH 430/526] Change Rc<Box<T>> recommendation to be Rc<T> instead of Box<T> --- clippy_lints/src/types.rs | 15 +++++++++++++-- tests/ui/redundant_allocation.fixed | 2 +- tests/ui/redundant_allocation.stderr | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c3dea447521..78cebc30472 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -353,14 +353,25 @@ impl Types { ); return; // don't recurse into the type } - if let Some(span) = match_type_parameter(cx, qpath, &paths::BOX) { + if match_type_parameter(cx, qpath, &paths::BOX).is_some() { + let box_ty = match &last_path_segment(qpath).args.unwrap().args[0] { + GenericArg::Type(ty) => match &ty.kind { + TyKind::Path(qpath) => qpath, + _ => panic!("Box that isn't a type"), + }, + _ => panic!("Rc without type argument"), + }; + let inner_span = match &last_path_segment(&box_ty).args.unwrap().args[0] { + GenericArg::Type(ty) => ty.span, + _ => panic!("Box without type argument"), + }; span_lint_and_sugg( cx, REDUNDANT_ALLOCATION, hir_ty.span, "usage of `Rc<Box<T>>`", "try", - snippet(cx, span, "..").to_string(), + format!("Rc<{}>", snippet(cx, inner_span, "..")), Applicability::MachineApplicable, ); return; // don't recurse into the type diff --git a/tests/ui/redundant_allocation.fixed b/tests/ui/redundant_allocation.fixed index 26635833458..6514fd6d1ac 100644 --- a/tests/ui/redundant_allocation.fixed +++ b/tests/ui/redundant_allocation.fixed @@ -33,7 +33,7 @@ pub fn test5(a: Rc<bool>) {} // Rc<Box<T>> -pub fn test6(a: Box<bool>) {} +pub fn test6(a: Rc<bool>) {} // Box<&T> diff --git a/tests/ui/redundant_allocation.stderr b/tests/ui/redundant_allocation.stderr index eaa57ce3024..92e4f67f5db 100644 --- a/tests/ui/redundant_allocation.stderr +++ b/tests/ui/redundant_allocation.stderr @@ -28,7 +28,7 @@ error: usage of `Rc<Box<T>>` --> $DIR/redundant_allocation.rs:36:17 | LL | pub fn test6(a: Rc<Box<bool>>) {} - | ^^^^^^^^^^^^^ help: try: `Box<bool>` + | ^^^^^^^^^^^^^ help: try: `Rc<bool>` error: usage of `Box<&T>` --> $DIR/redundant_allocation.rs:40:22 From 5634c8da02862653be557c6ab1242a6c9ce86ce8 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Wed, 12 Aug 2020 21:37:27 +0200 Subject: [PATCH 431/526] Fix: keep parenthesis for suggestion in `useless_conversion` lint --- clippy_lints/src/useless_conversion.rs | 5 +++-- tests/ui/useless_conversion.fixed | 5 +++++ tests/ui/useless_conversion.rs | 5 +++++ tests/ui/useless_conversion.stderr | 8 +++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 1bf37632e32..4ab2b5e796d 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -1,3 +1,4 @@ +use crate::utils::sugg::Sugg; use crate::utils::{ get_parent_expr, is_type_diagnostic_item, match_def_path, match_trait_method, paths, snippet, snippet_with_macro_callsite, span_lint_and_help, span_lint_and_sugg, @@ -158,7 +159,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { if TyS::same_type(a, b); then { - let sugg = snippet(cx, args[0].span.source_callsite(), "<expr>").into_owned(); + let sugg = Sugg::hir_with_macro_callsite(cx, &args[0], "<expr>").maybe_par(); let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); span_lint_and_sugg( @@ -167,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { e.span, "useless conversion to the same type", &sugg_msg, - sugg, + sugg.to_string(), Applicability::MachineApplicable, // snippet ); } diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed index 813cdaecaa9..8a9b0cd3cf0 100644 --- a/tests/ui/useless_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -64,4 +64,9 @@ fn main() { let _ = "".lines(); let _ = vec![1, 2, 3].into_iter(); let _: String = format!("Hello {}", "world"); + + // keep parenthesis around `a + b` for suggestion (see #4750) + let a: i32 = 1; + let b: i32 = 1; + let _ = (a + b) * 3; } diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs index 540fea23b36..4faa1572973 100644 --- a/tests/ui/useless_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -64,4 +64,9 @@ fn main() { let _ = "".lines().into_iter(); let _ = vec![1, 2, 3].into_iter().into_iter(); let _: String = format!("Hello {}", "world").into(); + + // keep parenthesis around `a + b` for suggestion (see #4750) + let a: i32 = 1; + let b: i32 = 1; + let _ = i32::from(a + b) * 3; } diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index b958b035452..f1e880d2696 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -64,5 +64,11 @@ error: useless conversion to the same type LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` -error: aborting due to 10 previous errors +error: useless conversion to the same type + --> $DIR/useless_conversion.rs:71:13 + | +LL | let _ = i32::from(a + b) * 3; + | ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)` + +error: aborting due to 11 previous errors From 4e28d99f413572087a74e1a70b17f051a08d3821 Mon Sep 17 00:00:00 2001 From: JarredAllen <jarredallen73@gmail.com> Date: Wed, 12 Aug 2020 13:24:55 -0700 Subject: [PATCH 432/526] Replace panics with early returns --- clippy_lints/src/types.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 78cebc30472..e0204273197 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -357,13 +357,13 @@ impl Types { let box_ty = match &last_path_segment(qpath).args.unwrap().args[0] { GenericArg::Type(ty) => match &ty.kind { TyKind::Path(qpath) => qpath, - _ => panic!("Box that isn't a type"), + _ => return, }, - _ => panic!("Rc without type argument"), + _ => return, }; let inner_span = match &last_path_segment(&box_ty).args.unwrap().args[0] { GenericArg::Type(ty) => ty.span, - _ => panic!("Box without type argument"), + _ => return, }; span_lint_and_sugg( cx, From 9f827abeb0ad8f4e3ed37af462907a31be7f7cdb Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Thu, 13 Aug 2020 09:02:49 +0900 Subject: [PATCH 433/526] Add reference to rustc-dev-guide about lint message --- doc/adding_lints.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 168092f7329..3c782e9b17f 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -295,8 +295,14 @@ impl EarlyLintPass for FooFunctions { Running our UI test should now produce output that contains the lint message. +According to [the rustc-dev-guide], the text should be matter of fact and avoid +capitalization and periods, unless multiple sentences are needed. +When code or an identifier must appear in a message or label, it should be +surrounded with single acute accents \`. + [check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html#method.check_fn [diagnostics]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/diagnostics.rs +[the rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/diagnostics.html ## Adding the lint logic From 48a142559de48ff38326e8276ffdfce9ef3b5c95 Mon Sep 17 00:00:00 2001 From: Erich Gubler <erichdongubler@gmail.com> Date: Thu, 13 Aug 2020 13:52:21 -0600 Subject: [PATCH 434/526] docs: typo in `temporary_cstring_as_ptr`: s/point/&s --- clippy_lints/src/methods/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index f4eb9c4516f..b6266ef2ba1 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -799,7 +799,7 @@ declare_clippy_lint! { /// call_some_ffi_func(c_str); /// } /// ``` - /// Here `c_str` point to a freed address. The correct use would be: + /// Here `c_str` points to a freed address. The correct use would be: /// ```rust /// # use std::ffi::CString; /// # fn call_some_ffi_func(_: *const i8) {} From 8514b8407ac83dc02532c82c9188c49967d9a5d6 Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Fri, 14 Aug 2020 14:13:35 +0200 Subject: [PATCH 435/526] appreciative too_large_for_stack in useless `vec!` Fixes: #5847 --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_lints/src/vec.rs | 97 +++++++++++++++++++++------------- tests/ui/vec.fixed | 7 +++ tests/ui/vec.rs | 7 +++ 5 files changed, 76 insertions(+), 39 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6ad525d7620..4a4445200a1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -930,11 +930,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || box cognitive_complexity::CognitiveComplexity::new(cognitive_complexity_threshold)); let too_large_for_stack = conf.too_large_for_stack; store.register_late_pass(move || box escape::BoxedLocal{too_large_for_stack}); + store.register_late_pass(move || box vec::UselessVec{too_large_for_stack}); store.register_late_pass(|| box panic_unimplemented::PanicUnimplemented); store.register_late_pass(|| box strings::StringLitAsBytes); store.register_late_pass(|| box derive::Derive); store.register_late_pass(|| box types::CharLitAsU8); - store.register_late_pass(|| box vec::UselessVec); store.register_late_pass(|| box drop_bounds::DropBounds); store.register_late_pass(|| box get_last_with_len::GetLastWithLen); store.register_late_pass(|| box drop_forget_ref::DropForgetRef); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index ba3492a6fff..292dbd7ad6b 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -138,7 +138,7 @@ define_Conf! { (type_complexity_threshold, "type_complexity_threshold": u64, 250), /// Lint: MANY_SINGLE_CHAR_NAMES. The maximum number of single char bindings a scope may have (single_char_binding_names_threshold, "single_char_binding_names_threshold": u64, 4), - /// Lint: BOXED_LOCAL. The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap + /// Lint: BOXED_LOCAL, USELESS_VEC. The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap (too_large_for_stack, "too_large_for_stack": u64, 200), /// Lint: ENUM_VARIANT_NAMES. The minimum number of enum variants for the lints about variant names to trigger (enum_variant_name_threshold, "enum_variant_name_threshold": u64, 3), diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index f2e76442a19..84e907d7125 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,13 +1,20 @@ -use crate::consts::constant; +use crate::consts::{constant, Constant}; +use crate::rustc_target::abi::LayoutOf; use crate::utils::{higher, is_copy, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; +#[allow(clippy::module_name_repetitions)] +#[derive(Copy, Clone)] +pub struct UselessVec { + pub too_large_for_stack: u64, +} + declare_clippy_lint! { /// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would /// be possible. @@ -31,7 +38,7 @@ declare_clippy_lint! { "useless `vec!`" } -declare_lint_pass!(UselessVec => [USELESS_VEC]); +impl_lint_pass!(UselessVec => [USELESS_VEC]); impl<'tcx> LateLintPass<'tcx> for UselessVec { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { @@ -42,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { if let ExprKind::AddrOf(BorrowKind::Ref, _, ref addressee) = expr.kind; if let Some(vec_args) = higher::vec_macro(cx, addressee); then { - check_vec_macro(cx, &vec_args, expr.span); + self.check_vec_macro(cx, &vec_args, expr.span); } } @@ -60,46 +67,62 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { .ctxt() .outer_expn_data() .call_site; - check_vec_macro(cx, &vec_args, span); + self.check_vec_macro(cx, &vec_args, span); } } } } -fn check_vec_macro<'tcx>(cx: &LateContext<'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) { - let mut applicability = Applicability::MachineApplicable; - let snippet = match *vec_args { - higher::VecArgs::Repeat(elem, len) => { - if constant(cx, cx.typeck_results(), len).is_some() { - format!( - "&[{}; {}]", - snippet_with_applicability(cx, elem.span, "elem", &mut applicability), - snippet_with_applicability(cx, len.span, "len", &mut applicability) - ) - } else { - return; - } - }, - higher::VecArgs::Vec(args) => { - if let Some(last) = args.iter().last() { - let span = args[0].span.to(last.span); +impl UselessVec { + fn check_vec_macro<'tcx>(self, cx: &LateContext<'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) { + let mut applicability = Applicability::MachineApplicable; + let snippet = match *vec_args { + higher::VecArgs::Repeat(elem, len) => { + if let Some((Constant::Int(len_constant), _)) = constant(cx, cx.typeck_results(), len) { + #[allow(clippy::cast_possible_truncation)] + if len_constant as u64 * size_of(cx, elem) > self.too_large_for_stack { + return; + } - format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability)) - } else { - "&[]".into() - } - }, - }; + format!( + "&[{}; {}]", + snippet_with_applicability(cx, elem.span, "elem", &mut applicability), + snippet_with_applicability(cx, len.span, "len", &mut applicability) + ) + } else { + return; + } + }, + higher::VecArgs::Vec(args) => { + if let Some(last) = args.iter().last() { + #[allow(clippy::cast_possible_truncation)] + if args.len() as u64 * size_of(cx, last) > self.too_large_for_stack { + return; + } + let span = args[0].span.to(last.span); - span_lint_and_sugg( - cx, - USELESS_VEC, - span, - "useless use of `vec!`", - "you can use a slice directly", - snippet, - applicability, - ); + format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability)) + } else { + "&[]".into() + } + }, + }; + + span_lint_and_sugg( + cx, + USELESS_VEC, + span, + "useless use of `vec!`", + "you can use a slice directly", + snippet, + applicability, + ); + } +} + +fn size_of(cx: &LateContext<'_>, expr: &Expr<'_>) -> u64 { + let ty = cx.typeck_results().expr_ty_adjusted(expr); + cx.layout_of(ty).map_or(0, |l| l.size.bytes()) } /// Returns the item type of the vector (i.e., the `T` in `Vec<T>`). diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index e73a791891f..85677159620 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -52,4 +52,11 @@ fn main() { for a in vec![NonCopy, NonCopy] { println!("{:?}", a); } + + on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` + + // Ok + for a in vec![1; 201] { + println!("{:?}", a); + } } diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index 3eb960f53d7..03b8ee81665 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -52,4 +52,11 @@ fn main() { for a in vec![NonCopy, NonCopy] { println!("{:?}", a); } + + on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` + + // Ok + for a in vec![1; 201] { + println!("{:?}", a); + } } From 8e549978e58fe724c4637ab71808ff8785743c61 Mon Sep 17 00:00:00 2001 From: chansuke <chansuke@georepublic.de> Date: Wed, 22 Jul 2020 21:44:53 +0900 Subject: [PATCH 436/526] Don't use `to_string` in impl Display --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 ++ clippy_lints/src/to_string_in_display.rs | 100 +++++++++++++++++++++++ src/lintlist/mod.rs | 7 ++ tests/ui/to_string_in_display.rs | 55 +++++++++++++ tests/ui/to_string_in_display.stderr | 10 +++ 6 files changed, 178 insertions(+) create mode 100644 clippy_lints/src/to_string_in_display.rs create mode 100644 tests/ui/to_string_in_display.rs create mode 100644 tests/ui/to_string_in_display.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e9ed54c848..71433773254 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1723,6 +1723,7 @@ Released 2018-09-13 [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment [`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr [`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some +[`to_string_in_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_display [`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo [`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments [`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6ad525d7620..7ae185103a3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -296,6 +296,7 @@ mod swap; mod tabs_in_doc_comments; mod temporary_assignment; mod to_digit_is_some; +mod to_string_in_display; mod trait_bounds; mod transmute; mod transmuting_null; @@ -788,6 +789,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &tabs_in_doc_comments::TABS_IN_DOC_COMMENTS, &temporary_assignment::TEMPORARY_ASSIGNMENT, &to_digit_is_some::TO_DIGIT_IS_SOME, + &to_string_in_display::TO_STRING_IN_DISPLAY, &trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS, &trait_bounds::TYPE_REPETITION_IN_BOUNDS, &transmute::CROSSPOINTER_TRANSMUTE, @@ -1017,6 +1019,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box reference::DerefAddrOf); store.register_early_pass(|| box reference::RefInDeref); store.register_early_pass(|| box double_parens::DoubleParens); + store.register_late_pass(|| box to_string_in_display::ToStringInDisplay::new()); store.register_early_pass(|| box unsafe_removed_from_name::UnsafeNameRemoval); store.register_early_pass(|| box if_not_else::IfNotElse); store.register_early_pass(|| box else_if_without_else::ElseIfWithoutElse); @@ -1427,6 +1430,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT), LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME), + LintId::of(&to_string_in_display::TO_STRING_IN_DISPLAY), LintId::of(&transmute::CROSSPOINTER_TRANSMUTE), LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), LintId::of(&transmute::TRANSMUTE_BYTES_TO_STR), @@ -1708,6 +1712,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), LintId::of(&swap::ALMOST_SWAPPED), + LintId::of(&to_string_in_display::TO_STRING_IN_DISPLAY), LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE), LintId::of(&transmute::WRONG_TRANSMUTE), LintId::of(&transmuting_null::TRANSMUTING_NULL), diff --git a/clippy_lints/src/to_string_in_display.rs b/clippy_lints/src/to_string_in_display.rs new file mode 100644 index 00000000000..11bdd27d9b1 --- /dev/null +++ b/clippy_lints/src/to_string_in_display.rs @@ -0,0 +1,100 @@ +use crate::utils::{match_def_path, match_trait_method, paths, span_lint}; +use if_chain::if_chain; +use rustc_hir::{Expr, ExprKind, Item, ItemKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; + +declare_clippy_lint! { + /// **What it does:** Checks for uses of `to_string()` in `Display` traits. + /// + /// **Why is this bad?** Usually `to_string` is implemented indirectly + /// via `Display`. Hence using it while implementing `Display` would + /// lead to infinite recursion. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// use std::fmt; + /// + /// struct Structure(i32); + /// impl fmt::Display for Structure { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "{}", self.to_string()) + /// } + /// } + /// + /// ``` + /// Use instead: + /// ```rust + /// use std::fmt; + /// + /// struct Structure(i32); + /// impl fmt::Display for Structure { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "{}", self.0) + /// } + /// } + /// ``` + pub TO_STRING_IN_DISPLAY, + correctness, + "to_string method used while implementing Display trait" +} + +#[derive(Default)] +pub struct ToStringInDisplay { + in_display_impl: bool, +} + +impl ToStringInDisplay { + pub fn new() -> Self { + Self { in_display_impl: false } + } +} + +impl_lint_pass!(ToStringInDisplay => [TO_STRING_IN_DISPLAY]); + +impl LateLintPass<'_> for ToStringInDisplay { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if is_display_impl(cx, item) { + self.in_display_impl = true; + } + } + + fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if is_display_impl(cx, item) { + self.in_display_impl = false; + } + } + + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if_chain! { + if let ExprKind::MethodCall(ref path, _, _, _) = expr.kind; + if path.ident.name == sym!(to_string); + if match_trait_method(cx, expr, &paths::TO_STRING); + if self.in_display_impl; + + then { + span_lint( + cx, + TO_STRING_IN_DISPLAY, + expr.span, + "Using to_string in fmt::Display implementation might lead to infinite recursion", + ); + } + } + } +} + +fn is_display_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool { + if_chain! { + if let ItemKind::Impl { of_trait: Some(trait_ref), .. } = &item.kind; + if let Some(did) = trait_ref.trait_def_id(); + then { + match_def_path(cx, did, &paths::DISPLAY_TRAIT) + } else { + false + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index ccc9e250952..46827084a60 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2166,6 +2166,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "to_digit_is_some", }, + Lint { + name: "to_string_in_display", + group: "correctness", + desc: "to_string method used while implementing Display trait", + deprecation: None, + module: "to_string_in_display", + }, Lint { name: "todo", group: "restriction", diff --git a/tests/ui/to_string_in_display.rs b/tests/ui/to_string_in_display.rs new file mode 100644 index 00000000000..3b46324704e --- /dev/null +++ b/tests/ui/to_string_in_display.rs @@ -0,0 +1,55 @@ +#![warn(clippy::to_string_in_display)] +#![allow(clippy::inherent_to_string_shadow_display)] + +use std::fmt; + +struct A; +impl A { + fn fmt(&self) { + self.to_string(); + } +} + +trait B { + fn fmt(&self) {} +} + +impl B for A { + fn fmt(&self) { + self.to_string(); + } +} + +impl fmt::Display for A { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_string()) + } +} + +fn fmt(a: A) { + a.to_string(); +} + +struct C; + +impl C { + fn to_string(&self) -> String { + String::from("I am C") + } +} + +impl fmt::Display for C { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_string()) + } +} + +fn main() { + let a = A; + a.to_string(); + a.fmt(); + fmt(a); + + let c = C; + c.to_string(); +} diff --git a/tests/ui/to_string_in_display.stderr b/tests/ui/to_string_in_display.stderr new file mode 100644 index 00000000000..cbc0a41036b --- /dev/null +++ b/tests/ui/to_string_in_display.stderr @@ -0,0 +1,10 @@ +error: Using to_string in fmt::Display implementation might lead to infinite recursion + --> $DIR/to_string_in_display.rs:25:25 + | +LL | write!(f, "{}", self.to_string()) + | ^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::to-string-in-display` implied by `-D warnings` + +error: aborting due to previous error + From f98ffa271d0112d04b482e1d61228d99bf006ccf Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Fri, 14 Aug 2020 22:54:12 +0900 Subject: [PATCH 437/526] Fix FP for `same_item_push` Don't emit a lint when `pushed_item` was declared as mutable variable. --- clippy_lints/src/loops.rs | 35 ++++++++++++++++++++++++++++++----- tests/ui/same_item_push.rs | 8 ++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8352a8a3d2c..f7db2563d2b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1141,11 +1141,36 @@ fn detect_same_item_push<'tcx>( if same_item_push_visitor.should_lint { if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push { // Make sure that the push does not involve possibly mutating values - if mutated_variables(pushed_item, cx).map_or(false, |mutvars| mutvars.is_empty()) { - if let PatKind::Wild = pat.kind { - let vec_str = snippet_with_macro_callsite(cx, vec.span, ""); - let item_str = snippet_with_macro_callsite(cx, pushed_item.span, ""); - + if let PatKind::Wild = pat.kind { + let vec_str = snippet_with_macro_callsite(cx, vec.span, ""); + let item_str = snippet_with_macro_callsite(cx, pushed_item.span, ""); + if let ExprKind::Path(ref qpath) = pushed_item.kind { + if let Res::Local(hir_id) = qpath_res(cx, qpath, pushed_item.hir_id) { + let node = cx.tcx.hir().get(hir_id); + if_chain! { + if let Node::Binding(pat) = node; + if let PatKind::Binding(bind_ann, ..) = pat.kind; + then { + match bind_ann { + BindingAnnotation::RefMut | BindingAnnotation::Mutable => {}, + _ => { + span_lint_and_help( + cx, + SAME_ITEM_PUSH, + vec.span, + "it looks like the same item is being pushed into this Vec", + None, + &format!( + "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})", + item_str, vec_str, item_str + ), + ) + } + } + } + } + } + } else if mutated_variables(pushed_item, cx).map_or(false, |mutvars| mutvars.is_empty()) { span_lint_and_help( cx, SAME_ITEM_PUSH, diff --git a/tests/ui/same_item_push.rs b/tests/ui/same_item_push.rs index ff1088f86f6..bfe27e02044 100644 --- a/tests/ui/same_item_push.rs +++ b/tests/ui/same_item_push.rs @@ -86,4 +86,12 @@ fn main() { for a in vec_a { vec12.push(2u8.pow(a.kind)); } + + // Fix #5902 + let mut vec13: Vec<u8> = Vec::new(); + let mut item = 0; + for _ in 0..10 { + vec13.push(item); + item += 10; + } } From 72d2c2eab42fe8c7247e4a45b01a6e7411898443 Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Sun, 9 Aug 2020 17:47:11 +0200 Subject: [PATCH 438/526] Lint `push_str` with a single-character string literal Fixes #5875 --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 ++ clippy_lints/src/single_char_push_str.rs | 62 ++++++++++++++++++++++++ clippy_lints/src/utils/paths.rs | 1 + src/lintlist/mod.rs | 7 +++ tests/ui/single_char_push_str.fixed | 10 ++++ tests/ui/single_char_push_str.rs | 10 ++++ tests/ui/single_char_push_str.stderr | 16 ++++++ 8 files changed, 112 insertions(+) create mode 100644 clippy_lints/src/single_char_push_str.rs create mode 100644 tests/ui/single_char_push_str.fixed create mode 100644 tests/ui/single_char_push_str.rs create mode 100644 tests/ui/single_char_push_str.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e9ed54c848..3b9cbbf0dcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1699,6 +1699,7 @@ Released 2018-09-13 [`should_implement_trait`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait [`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern +[`single_char_push_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_push_str [`single_component_path_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6ad525d7620..4f261ba932e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -287,6 +287,7 @@ mod repeat_once; mod returns; mod serde_api; mod shadow; +mod single_char_push_str; mod single_component_path_imports; mod slow_vector_initialization; mod stable_sort_primitive; @@ -775,6 +776,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &shadow::SHADOW_REUSE, &shadow::SHADOW_SAME, &shadow::SHADOW_UNRELATED, + &single_char_push_str::SINGLE_CHAR_PUSH_STR, &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, &stable_sort_primitive::STABLE_SORT_PRIMITIVE, @@ -932,6 +934,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || box escape::BoxedLocal{too_large_for_stack}); store.register_late_pass(|| box panic_unimplemented::PanicUnimplemented); store.register_late_pass(|| box strings::StringLitAsBytes); + store.register_late_pass(|| box single_char_push_str::SingleCharPushStrPass); store.register_late_pass(|| box derive::Derive); store.register_late_pass(|| box types::CharLitAsU8); store.register_late_pass(|| box vec::UselessVec); @@ -1416,6 +1419,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), LintId::of(&serde_api::SERDE_API_MISUSE), + LintId::of(&single_char_push_str::SINGLE_CHAR_PUSH_STR), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE), @@ -1556,6 +1560,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(®ex::TRIVIAL_REGEX), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), + LintId::of(&single_char_push_str::SINGLE_CHAR_PUSH_STR), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), diff --git a/clippy_lints/src/single_char_push_str.rs b/clippy_lints/src/single_char_push_str.rs new file mode 100644 index 00000000000..68bbef7261a --- /dev/null +++ b/clippy_lints/src/single_char_push_str.rs @@ -0,0 +1,62 @@ +use crate::utils::{match_def_path, paths, snippet_with_applicability, span_lint_and_sugg}; +use if_chain::if_chain; +use rustc_ast::ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Warns when using push_str with a single-character string literal, + /// and push with a char would work fine. + /// + /// **Why is this bad?** This is in all probability not the intended outcome. At + /// the least it hurts readability of the code. + /// + /// **Known problems:** None + /// + /// **Example:** + /// ``` + /// let mut string = String::new(); + /// string.push_str("R"); + /// ``` + /// Could be written as + /// ``` + /// let mut string = String::new(); + /// string.push('R'); + /// ``` + pub SINGLE_CHAR_PUSH_STR, + style, + "`push_str()` used with a single-character string literal as parameter" +} + +declare_lint_pass!(SingleCharPushStrPass => [SINGLE_CHAR_PUSH_STR]); + +impl<'tcx> LateLintPass<'tcx> for SingleCharPushStrPass { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if_chain! { + if let ExprKind::MethodCall(_, _, ref args, _) = expr.kind; + if let [base_string, extension_string] = args; + if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); + if match_def_path(cx, fn_def_id, &paths::PUSH_STR); + if let ExprKind::Lit(ref lit) = extension_string.kind; + if let LitKind::Str(symbol,_) = lit.node; + let extension_string_val = symbol.as_str().to_string(); + if extension_string_val.len() == 1; + then { + let mut applicability = Applicability::MachineApplicable; + let base_string_snippet = snippet_with_applicability(cx, base_string.span, "_", &mut applicability); + let sugg = format!("{}.push({:?})", base_string_snippet, extension_string_val.chars().next().unwrap()); + span_lint_and_sugg( + cx, + SINGLE_CHAR_PUSH_STR, + expr.span, + "calling `push_str()` using a single-character string literal", + "consider using `push` with a character literal", + sugg, + applicability + ); + } + } + } +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 923b319d777..ffab0395120 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -84,6 +84,7 @@ pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"]; pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; +pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index ccc9e250952..000ab8b8f36 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2012,6 +2012,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "methods", }, + Lint { + name: "single_char_push_str", + group: "style", + desc: "`push_str()` used with a single-character string literal as parameter", + deprecation: None, + module: "single_char_push_str", + }, Lint { name: "single_component_path_imports", group: "style", diff --git a/tests/ui/single_char_push_str.fixed b/tests/ui/single_char_push_str.fixed new file mode 100644 index 00000000000..49607c49218 --- /dev/null +++ b/tests/ui/single_char_push_str.fixed @@ -0,0 +1,10 @@ +// run-rustfix +#![warn(clippy::single_char_push_str)] + +fn main() { + let mut string = String::new(); + string.push('R'); + string.push('\''); + + string.push('u'); +} diff --git a/tests/ui/single_char_push_str.rs b/tests/ui/single_char_push_str.rs new file mode 100644 index 00000000000..bbeebd027b1 --- /dev/null +++ b/tests/ui/single_char_push_str.rs @@ -0,0 +1,10 @@ +// run-rustfix +#![warn(clippy::single_char_push_str)] + +fn main() { + let mut string = String::new(); + string.push_str("R"); + string.push_str("'"); + + string.push('u'); +} diff --git a/tests/ui/single_char_push_str.stderr b/tests/ui/single_char_push_str.stderr new file mode 100644 index 00000000000..453ec2d42f1 --- /dev/null +++ b/tests/ui/single_char_push_str.stderr @@ -0,0 +1,16 @@ +error: calling `push_str()` using a single-character string literal + --> $DIR/single_char_push_str.rs:6:5 + | +LL | string.push_str("R"); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('R')` + | + = note: `-D clippy::single-char-push-str` implied by `-D warnings` + +error: calling `push_str()` using a single-character string literal + --> $DIR/single_char_push_str.rs:7:5 + | +LL | string.push_str("'"); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/'')` + +error: aborting due to 2 previous errors + From ae56e988a2ae7b59c684cbbc5c326cb8097b3688 Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Fri, 14 Aug 2020 12:52:19 +0200 Subject: [PATCH 439/526] Merge lint with `single_char_pattern` --- clippy_lints/src/lib.rs | 8 +-- clippy_lints/src/methods/mod.rs | 89 ++++++++++++++++++++---- clippy_lints/src/single_char_push_str.rs | 62 ----------------- src/lintlist/mod.rs | 2 +- tests/ui/single_char_push_str.fixed | 5 ++ tests/ui/single_char_push_str.rs | 5 ++ tests/ui/single_char_push_str.stderr | 20 +++++- 7 files changed, 108 insertions(+), 83 deletions(-) delete mode 100644 clippy_lints/src/single_char_push_str.rs diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4f261ba932e..5e4a4a4f49c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -287,7 +287,6 @@ mod repeat_once; mod returns; mod serde_api; mod shadow; -mod single_char_push_str; mod single_component_path_imports; mod slow_vector_initialization; mod stable_sort_primitive; @@ -678,6 +677,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::SEARCH_IS_SOME, &methods::SHOULD_IMPLEMENT_TRAIT, &methods::SINGLE_CHAR_PATTERN, + &methods::SINGLE_CHAR_PUSH_STR, &methods::SKIP_WHILE_NEXT, &methods::STRING_EXTEND_CHARS, &methods::SUSPICIOUS_MAP, @@ -776,7 +776,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &shadow::SHADOW_REUSE, &shadow::SHADOW_SAME, &shadow::SHADOW_UNRELATED, - &single_char_push_str::SINGLE_CHAR_PUSH_STR, &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, &stable_sort_primitive::STABLE_SORT_PRIMITIVE, @@ -934,7 +933,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || box escape::BoxedLocal{too_large_for_stack}); store.register_late_pass(|| box panic_unimplemented::PanicUnimplemented); store.register_late_pass(|| box strings::StringLitAsBytes); - store.register_late_pass(|| box single_char_push_str::SingleCharPushStrPass); store.register_late_pass(|| box derive::Derive); store.register_late_pass(|| box types::CharLitAsU8); store.register_late_pass(|| box vec::UselessVec); @@ -1352,6 +1350,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::SEARCH_IS_SOME), LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT), LintId::of(&methods::SINGLE_CHAR_PATTERN), + LintId::of(&methods::SINGLE_CHAR_PUSH_STR), LintId::of(&methods::SKIP_WHILE_NEXT), LintId::of(&methods::STRING_EXTEND_CHARS), LintId::of(&methods::SUSPICIOUS_MAP), @@ -1419,7 +1418,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), LintId::of(&serde_api::SERDE_API_MISUSE), - LintId::of(&single_char_push_str::SINGLE_CHAR_PUSH_STR), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE), @@ -1536,6 +1534,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::OPTION_MAP_OR_NONE), LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION), LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT), + LintId::of(&methods::SINGLE_CHAR_PUSH_STR), LintId::of(&methods::STRING_EXTEND_CHARS), LintId::of(&methods::UNNECESSARY_FOLD), LintId::of(&methods::WRONG_SELF_CONVENTION), @@ -1560,7 +1559,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(®ex::TRIVIAL_REGEX), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), - LintId::of(&single_char_push_str::SINGLE_CHAR_PUSH_STR), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index b6266ef2ba1..2986a5a5944 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1306,6 +1306,29 @@ declare_clippy_lint! { "using `.iter().next()` on a sliced array, which can be shortened to just `.get()`" } +declare_clippy_lint! { + /// **What it does:** Warns when using push_str with a single-character string literal, + /// and push with a char would work fine. + /// + /// **Why is this bad?** it's less clear that we are pushing a single character + /// + /// **Known problems:** None + /// + /// **Example:** + /// ``` + /// let mut string = String::new(); + /// string.push_str("R"); + /// ``` + /// Could be written as + /// ``` + /// let mut string = String::new(); + /// string.push('R'); + /// ``` + pub SINGLE_CHAR_PUSH_STR, + style, + "`push_str()` used with a single-character string literal as parameter" +} + declare_lint_pass!(Methods => [ UNWRAP_USED, EXPECT_USED, @@ -1327,6 +1350,7 @@ declare_lint_pass!(Methods => [ INEFFICIENT_TO_STRING, NEW_RET_NO_SELF, SINGLE_CHAR_PATTERN, + SINGLE_CHAR_PUSH_STR, SEARCH_IS_SOME, TEMPORARY_CSTRING_AS_PTR, FILTER_NEXT, @@ -1441,6 +1465,12 @@ impl<'tcx> LateLintPass<'tcx> for Methods { inefficient_to_string::lint(cx, expr, &args[0], self_ty); } + if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { + if match_def_path(cx, fn_def_id, &paths::PUSH_STR) { + lint_single_char_push_string(cx, expr, args); + } + } + match self_ty.kind { ty::Ref(_, ty, _) if ty.kind == ty::Str => { for &(method, pos) in &PATTERN_METHODS { @@ -3124,15 +3154,18 @@ fn lint_chars_last_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryEx } } -/// lint for length-1 `str`s for methods in `PATTERN_METHODS` -fn lint_single_char_pattern<'tcx>(cx: &LateContext<'tcx>, _expr: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) { +fn get_hint_if_single_char_arg<'tcx>( + cx: &LateContext<'tcx>, + arg: &'tcx hir::Expr<'_>, + applicability: &mut Applicability, +) -> Option<String> { if_chain! { if let hir::ExprKind::Lit(lit) = &arg.kind; if let ast::LitKind::Str(r, style) = lit.node; - if r.as_str().len() == 1; + let string = r.as_str(); + if string.len() == 1; then { - let mut applicability = Applicability::MachineApplicable; - let snip = snippet_with_applicability(cx, arg.span, "..", &mut applicability); + let snip = snippet_with_applicability(cx, arg.span, &string, applicability); let ch = if let ast::StrStyle::Raw(nhash) = style { let nhash = nhash as usize; // for raw string: r##"a"## @@ -3142,19 +3175,47 @@ fn lint_single_char_pattern<'tcx>(cx: &LateContext<'tcx>, _expr: &'tcx hir::Expr &snip[1..(snip.len() - 1)] }; let hint = format!("'{}'", if ch == "'" { "\\'" } else { ch }); - span_lint_and_sugg( - cx, - SINGLE_CHAR_PATTERN, - arg.span, - "single-character string constant used as pattern", - "try using a `char` instead", - hint, - applicability, - ); + Some(hint) + } else { + None } } } +/// lint for length-1 `str`s for methods in `PATTERN_METHODS` +fn lint_single_char_pattern<'tcx>(cx: &LateContext<'tcx>, _expr: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) { + let mut applicability = Applicability::MachineApplicable; + if let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability) { + span_lint_and_sugg( + cx, + SINGLE_CHAR_PATTERN, + arg.span, + "single-character string constant used as pattern", + "try using a `char` instead", + hint, + applicability, + ); + } +} + +/// lint for length-1 `str`s as argument for `push_str` +fn lint_single_char_push_string<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, args: &'tcx [hir::Expr<'_>]) { + let mut applicability = Applicability::MachineApplicable; + if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) { + let base_string_snippet = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); + let sugg = format!("{}.push({})", base_string_snippet, extension_string); + span_lint_and_sugg( + cx, + SINGLE_CHAR_PUSH_STR, + expr.span, + "calling `push_str()` using a single-character string literal", + "consider using `push` with a character literal", + sugg, + applicability, + ); + } +} + /// Checks for the `USELESS_ASREF` lint. fn lint_asref(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, as_ref_args: &[hir::Expr<'_>]) { // when we get here, we've already checked that the call name is "as_ref" or "as_mut" diff --git a/clippy_lints/src/single_char_push_str.rs b/clippy_lints/src/single_char_push_str.rs deleted file mode 100644 index 68bbef7261a..00000000000 --- a/clippy_lints/src/single_char_push_str.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::utils::{match_def_path, paths, snippet_with_applicability, span_lint_and_sugg}; -use if_chain::if_chain; -use rustc_ast::ast::LitKind; -use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// **What it does:** Warns when using push_str with a single-character string literal, - /// and push with a char would work fine. - /// - /// **Why is this bad?** This is in all probability not the intended outcome. At - /// the least it hurts readability of the code. - /// - /// **Known problems:** None - /// - /// **Example:** - /// ``` - /// let mut string = String::new(); - /// string.push_str("R"); - /// ``` - /// Could be written as - /// ``` - /// let mut string = String::new(); - /// string.push('R'); - /// ``` - pub SINGLE_CHAR_PUSH_STR, - style, - "`push_str()` used with a single-character string literal as parameter" -} - -declare_lint_pass!(SingleCharPushStrPass => [SINGLE_CHAR_PUSH_STR]); - -impl<'tcx> LateLintPass<'tcx> for SingleCharPushStrPass { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::MethodCall(_, _, ref args, _) = expr.kind; - if let [base_string, extension_string] = args; - if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if match_def_path(cx, fn_def_id, &paths::PUSH_STR); - if let ExprKind::Lit(ref lit) = extension_string.kind; - if let LitKind::Str(symbol,_) = lit.node; - let extension_string_val = symbol.as_str().to_string(); - if extension_string_val.len() == 1; - then { - let mut applicability = Applicability::MachineApplicable; - let base_string_snippet = snippet_with_applicability(cx, base_string.span, "_", &mut applicability); - let sugg = format!("{}.push({:?})", base_string_snippet, extension_string_val.chars().next().unwrap()); - span_lint_and_sugg( - cx, - SINGLE_CHAR_PUSH_STR, - expr.span, - "calling `push_str()` using a single-character string literal", - "consider using `push` with a character literal", - sugg, - applicability - ); - } - } - } -} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 000ab8b8f36..4fd32776874 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2017,7 +2017,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ group: "style", desc: "`push_str()` used with a single-character string literal as parameter", deprecation: None, - module: "single_char_push_str", + module: "methods", }, Lint { name: "single_component_path_imports", diff --git a/tests/ui/single_char_push_str.fixed b/tests/ui/single_char_push_str.fixed index 49607c49218..0812c026a64 100644 --- a/tests/ui/single_char_push_str.fixed +++ b/tests/ui/single_char_push_str.fixed @@ -7,4 +7,9 @@ fn main() { string.push('\''); string.push('u'); + string.push_str("st"); + string.push_str(""); + string.push('\x52'); + string.push('\u{0052}'); + string.push('a'); } diff --git a/tests/ui/single_char_push_str.rs b/tests/ui/single_char_push_str.rs index bbeebd027b1..ab293bbe4ee 100644 --- a/tests/ui/single_char_push_str.rs +++ b/tests/ui/single_char_push_str.rs @@ -7,4 +7,9 @@ fn main() { string.push_str("'"); string.push('u'); + string.push_str("st"); + string.push_str(""); + string.push_str("\x52"); + string.push_str("\u{0052}"); + string.push_str(r##"a"##); } diff --git a/tests/ui/single_char_push_str.stderr b/tests/ui/single_char_push_str.stderr index 453ec2d42f1..0e9bdaa23e7 100644 --- a/tests/ui/single_char_push_str.stderr +++ b/tests/ui/single_char_push_str.stderr @@ -12,5 +12,23 @@ error: calling `push_str()` using a single-character string literal LL | string.push_str("'"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/'')` -error: aborting due to 2 previous errors +error: calling `push_str()` using a single-character string literal + --> $DIR/single_char_push_str.rs:12:5 + | +LL | string.push_str("/x52"); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/x52')` + +error: calling `push_str()` using a single-character string literal + --> $DIR/single_char_push_str.rs:13:5 + | +LL | string.push_str("/u{0052}"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/u{0052}')` + +error: calling `push_str()` using a single-character string literal + --> $DIR/single_char_push_str.rs:14:5 + | +LL | string.push_str(r##"a"##); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('a')` + +error: aborting due to 5 previous errors From b381ade1795f36149e36a646cdc83ee2fff032bf Mon Sep 17 00:00:00 2001 From: Christoph Walcher <christoph-wa@gmx.de> Date: Sat, 15 Aug 2020 01:40:47 +0200 Subject: [PATCH 440/526] elide lifetimes --- clippy_lints/src/methods/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2986a5a5944..614773a7e26 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1310,7 +1310,7 @@ declare_clippy_lint! { /// **What it does:** Warns when using push_str with a single-character string literal, /// and push with a char would work fine. /// - /// **Why is this bad?** it's less clear that we are pushing a single character + /// **Why is this bad?** It's less clear that we are pushing a single character /// /// **Known problems:** None /// @@ -3154,9 +3154,9 @@ fn lint_chars_last_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryEx } } -fn get_hint_if_single_char_arg<'tcx>( - cx: &LateContext<'tcx>, - arg: &'tcx hir::Expr<'_>, +fn get_hint_if_single_char_arg( + cx: &LateContext<'_>, + arg: &hir::Expr<'_>, applicability: &mut Applicability, ) -> Option<String> { if_chain! { @@ -3183,7 +3183,7 @@ fn get_hint_if_single_char_arg<'tcx>( } /// lint for length-1 `str`s for methods in `PATTERN_METHODS` -fn lint_single_char_pattern<'tcx>(cx: &LateContext<'tcx>, _expr: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) { +fn lint_single_char_pattern(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) { let mut applicability = Applicability::MachineApplicable; if let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability) { span_lint_and_sugg( @@ -3199,7 +3199,7 @@ fn lint_single_char_pattern<'tcx>(cx: &LateContext<'tcx>, _expr: &'tcx hir::Expr } /// lint for length-1 `str`s as argument for `push_str` -fn lint_single_char_push_string<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, args: &'tcx [hir::Expr<'_>]) { +fn lint_single_char_push_string(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let mut applicability = Applicability::MachineApplicable; if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) { let base_string_snippet = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); From 6d18fe730e88903fa881f7b753369623108a5d55 Mon Sep 17 00:00:00 2001 From: jrqc <jrqc01@hotmail.com> Date: Wed, 12 Aug 2020 15:43:44 +0300 Subject: [PATCH 441/526] Make needless_return a late lint pass --- clippy_lints/src/lib.rs | 8 +- clippy_lints/src/needless_return.rs | 166 ++++++++++++++++++++++++++++ clippy_lints/src/returns.rs | 141 +---------------------- src/lintlist/mod.rs | 2 +- 4 files changed, 175 insertions(+), 142 deletions(-) create mode 100644 clippy_lints/src/needless_return.rs diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6ad525d7620..d2f66cf9bd0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -256,6 +256,7 @@ mod needless_borrow; mod needless_borrowed_ref; mod needless_continue; mod needless_pass_by_value; +mod needless_return; mod needless_update; mod neg_cmp_op_on_partial_ord; mod neg_multiply; @@ -726,6 +727,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, &needless_continue::NEEDLESS_CONTINUE, &needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, + &needless_return::NEEDLESS_RETURN, &needless_update::NEEDLESS_UPDATE, &neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, &neg_multiply::NEG_MULTIPLY, @@ -769,7 +771,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ®ex::INVALID_REGEX, ®ex::TRIVIAL_REGEX, &repeat_once::REPEAT_ONCE, - &returns::NEEDLESS_RETURN, &returns::UNUSED_UNIT, &serde_api::SERDE_API_MISUSE, &shadow::SHADOW_REUSE, @@ -1027,6 +1028,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box redundant_closure_call::RedundantClosureCall); store.register_early_pass(|| box returns::Return); store.register_late_pass(|| box let_and_return::LetReturn); + store.register_late_pass(|| box needless_return::NeedlessReturn); store.register_early_pass(|| box collapsible_if::CollapsibleIf); store.register_early_pass(|| box items_after_statements::ItemsAfterStatements); store.register_early_pass(|| box precedence::Precedence); @@ -1381,6 +1383,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&needless_bool::BOOL_COMPARISON), LintId::of(&needless_bool::NEEDLESS_BOOL), LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), + LintId::of(&needless_return::NEEDLESS_RETURN), LintId::of(&needless_update::NEEDLESS_UPDATE), LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), LintId::of(&neg_multiply::NEG_MULTIPLY), @@ -1413,7 +1416,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(®ex::INVALID_REGEX), LintId::of(®ex::TRIVIAL_REGEX), LintId::of(&repeat_once::REPEAT_ONCE), - LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), @@ -1543,6 +1545,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), LintId::of(&misc_early::REDUNDANT_PATTERN), LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED), + LintId::of(&needless_return::NEEDLESS_RETURN), LintId::of(&neg_multiply::NEG_MULTIPLY), LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), @@ -1554,7 +1557,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES), LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), LintId::of(®ex::TRIVIAL_REGEX), - LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&returns::UNUSED_UNIT), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&strings::STRING_LIT_AS_BYTES), diff --git a/clippy_lints/src/needless_return.rs b/clippy_lints/src/needless_return.rs new file mode 100644 index 00000000000..a8876619ac1 --- /dev/null +++ b/clippy_lints/src/needless_return.rs @@ -0,0 +1,166 @@ +use rustc_lint::{LateLintPass, LateContext}; +use rustc_ast::ast::Attribute; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_errors::Applicability; +use rustc_hir::intravisit::FnKind; +use rustc_span::source_map::Span; +use rustc_middle::lint::in_external_macro; +use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, StmtKind}; + +use crate::utils::{snippet_opt, span_lint_and_sugg, span_lint_and_then}; + +declare_clippy_lint! { + /// **What it does:** Checks for return statements at the end of a block. + /// + /// **Why is this bad?** Removing the `return` and semicolon will make the code + /// more rusty. + /// + /// **Known problems:** If the computation returning the value borrows a local + /// variable, removing the `return` may run afoul of the borrow checker. + /// + /// **Example:** + /// ```rust + /// fn foo(x: usize) -> usize { + /// return x; + /// } + /// ``` + /// simplify to + /// ```rust + /// fn foo(x: usize) -> usize { + /// x + /// } + /// ``` + pub NEEDLESS_RETURN, + style, + "using a return statement like `return expr;` where an expression would suffice" +} + +#[derive(PartialEq, Eq, Copy, Clone)] +enum RetReplacement { + Empty, + Block, +} + +declare_lint_pass!(NeedlessReturn => [NEEDLESS_RETURN]); + +impl<'tcx> LateLintPass<'tcx> for NeedlessReturn { + fn check_fn(&mut self, cx: &LateContext<'tcx>, kind: FnKind<'tcx>, _: &'tcx FnDecl<'tcx>, body: &'tcx Body<'tcx>, _: Span, _: HirId) { + match kind { + FnKind::Closure(_) => { + check_final_expr(cx, &body.value, Some(body.value.span), RetReplacement::Empty) + } + FnKind::ItemFn(..) | FnKind::Method(..) => { + if let ExprKind::Block(ref block, _) = body.value.kind { + check_block_return(cx, block) + } + } + } + } +} + +fn attr_is_cfg(attr: &Attribute) -> bool { + attr.meta_item_list().is_some() && attr.has_name(sym!(cfg)) +} + +fn check_block_return(cx: &LateContext<'_>, block: &Block<'_>) { + if let Some(expr) = block.expr { + check_final_expr(cx, expr, Some(expr.span), RetReplacement::Empty); + } else if let Some(stmt) = block.stmts.iter().last() { + match stmt.kind { + StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { + check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty); + } + _ => (), + } + } +} + + +fn check_final_expr( + cx: &LateContext<'_>, + expr: &Expr<'_>, + span: Option<Span>, + replacement: RetReplacement, +) { + match expr.kind { + // simple return is always "bad" + ExprKind::Ret(ref inner) => { + + // allow `#[cfg(a)] return a; #[cfg(b)] return b;` + if !expr.attrs.iter().any(attr_is_cfg) { + emit_return_lint( + cx, + span.expect("`else return` is not possible"), + inner.as_ref().map(|i| i.span), + replacement, + ); + } + } + // a whole block? check it! + ExprKind::Block(ref block, _) => { + check_block_return(cx, block); + } + // a match expr, check all arms + // an if/if let expr, check both exprs + // note, if without else is going to be a type checking error anyways + // (except for unit type functions) so we don't match it + + ExprKind::Match(_, ref arms, source) => { + match source { + MatchSource::Normal => { + for arm in arms.iter() { + check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block); + } + } + MatchSource::IfDesugar { contains_else_clause: true } | MatchSource::IfLetDesugar { contains_else_clause: true } => { + if let ExprKind::Block(ref ifblock, _) = arms[0].body.kind { + check_block_return(cx, ifblock); + } + check_final_expr(cx, arms[1].body, None, RetReplacement::Empty); + } + _ => () + } + } + _ => (), + } +} + +fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Span>, replacement: RetReplacement) { + match inner_span { + Some(inner_span) => { + if in_external_macro(cx.tcx.sess, inner_span) || inner_span.from_expansion() { + return; + } + + span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| { + if let Some(snippet) = snippet_opt(cx, inner_span) { + diag.span_suggestion(ret_span, "remove `return`", snippet, Applicability::MachineApplicable); + } + }) + } + None => match replacement { + RetReplacement::Empty => { + span_lint_and_sugg( + cx, + NEEDLESS_RETURN, + ret_span, + "unneeded `return` statement", + "remove `return`", + String::new(), + Applicability::MachineApplicable, + ); + } + RetReplacement::Block => { + span_lint_and_sugg( + cx, + NEEDLESS_RETURN, + ret_span, + "unneeded `return` statement", + "replace `return` with an empty block", + "{}".to_string(), + Applicability::MachineApplicable, + ); + } + }, + } +} diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 8ed20995a70..2bd0cccd39d 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -3,38 +3,11 @@ use rustc_ast::ast; use rustc_ast::visit::FnKind; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::BytePos; -use crate::utils::{snippet_opt, span_lint_and_sugg, span_lint_and_then}; - -declare_clippy_lint! { - /// **What it does:** Checks for return statements at the end of a block. - /// - /// **Why is this bad?** Removing the `return` and semicolon will make the code - /// more rusty. - /// - /// **Known problems:** If the computation returning the value borrows a local - /// variable, removing the `return` may run afoul of the borrow checker. - /// - /// **Example:** - /// ```rust - /// fn foo(x: usize) -> usize { - /// return x; - /// } - /// ``` - /// simplify to - /// ```rust - /// fn foo(x: usize) -> usize { - /// x - /// } - /// ``` - pub NEEDLESS_RETURN, - style, - "using a return statement like `return expr;` where an expression would suffice" -} +use crate::utils::{span_lint_and_sugg}; declare_clippy_lint! { /// **What it does:** Checks for unit (`()`) expressions that can be removed. @@ -57,117 +30,12 @@ declare_clippy_lint! { "needless unit expression" } -#[derive(PartialEq, Eq, Copy, Clone)] -enum RetReplacement { - Empty, - Block, -} -declare_lint_pass!(Return => [NEEDLESS_RETURN, UNUSED_UNIT]); - -impl Return { - // Check the final stmt or expr in a block for unnecessary return. - fn check_block_return(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { - if let Some(stmt) = block.stmts.last() { - match stmt.kind { - ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { - self.check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty); - }, - _ => (), - } - } - } - - // Check the final expression in a block if it's a return. - fn check_final_expr( - &mut self, - cx: &EarlyContext<'_>, - expr: &ast::Expr, - span: Option<Span>, - replacement: RetReplacement, - ) { - match expr.kind { - // simple return is always "bad" - ast::ExprKind::Ret(ref inner) => { - // allow `#[cfg(a)] return a; #[cfg(b)] return b;` - if !expr.attrs.iter().any(attr_is_cfg) { - Self::emit_return_lint( - cx, - span.expect("`else return` is not possible"), - inner.as_ref().map(|i| i.span), - replacement, - ); - } - }, - // a whole block? check it! - ast::ExprKind::Block(ref block, _) => { - self.check_block_return(cx, block); - }, - // an if/if let expr, check both exprs - // note, if without else is going to be a type checking error anyways - // (except for unit type functions) so we don't match it - ast::ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => { - self.check_block_return(cx, ifblock); - self.check_final_expr(cx, elsexpr, None, RetReplacement::Empty); - }, - // a match expr, check all arms - ast::ExprKind::Match(_, ref arms) => { - for arm in arms { - self.check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block); - } - }, - _ => (), - } - } - - fn emit_return_lint(cx: &EarlyContext<'_>, ret_span: Span, inner_span: Option<Span>, replacement: RetReplacement) { - match inner_span { - Some(inner_span) => { - if in_external_macro(cx.sess(), inner_span) || inner_span.from_expansion() { - return; - } - - span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| { - if let Some(snippet) = snippet_opt(cx, inner_span) { - diag.span_suggestion(ret_span, "remove `return`", snippet, Applicability::MachineApplicable); - } - }) - }, - None => match replacement { - RetReplacement::Empty => { - span_lint_and_sugg( - cx, - NEEDLESS_RETURN, - ret_span, - "unneeded `return` statement", - "remove `return`", - String::new(), - Applicability::MachineApplicable, - ); - }, - RetReplacement::Block => { - span_lint_and_sugg( - cx, - NEEDLESS_RETURN, - ret_span, - "unneeded `return` statement", - "replace `return` with an empty block", - "{}".to_string(), - Applicability::MachineApplicable, - ); - }, - }, - } - } -} +declare_lint_pass!(Return => [UNUSED_UNIT]); impl EarlyLintPass for Return { fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, span: Span, _: ast::NodeId) { - match kind { - FnKind::Fn(.., Some(block)) => self.check_block_return(cx, block), - FnKind::Closure(_, body) => self.check_final_expr(cx, body, Some(body.span), RetReplacement::Empty), - FnKind::Fn(.., None) => {}, - } + if_chain! { if let ast::FnRetTy::Ty(ref ty) = kind.decl().output; if let ast::TyKind::Tup(ref vals) = ty.kind; @@ -234,9 +102,6 @@ impl EarlyLintPass for Return { } } -fn attr_is_cfg(attr: &ast::Attribute) -> bool { - attr.meta_item_list().is_some() && attr.has_name(sym!(cfg)) -} // get the def site #[must_use] diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index ccc9e250952..7464f1cc6de 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1534,7 +1534,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ group: "style", desc: "using a return statement like `return expr;` where an expression would suffice", deprecation: None, - module: "returns", + module: "needless_return", }, Lint { name: "needless_update", From 85f4ef0fbd92453cf480af4e3f9eed877071ea2e Mon Sep 17 00:00:00 2001 From: jrqc <jrqc01@hotmail.com> Date: Wed, 12 Aug 2020 17:14:12 +0300 Subject: [PATCH 442/526] Visitor added --- clippy_lints/src/needless_return.rs | 45 +++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/needless_return.rs b/clippy_lints/src/needless_return.rs index a8876619ac1..861a7ec558c 100644 --- a/clippy_lints/src/needless_return.rs +++ b/clippy_lints/src/needless_return.rs @@ -2,12 +2,14 @@ use rustc_lint::{LateLintPass, LateContext}; use rustc_ast::ast::Attribute; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; -use rustc_hir::intravisit::FnKind; +use rustc_hir::intravisit::{FnKind, walk_expr, NestedVisitorMap, Visitor}; use rustc_span::source_map::Span; use rustc_middle::lint::in_external_macro; +use rustc_middle::hir::map::Map; +use rustc_middle::ty::subst::GenericArgKind; use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, StmtKind}; -use crate::utils::{snippet_opt, span_lint_and_sugg, span_lint_and_then}; +use crate::utils::{fn_def_id, snippet_opt, span_lint_and_sugg, span_lint_and_then}; declare_clippy_lint! { /// **What it does:** Checks for return statements at the end of a block. @@ -164,3 +166,42 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Spa }, } } + +fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + let mut visitor = BorrowVisitor { cx, borrows: false }; + walk_expr(&mut visitor, expr); + visitor.borrows +} + +struct BorrowVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + borrows: bool, +} + +impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + if self.borrows { + return; + } + + if let Some(def_id) = fn_def_id(self.cx, expr) { + self.borrows = self + .cx + .tcx + .fn_sig(def_id) + .output() + .skip_binder() + .walk() + .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))); + } + + walk_expr(self, expr); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } +} + From 65d10c7abf4752923f040264c79433da8fc234ea Mon Sep 17 00:00:00 2001 From: jrqc <jrqc01@hotmail.com> Date: Thu, 13 Aug 2020 15:14:08 +0300 Subject: [PATCH 443/526] Borrow checker added --- clippy_lints/src/needless_return.rs | 101 ++++++++++++++++------------ clippy_lints/src/returns.rs | 5 +- tests/ui/needless_return.fixed | 10 +++ tests/ui/needless_return.rs | 10 +++ 4 files changed, 80 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/needless_return.rs b/clippy_lints/src/needless_return.rs index 861a7ec558c..ba280cd5a61 100644 --- a/clippy_lints/src/needless_return.rs +++ b/clippy_lints/src/needless_return.rs @@ -1,13 +1,13 @@ -use rustc_lint::{LateLintPass, LateContext}; use rustc_ast::ast::Attribute; -use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; -use rustc_hir::intravisit::{FnKind, walk_expr, NestedVisitorMap, Visitor}; -use rustc_span::source_map::Span; -use rustc_middle::lint::in_external_macro; -use rustc_middle::hir::map::Map; -use rustc_middle::ty::subst::GenericArgKind; +use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, StmtKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::subst::GenericArgKind; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Span; use crate::utils::{fn_def_id, snippet_opt, span_lint_and_sugg, span_lint_and_then}; @@ -46,16 +46,39 @@ enum RetReplacement { declare_lint_pass!(NeedlessReturn => [NEEDLESS_RETURN]); impl<'tcx> LateLintPass<'tcx> for NeedlessReturn { - fn check_fn(&mut self, cx: &LateContext<'tcx>, kind: FnKind<'tcx>, _: &'tcx FnDecl<'tcx>, body: &'tcx Body<'tcx>, _: Span, _: HirId) { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + kind: FnKind<'tcx>, + _: &'tcx FnDecl<'tcx>, + body: &'tcx Body<'tcx>, + _: Span, + _: HirId, + ) { match kind { FnKind::Closure(_) => { - check_final_expr(cx, &body.value, Some(body.value.span), RetReplacement::Empty) - } + if !last_statement_borrows(cx, &body.value) { + check_final_expr(cx, &body.value, Some(body.value.span), RetReplacement::Empty) + } + }, FnKind::ItemFn(..) | FnKind::Method(..) => { if let ExprKind::Block(ref block, _) = body.value.kind { - check_block_return(cx, block) + if let Some(expr) = block.expr { + if !last_statement_borrows(cx, expr) { + check_final_expr(cx, expr, Some(expr.span), RetReplacement::Empty); + } + } else if let Some(stmt) = block.stmts.iter().last() { + match stmt.kind { + StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { + if !last_statement_borrows(cx, expr) { + check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty); + } + }, + _ => (), + } + } } - } + }, } } } @@ -71,23 +94,16 @@ fn check_block_return(cx: &LateContext<'_>, block: &Block<'_>) { match stmt.kind { StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty); - } + }, _ => (), } } } - -fn check_final_expr( - cx: &LateContext<'_>, - expr: &Expr<'_>, - span: Option<Span>, - replacement: RetReplacement, -) { +fn check_final_expr(cx: &LateContext<'_>, expr: &Expr<'_>, span: Option<Span>, replacement: RetReplacement) { match expr.kind { // simple return is always "bad" ExprKind::Ret(ref inner) => { - // allow `#[cfg(a)] return a; #[cfg(b)] return b;` if !expr.attrs.iter().any(attr_is_cfg) { emit_return_lint( @@ -97,32 +113,34 @@ fn check_final_expr( replacement, ); } - } + }, // a whole block? check it! ExprKind::Block(ref block, _) => { check_block_return(cx, block); - } + }, // a match expr, check all arms // an if/if let expr, check both exprs // note, if without else is going to be a type checking error anyways // (except for unit type functions) so we don't match it - - ExprKind::Match(_, ref arms, source) => { - match source { - MatchSource::Normal => { - for arm in arms.iter() { - check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block); - } + ExprKind::Match(_, ref arms, source) => match source { + MatchSource::Normal => { + for arm in arms.iter() { + check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block); } - MatchSource::IfDesugar { contains_else_clause: true } | MatchSource::IfLetDesugar { contains_else_clause: true } => { - if let ExprKind::Block(ref ifblock, _) = arms[0].body.kind { - check_block_return(cx, ifblock); - } - check_final_expr(cx, arms[1].body, None, RetReplacement::Empty); - } - _ => () + }, + MatchSource::IfDesugar { + contains_else_clause: true, } - } + | MatchSource::IfLetDesugar { + contains_else_clause: true, + } => { + if let ExprKind::Block(ref ifblock, _) = arms[0].body.kind { + check_block_return(cx, ifblock); + } + check_final_expr(cx, arms[1].body, None, RetReplacement::Empty); + }, + _ => (), + }, _ => (), } } @@ -139,7 +157,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Spa diag.span_suggestion(ret_span, "remove `return`", snippet, Applicability::MachineApplicable); } }) - } + }, None => match replacement { RetReplacement::Empty => { span_lint_and_sugg( @@ -151,7 +169,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Spa String::new(), Applicability::MachineApplicable, ); - } + }, RetReplacement::Block => { span_lint_and_sugg( cx, @@ -162,7 +180,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Spa "{}".to_string(), Applicability::MachineApplicable, ); - } + }, }, } } @@ -204,4 +222,3 @@ impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> { NestedVisitorMap::None } } - diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 2bd0cccd39d..593e2f6c74b 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -7,7 +7,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::BytePos; -use crate::utils::{span_lint_and_sugg}; +use crate::utils::span_lint_and_sugg; declare_clippy_lint! { /// **What it does:** Checks for unit (`()`) expressions that can be removed. @@ -30,12 +30,10 @@ declare_clippy_lint! { "needless unit expression" } - declare_lint_pass!(Return => [UNUSED_UNIT]); impl EarlyLintPass for Return { fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, span: Span, _: ast::NodeId) { - if_chain! { if let ast::FnRetTy::Ty(ref ty) = kind.decl().output; if let ast::TyKind::Tup(ref vals) = ty.kind; @@ -102,7 +100,6 @@ impl EarlyLintPass for Return { } } - // get the def site #[must_use] fn get_def(span: Span) -> Option<Span> { diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index ad20e238107..6b5cf2626df 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -69,6 +69,16 @@ fn test_void_match(x: u32) { } } +mod no_lint_if_stmt_borrows { + mod issue_5858 { + fn read_line() -> String { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + return stdin.lock().lines().next().unwrap().unwrap(); + } + } +} + fn main() { let _ = test_end_of_fn(); let _ = test_no_semicolon(); diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index af0cdfb207f..1a693c9aa53 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -69,6 +69,16 @@ fn test_void_match(x: u32) { } } +mod no_lint_if_stmt_borrows { + mod issue_5858 { + fn read_line() -> String { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + return stdin.lock().lines().next().unwrap().unwrap(); + } + } +} + fn main() { let _ = test_end_of_fn(); let _ = test_no_semicolon(); From cd6ca72e0e4040a5c3a6623c2e8533db91db6042 Mon Sep 17 00:00:00 2001 From: jrqc <jrqc01@hotmail.com> Date: Thu, 13 Aug 2020 15:21:09 +0300 Subject: [PATCH 444/526] Known problems changed --- clippy_lints/src/needless_return.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/needless_return.rs b/clippy_lints/src/needless_return.rs index ba280cd5a61..eb0bf12c0ab 100644 --- a/clippy_lints/src/needless_return.rs +++ b/clippy_lints/src/needless_return.rs @@ -17,8 +17,7 @@ declare_clippy_lint! { /// **Why is this bad?** Removing the `return` and semicolon will make the code /// more rusty. /// - /// **Known problems:** If the computation returning the value borrows a local - /// variable, removing the `return` may run afoul of the borrow checker. + /// **Known problems:** None. /// /// **Example:** /// ```rust From a7d5c2f967dd1f075ba5f8c4ca05c4b2ca2d22b4 Mon Sep 17 00:00:00 2001 From: jrqc <jrqc01@hotmail.com> Date: Thu, 13 Aug 2020 19:24:34 +0300 Subject: [PATCH 445/526] Modifications according to the code review --- clippy_lints/src/let_and_return.rs | 124 ---------- clippy_lints/src/lib.rs | 26 +- clippy_lints/src/needless_return.rs | 223 ------------------ clippy_lints/src/returns.rs | 353 ++++++++++++++++++++-------- clippy_lints/src/unused_unit.rs | 145 ++++++++++++ tests/ui/needless_return.fixed | 11 + tests/ui/needless_return.rs | 11 + 7 files changed, 428 insertions(+), 465 deletions(-) delete mode 100644 clippy_lints/src/let_and_return.rs delete mode 100644 clippy_lints/src/needless_return.rs create mode 100644 clippy_lints/src/unused_unit.rs diff --git a/clippy_lints/src/let_and_return.rs b/clippy_lints/src/let_and_return.rs deleted file mode 100644 index fa560ffb980..00000000000 --- a/clippy_lints/src/let_and_return.rs +++ /dev/null @@ -1,124 +0,0 @@ -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::{Block, Expr, ExprKind, PatKind, StmtKind}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::hir::map::Map; -use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::subst::GenericArgKind; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -use crate::utils::{fn_def_id, in_macro, match_qpath, snippet_opt, span_lint_and_then}; - -declare_clippy_lint! { - /// **What it does:** Checks for `let`-bindings, which are subsequently - /// returned. - /// - /// **Why is this bad?** It is just extraneous code. Remove it to make your code - /// more rusty. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// fn foo() -> String { - /// let x = String::new(); - /// x - /// } - /// ``` - /// instead, use - /// ``` - /// fn foo() -> String { - /// String::new() - /// } - /// ``` - pub LET_AND_RETURN, - style, - "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block" -} - -declare_lint_pass!(LetReturn => [LET_AND_RETURN]); - -impl<'tcx> LateLintPass<'tcx> for LetReturn { - fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { - // we need both a let-binding stmt and an expr - if_chain! { - if let Some(retexpr) = block.expr; - if let Some(stmt) = block.stmts.iter().last(); - if let StmtKind::Local(local) = &stmt.kind; - if local.ty.is_none(); - if local.attrs.is_empty(); - if let Some(initexpr) = &local.init; - if let PatKind::Binding(.., ident, _) = local.pat.kind; - if let ExprKind::Path(qpath) = &retexpr.kind; - if match_qpath(qpath, &[&*ident.name.as_str()]); - if !last_statement_borrows(cx, initexpr); - if !in_external_macro(cx.sess(), initexpr.span); - if !in_external_macro(cx.sess(), retexpr.span); - if !in_external_macro(cx.sess(), local.span); - if !in_macro(local.span); - then { - span_lint_and_then( - cx, - LET_AND_RETURN, - retexpr.span, - "returning the result of a `let` binding from a block", - |err| { - err.span_label(local.span, "unnecessary `let` binding"); - - if let Some(snippet) = snippet_opt(cx, initexpr.span) { - err.multipart_suggestion( - "return the expression directly", - vec![ - (local.span, String::new()), - (retexpr.span, snippet), - ], - Applicability::MachineApplicable, - ); - } else { - err.span_help(initexpr.span, "this expression can be directly returned"); - } - }, - ); - } - } - } -} - -fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { - let mut visitor = BorrowVisitor { cx, borrows: false }; - walk_expr(&mut visitor, expr); - visitor.borrows -} - -struct BorrowVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - borrows: bool, -} - -impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> { - type Map = Map<'tcx>; - - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if self.borrows { - return; - } - - if let Some(def_id) = fn_def_id(self.cx, expr) { - self.borrows = self - .cx - .tcx - .fn_sig(def_id) - .output() - .skip_binder() - .walk() - .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))); - } - - walk_expr(self, expr); - } - - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::None - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d2f66cf9bd0..63de0f8a0c2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -218,7 +218,6 @@ mod large_const_arrays; mod large_enum_variant; mod large_stack_arrays; mod len_zero; -mod let_and_return; mod let_if_seq; mod let_underscore; mod lifetimes; @@ -256,7 +255,6 @@ mod needless_borrow; mod needless_borrowed_ref; mod needless_continue; mod needless_pass_by_value; -mod needless_return; mod needless_update; mod neg_cmp_op_on_partial_ord; mod neg_multiply; @@ -311,6 +309,7 @@ mod unnested_or_patterns; mod unsafe_removed_from_name; mod unused_io_amount; mod unused_self; +mod unused_unit; mod unwrap; mod use_self; mod useless_conversion; @@ -587,7 +586,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &large_stack_arrays::LARGE_STACK_ARRAYS, &len_zero::LEN_WITHOUT_IS_EMPTY, &len_zero::LEN_ZERO, - &let_and_return::LET_AND_RETURN, + &returns::LET_AND_RETURN, &let_if_seq::USELESS_LET_IF_SEQ, &let_underscore::LET_UNDERSCORE_LOCK, &let_underscore::LET_UNDERSCORE_MUST_USE, @@ -727,7 +726,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, &needless_continue::NEEDLESS_CONTINUE, &needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, - &needless_return::NEEDLESS_RETURN, + &returns::NEEDLESS_RETURN, &needless_update::NEEDLESS_UPDATE, &neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, &neg_multiply::NEG_MULTIPLY, @@ -771,7 +770,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ®ex::INVALID_REGEX, ®ex::TRIVIAL_REGEX, &repeat_once::REPEAT_ONCE, - &returns::UNUSED_UNIT, + &unused_unit::UNUSED_UNIT, &serde_api::SERDE_API_MISUSE, &shadow::SHADOW_REUSE, &shadow::SHADOW_SAME, @@ -1026,9 +1025,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box misc_early::MiscEarlyLints); store.register_early_pass(|| box redundant_closure_call::RedundantClosureCall); store.register_late_pass(|| box redundant_closure_call::RedundantClosureCall); - store.register_early_pass(|| box returns::Return); - store.register_late_pass(|| box let_and_return::LetReturn); - store.register_late_pass(|| box needless_return::NeedlessReturn); + store.register_early_pass(|| box unused_unit::UnusedUnit); + store.register_late_pass(|| box returns::Return); store.register_early_pass(|| box collapsible_if::CollapsibleIf); store.register_early_pass(|| box items_after_statements::ItemsAfterStatements); store.register_early_pass(|| box precedence::Precedence); @@ -1286,7 +1284,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), - LintId::of(&let_and_return::LET_AND_RETURN), + LintId::of(&returns::LET_AND_RETURN), LintId::of(&let_underscore::LET_UNDERSCORE_LOCK), LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES), LintId::of(&lifetimes::NEEDLESS_LIFETIMES), @@ -1383,7 +1381,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&needless_bool::BOOL_COMPARISON), LintId::of(&needless_bool::NEEDLESS_BOOL), LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), - LintId::of(&needless_return::NEEDLESS_RETURN), + LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&needless_update::NEEDLESS_UPDATE), LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), LintId::of(&neg_multiply::NEG_MULTIPLY), @@ -1416,7 +1414,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(®ex::INVALID_REGEX), LintId::of(®ex::TRIVIAL_REGEX), LintId::of(&repeat_once::REPEAT_ONCE), - LintId::of(&returns::UNUSED_UNIT), + LintId::of(&unused_unit::UNUSED_UNIT), LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), @@ -1502,7 +1500,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&inherent_to_string::INHERENT_TO_STRING), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), - LintId::of(&let_and_return::LET_AND_RETURN), + LintId::of(&returns::LET_AND_RETURN), LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING), LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::FOR_KV_MAP), @@ -1545,7 +1543,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), LintId::of(&misc_early::REDUNDANT_PATTERN), LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED), - LintId::of(&needless_return::NEEDLESS_RETURN), + LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&neg_multiply::NEG_MULTIPLY), LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), @@ -1557,7 +1555,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES), LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), LintId::of(®ex::TRIVIAL_REGEX), - LintId::of(&returns::UNUSED_UNIT), + LintId::of(&unused_unit::UNUSED_UNIT), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), diff --git a/clippy_lints/src/needless_return.rs b/clippy_lints/src/needless_return.rs deleted file mode 100644 index eb0bf12c0ab..00000000000 --- a/clippy_lints/src/needless_return.rs +++ /dev/null @@ -1,223 +0,0 @@ -use rustc_ast::ast::Attribute; -use rustc_errors::Applicability; -use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; -use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, StmtKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::hir::map::Map; -use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::subst::GenericArgKind; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; - -use crate::utils::{fn_def_id, snippet_opt, span_lint_and_sugg, span_lint_and_then}; - -declare_clippy_lint! { - /// **What it does:** Checks for return statements at the end of a block. - /// - /// **Why is this bad?** Removing the `return` and semicolon will make the code - /// more rusty. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// fn foo(x: usize) -> usize { - /// return x; - /// } - /// ``` - /// simplify to - /// ```rust - /// fn foo(x: usize) -> usize { - /// x - /// } - /// ``` - pub NEEDLESS_RETURN, - style, - "using a return statement like `return expr;` where an expression would suffice" -} - -#[derive(PartialEq, Eq, Copy, Clone)] -enum RetReplacement { - Empty, - Block, -} - -declare_lint_pass!(NeedlessReturn => [NEEDLESS_RETURN]); - -impl<'tcx> LateLintPass<'tcx> for NeedlessReturn { - fn check_fn( - &mut self, - cx: &LateContext<'tcx>, - kind: FnKind<'tcx>, - _: &'tcx FnDecl<'tcx>, - body: &'tcx Body<'tcx>, - _: Span, - _: HirId, - ) { - match kind { - FnKind::Closure(_) => { - if !last_statement_borrows(cx, &body.value) { - check_final_expr(cx, &body.value, Some(body.value.span), RetReplacement::Empty) - } - }, - FnKind::ItemFn(..) | FnKind::Method(..) => { - if let ExprKind::Block(ref block, _) = body.value.kind { - if let Some(expr) = block.expr { - if !last_statement_borrows(cx, expr) { - check_final_expr(cx, expr, Some(expr.span), RetReplacement::Empty); - } - } else if let Some(stmt) = block.stmts.iter().last() { - match stmt.kind { - StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { - if !last_statement_borrows(cx, expr) { - check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty); - } - }, - _ => (), - } - } - } - }, - } - } -} - -fn attr_is_cfg(attr: &Attribute) -> bool { - attr.meta_item_list().is_some() && attr.has_name(sym!(cfg)) -} - -fn check_block_return(cx: &LateContext<'_>, block: &Block<'_>) { - if let Some(expr) = block.expr { - check_final_expr(cx, expr, Some(expr.span), RetReplacement::Empty); - } else if let Some(stmt) = block.stmts.iter().last() { - match stmt.kind { - StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { - check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty); - }, - _ => (), - } - } -} - -fn check_final_expr(cx: &LateContext<'_>, expr: &Expr<'_>, span: Option<Span>, replacement: RetReplacement) { - match expr.kind { - // simple return is always "bad" - ExprKind::Ret(ref inner) => { - // allow `#[cfg(a)] return a; #[cfg(b)] return b;` - if !expr.attrs.iter().any(attr_is_cfg) { - emit_return_lint( - cx, - span.expect("`else return` is not possible"), - inner.as_ref().map(|i| i.span), - replacement, - ); - } - }, - // a whole block? check it! - ExprKind::Block(ref block, _) => { - check_block_return(cx, block); - }, - // a match expr, check all arms - // an if/if let expr, check both exprs - // note, if without else is going to be a type checking error anyways - // (except for unit type functions) so we don't match it - ExprKind::Match(_, ref arms, source) => match source { - MatchSource::Normal => { - for arm in arms.iter() { - check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block); - } - }, - MatchSource::IfDesugar { - contains_else_clause: true, - } - | MatchSource::IfLetDesugar { - contains_else_clause: true, - } => { - if let ExprKind::Block(ref ifblock, _) = arms[0].body.kind { - check_block_return(cx, ifblock); - } - check_final_expr(cx, arms[1].body, None, RetReplacement::Empty); - }, - _ => (), - }, - _ => (), - } -} - -fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Span>, replacement: RetReplacement) { - match inner_span { - Some(inner_span) => { - if in_external_macro(cx.tcx.sess, inner_span) || inner_span.from_expansion() { - return; - } - - span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| { - if let Some(snippet) = snippet_opt(cx, inner_span) { - diag.span_suggestion(ret_span, "remove `return`", snippet, Applicability::MachineApplicable); - } - }) - }, - None => match replacement { - RetReplacement::Empty => { - span_lint_and_sugg( - cx, - NEEDLESS_RETURN, - ret_span, - "unneeded `return` statement", - "remove `return`", - String::new(), - Applicability::MachineApplicable, - ); - }, - RetReplacement::Block => { - span_lint_and_sugg( - cx, - NEEDLESS_RETURN, - ret_span, - "unneeded `return` statement", - "replace `return` with an empty block", - "{}".to_string(), - Applicability::MachineApplicable, - ); - }, - }, - } -} - -fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { - let mut visitor = BorrowVisitor { cx, borrows: false }; - walk_expr(&mut visitor, expr); - visitor.borrows -} - -struct BorrowVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - borrows: bool, -} - -impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> { - type Map = Map<'tcx>; - - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if self.borrows { - return; - } - - if let Some(def_id) = fn_def_id(self.cx, expr) { - self.borrows = self - .cx - .tcx - .fn_sig(def_id) - .output() - .skip_binder() - .walk() - .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))); - } - - walk_expr(self, expr); - } - - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::None - } -} diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 593e2f6c74b..4d91f9be999 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,145 +1,290 @@ use if_chain::if_chain; -use rustc_ast::ast; -use rustc_ast::visit::FnKind; +use rustc_ast::ast::Attribute; use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; +use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, PatKind, StmtKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::subst::GenericArgKind; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::BytePos; -use crate::utils::span_lint_and_sugg; +use crate::utils::{fn_def_id, in_macro, match_qpath, snippet_opt, span_lint_and_sugg, span_lint_and_then}; declare_clippy_lint! { - /// **What it does:** Checks for unit (`()`) expressions that can be removed. + /// **What it does:** Checks for `let`-bindings, which are subsequently + /// returned. /// - /// **Why is this bad?** Such expressions add no value, but can make the code - /// less readable. Depending on formatting they can make a `break` or `return` - /// statement look like a function call. + /// **Why is this bad?** It is just extraneous code. Remove it to make your code + /// more rusty. /// - /// **Known problems:** The lint currently misses unit return types in types, - /// e.g., the `F` in `fn generic_unit<F: Fn() -> ()>(f: F) { .. }`. + /// **Known problems:** None. /// /// **Example:** /// ```rust - /// fn return_unit() -> () { - /// () + /// fn foo() -> String { + /// let x = String::new(); + /// x /// } /// ``` - pub UNUSED_UNIT, + /// instead, use + /// ``` + /// fn foo() -> String { + /// String::new() + /// } + /// ``` + pub LET_AND_RETURN, style, - "needless unit expression" + "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block" } -declare_lint_pass!(Return => [UNUSED_UNIT]); +declare_clippy_lint! { + /// **What it does:** Checks for return statements at the end of a block. + /// + /// **Why is this bad?** Removing the `return` and semicolon will make the code + /// more rusty. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// fn foo(x: usize) -> usize { + /// return x; + /// } + /// ``` + /// simplify to + /// ```rust + /// fn foo(x: usize) -> usize { + /// x + /// } + /// ``` + pub NEEDLESS_RETURN, + style, + "using a return statement like `return expr;` where an expression would suffice" +} -impl EarlyLintPass for Return { - fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, span: Span, _: ast::NodeId) { - if_chain! { - if let ast::FnRetTy::Ty(ref ty) = kind.decl().output; - if let ast::TyKind::Tup(ref vals) = ty.kind; - if vals.is_empty() && !ty.span.from_expansion() && get_def(span) == get_def(ty.span); - then { - lint_unneeded_unit_return(cx, ty, span); - } - } - } +#[derive(PartialEq, Eq, Copy, Clone)] +enum RetReplacement { + Empty, + Block, +} - fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { +declare_lint_pass!(Return => [LET_AND_RETURN, NEEDLESS_RETURN]); + +impl<'tcx> LateLintPass<'tcx> for Return { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { + // we need both a let-binding stmt and an expr if_chain! { - if let Some(ref stmt) = block.stmts.last(); - if let ast::StmtKind::Expr(ref expr) = stmt.kind; - if is_unit_expr(expr) && !stmt.span.from_expansion(); + if let Some(retexpr) = block.expr; + if let Some(stmt) = block.stmts.iter().last(); + if let StmtKind::Local(local) = &stmt.kind; + if local.ty.is_none(); + if local.attrs.is_empty(); + if let Some(initexpr) = &local.init; + if let PatKind::Binding(.., ident, _) = local.pat.kind; + if let ExprKind::Path(qpath) = &retexpr.kind; + if match_qpath(qpath, &[&*ident.name.as_str()]); + if !last_statement_borrows(cx, initexpr); + if !in_external_macro(cx.sess(), initexpr.span); + if !in_external_macro(cx.sess(), retexpr.span); + if !in_external_macro(cx.sess(), local.span); + if !in_macro(local.span); then { - let sp = expr.span; - span_lint_and_sugg( + span_lint_and_then( cx, - UNUSED_UNIT, - sp, - "unneeded unit expression", - "remove the final `()`", - String::new(), - Applicability::MachineApplicable, + LET_AND_RETURN, + retexpr.span, + "returning the result of a `let` binding from a block", + |err| { + err.span_label(local.span, "unnecessary `let` binding"); + + if let Some(snippet) = snippet_opt(cx, initexpr.span) { + err.multipart_suggestion( + "return the expression directly", + vec![ + (local.span, String::new()), + (retexpr.span, snippet), + ], + Applicability::MachineApplicable, + ); + } else { + err.span_help(initexpr.span, "this expression can be directly returned"); + } + }, ); } } } - fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { - match e.kind { - ast::ExprKind::Ret(Some(ref expr)) | ast::ExprKind::Break(_, Some(ref expr)) => { - if is_unit_expr(expr) && !expr.span.from_expansion() { - span_lint_and_sugg( - cx, - UNUSED_UNIT, - expr.span, - "unneeded `()`", - "remove the `()`", - String::new(), - Applicability::MachineApplicable, - ); + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + kind: FnKind<'tcx>, + _: &'tcx FnDecl<'tcx>, + body: &'tcx Body<'tcx>, + _: Span, + _: HirId, + ) { + match kind { + FnKind::Closure(_) => check_final_expr(cx, &body.value, Some(body.value.span), RetReplacement::Empty), + FnKind::ItemFn(..) | FnKind::Method(..) => { + if let ExprKind::Block(ref block, _) = body.value.kind { + check_block_return(cx, block); } }, + } + } +} + +fn attr_is_cfg(attr: &Attribute) -> bool { + attr.meta_item_list().is_some() && attr.has_name(sym!(cfg)) +} + +fn check_block_return<'tcx>(cx: &LateContext<'tcx>, block: &Block<'tcx>) { + if let Some(expr) = block.expr { + check_final_expr(cx, expr, Some(expr.span), RetReplacement::Empty); + } else if let Some(stmt) = block.stmts.iter().last() { + match stmt.kind { + StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { + check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty); + }, _ => (), } } +} - fn check_poly_trait_ref(&mut self, cx: &EarlyContext<'_>, poly: &ast::PolyTraitRef, _: &ast::TraitBoundModifier) { - let segments = &poly.trait_ref.path.segments; +fn check_final_expr<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + span: Option<Span>, + replacement: RetReplacement, +) { + if last_statement_borrows(cx, expr) { + return; + } - if_chain! { - if segments.len() == 1; - if ["Fn", "FnMut", "FnOnce"].contains(&&*segments[0].ident.name.as_str()); - if let Some(args) = &segments[0].args; - if let ast::GenericArgs::Parenthesized(generic_args) = &**args; - if let ast::FnRetTy::Ty(ty) = &generic_args.output; - if ty.kind.is_unit(); - then { - lint_unneeded_unit_return(cx, ty, generic_args.span); + match expr.kind { + // simple return is always "bad" + ExprKind::Ret(ref inner) => { + // allow `#[cfg(a)] return a; #[cfg(b)] return b;` + if !expr.attrs.iter().any(attr_is_cfg) { + let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner)); + if !borrows { + emit_return_lint( + cx, + span.expect("`else return` is not possible"), + inner.as_ref().map(|i| i.span), + replacement, + ); + } } - } + }, + // a whole block? check it! + ExprKind::Block(ref block, _) => { + check_block_return(cx, block); + }, + // a match expr, check all arms + // an if/if let expr, check both exprs + // note, if without else is going to be a type checking error anyways + // (except for unit type functions) so we don't match it + ExprKind::Match(_, ref arms, source) => match source { + MatchSource::Normal => { + for arm in arms.iter() { + check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block); + } + }, + MatchSource::IfDesugar { + contains_else_clause: true, + } + | MatchSource::IfLetDesugar { + contains_else_clause: true, + } => { + if let ExprKind::Block(ref ifblock, _) = arms[0].body.kind { + check_block_return(cx, ifblock); + } + check_final_expr(cx, arms[1].body, None, RetReplacement::Empty); + }, + _ => (), + }, + _ => (), } } -// get the def site -#[must_use] -fn get_def(span: Span) -> Option<Span> { - if span.from_expansion() { - Some(span.ctxt().outer_expn_data().def_site) - } else { - None - } -} +fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Span>, replacement: RetReplacement) { + match inner_span { + Some(inner_span) => { + if in_external_macro(cx.tcx.sess, inner_span) || inner_span.from_expansion() { + return; + } -// is this expr a `()` unit? -fn is_unit_expr(expr: &ast::Expr) -> bool { - if let ast::ExprKind::Tup(ref vals) = expr.kind { - vals.is_empty() - } else { - false - } -} - -fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) { - let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) { - fn_source - .rfind("->") - .map_or((ty.span, Applicability::MaybeIncorrect), |rpos| { - ( - #[allow(clippy::cast_possible_truncation)] - ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), - Applicability::MachineApplicable, - ) + span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| { + if let Some(snippet) = snippet_opt(cx, inner_span) { + diag.span_suggestion(ret_span, "remove `return`", snippet, Applicability::MachineApplicable); + } }) - } else { - (ty.span, Applicability::MaybeIncorrect) - }; - span_lint_and_sugg( - cx, - UNUSED_UNIT, - ret_span, - "unneeded unit return type", - "remove the `-> ()`", - String::new(), - appl, - ); + }, + None => match replacement { + RetReplacement::Empty => { + span_lint_and_sugg( + cx, + NEEDLESS_RETURN, + ret_span, + "unneeded `return` statement", + "remove `return`", + String::new(), + Applicability::MachineApplicable, + ); + }, + RetReplacement::Block => { + span_lint_and_sugg( + cx, + NEEDLESS_RETURN, + ret_span, + "unneeded `return` statement", + "replace `return` with an empty block", + "{}".to_string(), + Applicability::MachineApplicable, + ); + }, + }, + } +} + +fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + let mut visitor = BorrowVisitor { cx, borrows: false }; + walk_expr(&mut visitor, expr); + visitor.borrows +} + +struct BorrowVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + borrows: bool, +} + +impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + if self.borrows { + return; + } + + if let Some(def_id) = fn_def_id(self.cx, expr) { + self.borrows = self + .cx + .tcx + .fn_sig(def_id) + .output() + .skip_binder() + .walk() + .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))); + } + + walk_expr(self, expr); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } } diff --git a/clippy_lints/src/unused_unit.rs b/clippy_lints/src/unused_unit.rs new file mode 100644 index 00000000000..e322e402535 --- /dev/null +++ b/clippy_lints/src/unused_unit.rs @@ -0,0 +1,145 @@ +use if_chain::if_chain; +use rustc_ast::ast; +use rustc_ast::visit::FnKind; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Span; +use rustc_span::BytePos; + +use crate::utils::span_lint_and_sugg; + +declare_clippy_lint! { + /// **What it does:** Checks for unit (`()`) expressions that can be removed. + /// + /// **Why is this bad?** Such expressions add no value, but can make the code + /// less readable. Depending on formatting they can make a `break` or `return` + /// statement look like a function call. + /// + /// **Known problems:** The lint currently misses unit return types in types, + /// e.g., the `F` in `fn generic_unit<F: Fn() -> ()>(f: F) { .. }`. + /// + /// **Example:** + /// ```rust + /// fn return_unit() -> () { + /// () + /// } + /// ``` + pub UNUSED_UNIT, + style, + "needless unit expression" +} + +declare_lint_pass!(UnusedUnit => [UNUSED_UNIT]); + +impl EarlyLintPass for UnusedUnit { + fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, span: Span, _: ast::NodeId) { + if_chain! { + if let ast::FnRetTy::Ty(ref ty) = kind.decl().output; + if let ast::TyKind::Tup(ref vals) = ty.kind; + if vals.is_empty() && !ty.span.from_expansion() && get_def(span) == get_def(ty.span); + then { + lint_unneeded_unit_return(cx, ty, span); + } + } + } + + fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { + if_chain! { + if let Some(ref stmt) = block.stmts.last(); + if let ast::StmtKind::Expr(ref expr) = stmt.kind; + if is_unit_expr(expr) && !stmt.span.from_expansion(); + then { + let sp = expr.span; + span_lint_and_sugg( + cx, + UNUSED_UNIT, + sp, + "unneeded unit expression", + "remove the final `()`", + String::new(), + Applicability::MachineApplicable, + ); + } + } + } + + fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { + match e.kind { + ast::ExprKind::Ret(Some(ref expr)) | ast::ExprKind::Break(_, Some(ref expr)) => { + if is_unit_expr(expr) && !expr.span.from_expansion() { + span_lint_and_sugg( + cx, + UNUSED_UNIT, + expr.span, + "unneeded `()`", + "remove the `()`", + String::new(), + Applicability::MachineApplicable, + ); + } + }, + _ => (), + } + } + + fn check_poly_trait_ref(&mut self, cx: &EarlyContext<'_>, poly: &ast::PolyTraitRef, _: &ast::TraitBoundModifier) { + let segments = &poly.trait_ref.path.segments; + + if_chain! { + if segments.len() == 1; + if ["Fn", "FnMut", "FnOnce"].contains(&&*segments[0].ident.name.as_str()); + if let Some(args) = &segments[0].args; + if let ast::GenericArgs::Parenthesized(generic_args) = &**args; + if let ast::FnRetTy::Ty(ty) = &generic_args.output; + if ty.kind.is_unit(); + then { + lint_unneeded_unit_return(cx, ty, generic_args.span); + } + } + } +} + +// get the def site +#[must_use] +fn get_def(span: Span) -> Option<Span> { + if span.from_expansion() { + Some(span.ctxt().outer_expn_data().def_site) + } else { + None + } +} + +// is this expr a `()` unit? +fn is_unit_expr(expr: &ast::Expr) -> bool { + if let ast::ExprKind::Tup(ref vals) = expr.kind { + vals.is_empty() + } else { + false + } +} + +fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) { + let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) { + fn_source + .rfind("->") + .map_or((ty.span, Applicability::MaybeIncorrect), |rpos| { + ( + #[allow(clippy::cast_possible_truncation)] + ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), + Applicability::MachineApplicable, + ) + }) + } else { + (ty.span, Applicability::MaybeIncorrect) + }; + span_lint_and_sugg( + cx, + UNUSED_UNIT, + ret_span, + "unneeded unit return type", + "remove the `-> ()`", + String::new(), + appl, + ); +} diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index 6b5cf2626df..b795516f999 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -76,6 +76,17 @@ mod no_lint_if_stmt_borrows { let stdin = ::std::io::stdin(); return stdin.lock().lines().next().unwrap().unwrap(); } + + fn read_line2(value: bool) -> String { + if value { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + let _a = stdin.lock().lines().next().unwrap().unwrap(); + return String::from("test"); + } else { + return String::new(); + } + } } } diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 1a693c9aa53..3547991935d 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -76,6 +76,17 @@ mod no_lint_if_stmt_borrows { let stdin = ::std::io::stdin(); return stdin.lock().lines().next().unwrap().unwrap(); } + + fn read_line2(value: bool) -> String { + if value { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + let _a = stdin.lock().lines().next().unwrap().unwrap(); + return String::from("test"); + } else { + return String::new(); + } + } } } From 96efaee55240a3d3428ea5fe30c884a3227dad6e Mon Sep 17 00:00:00 2001 From: jrqc <jrqc01@hotmail.com> Date: Thu, 13 Aug 2020 19:30:49 +0300 Subject: [PATCH 446/526] cargo dev update_lints --- clippy_lints/src/lib.rs | 18 +++++++++--------- src/lintlist/mod.rs | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 63de0f8a0c2..c0b645e9311 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -586,7 +586,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &large_stack_arrays::LARGE_STACK_ARRAYS, &len_zero::LEN_WITHOUT_IS_EMPTY, &len_zero::LEN_ZERO, - &returns::LET_AND_RETURN, &let_if_seq::USELESS_LET_IF_SEQ, &let_underscore::LET_UNDERSCORE_LOCK, &let_underscore::LET_UNDERSCORE_MUST_USE, @@ -726,7 +725,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, &needless_continue::NEEDLESS_CONTINUE, &needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, - &returns::NEEDLESS_RETURN, &needless_update::NEEDLESS_UPDATE, &neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, &neg_multiply::NEG_MULTIPLY, @@ -770,7 +768,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ®ex::INVALID_REGEX, ®ex::TRIVIAL_REGEX, &repeat_once::REPEAT_ONCE, - &unused_unit::UNUSED_UNIT, + &returns::LET_AND_RETURN, + &returns::NEEDLESS_RETURN, &serde_api::SERDE_API_MISUSE, &shadow::SHADOW_REUSE, &shadow::SHADOW_SAME, @@ -840,6 +839,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, &unused_io_amount::UNUSED_IO_AMOUNT, &unused_self::UNUSED_SELF, + &unused_unit::UNUSED_UNIT, &unwrap::PANICKING_UNWRAP, &unwrap::UNNECESSARY_UNWRAP, &use_self::USE_SELF, @@ -1284,7 +1284,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), - LintId::of(&returns::LET_AND_RETURN), LintId::of(&let_underscore::LET_UNDERSCORE_LOCK), LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES), LintId::of(&lifetimes::NEEDLESS_LIFETIMES), @@ -1381,7 +1380,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&needless_bool::BOOL_COMPARISON), LintId::of(&needless_bool::NEEDLESS_BOOL), LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), - LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&needless_update::NEEDLESS_UPDATE), LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), LintId::of(&neg_multiply::NEG_MULTIPLY), @@ -1414,7 +1412,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(®ex::INVALID_REGEX), LintId::of(®ex::TRIVIAL_REGEX), LintId::of(&repeat_once::REPEAT_ONCE), - LintId::of(&unused_unit::UNUSED_UNIT), + LintId::of(&returns::LET_AND_RETURN), + LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), @@ -1460,6 +1459,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), + LintId::of(&unused_unit::UNUSED_UNIT), LintId::of(&unwrap::PANICKING_UNWRAP), LintId::of(&unwrap::UNNECESSARY_UNWRAP), LintId::of(&useless_conversion::USELESS_CONVERSION), @@ -1500,7 +1500,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&inherent_to_string::INHERENT_TO_STRING), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), - LintId::of(&returns::LET_AND_RETURN), LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING), LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::FOR_KV_MAP), @@ -1543,7 +1542,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), LintId::of(&misc_early::REDUNDANT_PATTERN), LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED), - LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&neg_multiply::NEG_MULTIPLY), LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), @@ -1555,7 +1553,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES), LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), LintId::of(®ex::TRIVIAL_REGEX), - LintId::of(&unused_unit::UNUSED_UNIT), + LintId::of(&returns::LET_AND_RETURN), + LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&strings::STRING_LIT_AS_BYTES), LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), @@ -1564,6 +1563,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::FN_TO_NUMERIC_CAST), LintId::of(&types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), + LintId::of(&unused_unit::UNUSED_UNIT), LintId::of(&write::PRINTLN_EMPTY_STRING), LintId::of(&write::PRINT_LITERAL), LintId::of(&write::PRINT_WITH_NEWLINE), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 7464f1cc6de..dff6198d00d 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1037,7 +1037,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ group: "style", desc: "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block", deprecation: None, - module: "let_and_return", + module: "returns", }, Lint { name: "let_underscore_lock", @@ -1534,7 +1534,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ group: "style", desc: "using a return statement like `return expr;` where an expression would suffice", deprecation: None, - module: "needless_return", + module: "returns", }, Lint { name: "needless_update", @@ -2479,7 +2479,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ group: "style", desc: "needless unit expression", deprecation: None, - module: "returns", + module: "unused_unit", }, Lint { name: "unwrap_used", From baa4cb1cddc3a8ce1f47c4006e236edf082ee858 Mon Sep 17 00:00:00 2001 From: jrqc <jrqc01@hotmail.com> Date: Fri, 14 Aug 2020 09:25:26 +0300 Subject: [PATCH 447/526] early return removed --- clippy_lints/src/returns.rs | 4 ---- clippy_lints/src/unused_unit.rs | 3 +-- tests/ui/needless_return.fixed | 30 +++++++++++++----------------- tests/ui/needless_return.rs | 30 +++++++++++++----------------- tests/ui/needless_return.stderr | 14 +++++++++++++- 5 files changed, 40 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 4d91f9be999..3c5541e64b4 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -160,10 +160,6 @@ fn check_final_expr<'tcx>( span: Option<Span>, replacement: RetReplacement, ) { - if last_statement_borrows(cx, expr) { - return; - } - match expr.kind { // simple return is always "bad" ExprKind::Ret(ref inner) => { diff --git a/clippy_lints/src/unused_unit.rs b/clippy_lints/src/unused_unit.rs index e322e402535..7548c6afa97 100644 --- a/clippy_lints/src/unused_unit.rs +++ b/clippy_lints/src/unused_unit.rs @@ -16,8 +16,7 @@ declare_clippy_lint! { /// less readable. Depending on formatting they can make a `break` or `return` /// statement look like a function call. /// - /// **Known problems:** The lint currently misses unit return types in types, - /// e.g., the `F` in `fn generic_unit<F: Fn() -> ()>(f: F) { .. }`. + /// **Known problems:** None. /// /// **Example:** /// ```rust diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index b795516f999..d849e093da7 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -69,24 +69,20 @@ fn test_void_match(x: u32) { } } -mod no_lint_if_stmt_borrows { - mod issue_5858 { - fn read_line() -> String { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - return stdin.lock().lines().next().unwrap().unwrap(); - } +fn read_line() -> String { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + return stdin.lock().lines().next().unwrap().unwrap(); +} - fn read_line2(value: bool) -> String { - if value { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - let _a = stdin.lock().lines().next().unwrap().unwrap(); - return String::from("test"); - } else { - return String::new(); - } - } +fn borrows_but_not_last(value: bool) -> String { + if value { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + let _a = stdin.lock().lines().next().unwrap().unwrap(); + String::from("test") + } else { + String::new() } } diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 3547991935d..29f2bd1852a 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -69,24 +69,20 @@ fn test_void_match(x: u32) { } } -mod no_lint_if_stmt_borrows { - mod issue_5858 { - fn read_line() -> String { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - return stdin.lock().lines().next().unwrap().unwrap(); - } +fn read_line() -> String { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + return stdin.lock().lines().next().unwrap().unwrap(); +} - fn read_line2(value: bool) -> String { - if value { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - let _a = stdin.lock().lines().next().unwrap().unwrap(); - return String::from("test"); - } else { - return String::new(); - } - } +fn borrows_but_not_last(value: bool) -> String { + if value { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + let _a = stdin.lock().lines().next().unwrap().unwrap(); + return String::from("test"); + } else { + return String::new(); } } diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index c34eecbcbb6..f73c833a801 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -72,5 +72,17 @@ error: unneeded `return` statement LL | _ => return, | ^^^^^^ help: replace `return` with an empty block: `{}` -error: aborting due to 12 previous errors +error: unneeded `return` statement + --> $DIR/needless_return.rs:83:9 + | +LL | return String::from("test"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:85:9 + | +LL | return String::new(); + | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()` + +error: aborting due to 14 previous errors From 1a140dcc1c933ae84365bd1153372a7430f6f647 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sun, 16 Aug 2020 00:25:54 +0200 Subject: [PATCH 448/526] Improve needless_doctest_main by using the parser --- clippy_lints/src/doc.rs | 75 ++++++++++++++++++++++++++++--- tests/ui/needless_doc_main.rs | 68 ++++++++++++++++++++++++++-- tests/ui/needless_doc_main.stderr | 12 +++-- 3 files changed, 142 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 6ce36fd2360..9555459e240 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,16 +1,22 @@ use crate::utils::{implements_trait, is_entrypoint_fn, is_type_diagnostic_item, return_ty, span_lint}; use if_chain::if_chain; use itertools::Itertools; -use rustc_ast::ast::{AttrKind, Attribute}; +use rustc_ast::ast::{Async, AttrKind, Attribute, FnRetTy, ItemKind}; use rustc_ast::token::CommentKind; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sync::Lrc; +use rustc_errors::emitter::EmitterWriter; +use rustc_errors::Handler; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; +use rustc_parse::maybe_new_parser_from_source_str; +use rustc_session::parse::ParseSess; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::source_map::{BytePos, MultiSpan, Span}; -use rustc_span::Pos; +use rustc_span::source_map::{BytePos, FilePathMapping, MultiSpan, SourceMap, Span}; +use rustc_span::{FileName, Pos}; +use std::io; use std::ops::Range; use url::Url; @@ -431,10 +437,67 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize headers } -static LEAVE_MAIN_PATTERNS: &[&str] = &["static", "fn main() {}", "extern crate", "async fn main() {"]; - fn check_code(cx: &LateContext<'_>, text: &str, span: Span) { - if text.contains("fn main() {") && !LEAVE_MAIN_PATTERNS.iter().any(|p| text.contains(p)) { + fn has_needless_main(code: &str) -> bool { + let filename = FileName::anon_source_code(code); + + let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let emitter = EmitterWriter::new(box io::sink(), None, false, false, false, None, false); + let handler = Handler::with_emitter(false, None, box emitter); + let sess = ParseSess::with_span_handler(handler, sm); + + let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code.into()) { + Ok(p) => p, + Err(errs) => { + for mut err in errs { + err.cancel(); + } + return false; + }, + }; + + let mut relevant_main_found = false; + loop { + match parser.parse_item() { + Ok(Some(item)) => match &item.kind { + // Tests with one of these items are ignored + ItemKind::Static(..) + | ItemKind::Const(..) + | ItemKind::ExternCrate(..) + | ItemKind::ForeignMod(..) => return false, + // We found a main function ... + ItemKind::Fn(_, sig, _, Some(block)) if item.ident.name == sym!(main) => { + let is_async = matches!(sig.header.asyncness, Async::Yes{..}); + let returns_nothing = match &sig.decl.output { + FnRetTy::Default(..) => true, + FnRetTy::Ty(ty) if ty.kind.is_unit() => true, + _ => false, + }; + + if returns_nothing && !is_async && !block.stmts.is_empty() { + // This main function should be linted, but only if there are no other functions + relevant_main_found = true; + } else { + // This main function should not be linted, we're done + return false; + } + }, + // Another function was found; this case is ignored too + ItemKind::Fn(..) => return false, + _ => {}, + }, + Ok(None) => break, + Err(mut e) => { + e.cancel(); + return false; + }, + } + } + + relevant_main_found + } + + if has_needless_main(text) { span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest"); } } diff --git a/tests/ui/needless_doc_main.rs b/tests/ui/needless_doc_main.rs index 682d7b3c4ce..883683e08a2 100644 --- a/tests/ui/needless_doc_main.rs +++ b/tests/ui/needless_doc_main.rs @@ -9,8 +9,14 @@ /// } /// ``` /// -/// This should, too. +/// With an explicit return type it should lint too +/// ``` +/// fn main() -> () { +/// unimplemented!(); +/// } +/// ``` /// +/// This should, too. /// ```rust /// fn main() { /// unimplemented!(); @@ -18,7 +24,6 @@ /// ``` /// /// This one too. -/// /// ```no_run /// fn main() { /// unimplemented!(); @@ -33,6 +38,20 @@ fn bad_doctests() {} /// fn main(){} /// ``` /// +/// This shouldn't lint either, because main is async: +/// ``` +/// async fn main() { +/// assert_eq!(42, ANSWER); +/// } +/// ``` +/// +/// Same here, because the return type is not the unit type: +/// ``` +/// fn main() -> Result<()> { +/// Ok(()) +/// } +/// ``` +/// /// This shouldn't lint either, because there's a `static`: /// ``` /// static ANSWER: i32 = 42; @@ -42,6 +61,15 @@ fn bad_doctests() {} /// } /// ``` /// +/// This shouldn't lint either, because there's a `const`: +/// ``` +/// fn main() { +/// assert_eq!(42, ANSWER); +/// } +/// +/// const ANSWER: i32 = 42; +/// ``` +/// /// Neither should this lint because of `extern crate`: /// ``` /// #![feature(test)] @@ -51,8 +79,41 @@ fn bad_doctests() {} /// } /// ``` /// -/// We should not lint ignored examples: +/// Neither should this lint because it has an extern block: +/// ``` +/// extern {} +/// fn main() { +/// unimplemented!(); +/// } +/// ``` /// +/// This should not lint because there is another function defined: +/// ``` +/// fn fun() {} +/// +/// fn main() { +/// unimplemented!(); +/// } +/// ``` +/// +/// We should not lint inside raw strings ... +/// ``` +/// let string = r#" +/// fn main() { +/// unimplemented!(); +/// } +/// "#; +/// ``` +/// +/// ... or comments +/// ``` +/// // fn main() { +/// // let _inception = 42; +/// // } +/// let _inception = 42; +/// ``` +/// +/// We should not lint ignored examples: /// ```rust,ignore /// fn main() { /// unimplemented!(); @@ -60,7 +121,6 @@ fn bad_doctests() {} /// ``` /// /// Or even non-rust examples: -/// /// ```text /// fn main() { /// is what starts the program diff --git a/tests/ui/needless_doc_main.stderr b/tests/ui/needless_doc_main.stderr index 65d40ee6832..05c7f9d33a7 100644 --- a/tests/ui/needless_doc_main.stderr +++ b/tests/ui/needless_doc_main.stderr @@ -7,16 +7,22 @@ LL | /// fn main() { = note: `-D clippy::needless-doctest-main` implied by `-D warnings` error: needless `fn main` in doctest - --> $DIR/needless_doc_main.rs:15:4 + --> $DIR/needless_doc_main.rs:14:4 + | +LL | /// fn main() -> () { + | ^^^^^^^^^^^^^^^^^^ + +error: needless `fn main` in doctest + --> $DIR/needless_doc_main.rs:21:4 | LL | /// fn main() { | ^^^^^^^^^^^^ error: needless `fn main` in doctest - --> $DIR/needless_doc_main.rs:23:4 + --> $DIR/needless_doc_main.rs:28:4 | LL | /// fn main() { | ^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors From a3ea65c2d9bc52f308745ae488435388fce753a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Mon, 15 Jun 2020 11:21:56 +0200 Subject: [PATCH 449/526] Implement new lint --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 3 + clippy_lints/src/methods/mod.rs | 130 ++++++++++++++++++++++- src/lintlist/mod.rs | 7 ++ tests/ui/unnecessary_lazy_eval.fixed | 105 +++++++++++++++++++ tests/ui/unnecessary_lazy_eval.rs | 105 +++++++++++++++++++ tests/ui/unnecessary_lazy_eval.stderr | 144 ++++++++++++++++++++++++++ 7 files changed, 494 insertions(+), 1 deletion(-) create mode 100644 tests/ui/unnecessary_lazy_eval.fixed create mode 100644 tests/ui/unnecessary_lazy_eval.rs create mode 100644 tests/ui/unnecessary_lazy_eval.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 50fe7612909..c21190e9b9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1646,6 +1646,7 @@ Released 2018-09-13 [`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn [`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option +[`option_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_unwrap_or_else [`or_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call [`out_of_bounds_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#out_of_bounds_indexing [`overflow_check_conditional`]: https://rust-lang.github.io/rust-clippy/master/index.html#overflow_check_conditional diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 986e9d9bee4..cb29f71387b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -672,6 +672,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::OK_EXPECT, &methods::OPTION_AS_REF_DEREF, &methods::OPTION_MAP_OR_NONE, + &methods::UNNECESSARY_LAZY_EVALUATION, &methods::OR_FUN_CALL, &methods::RESULT_MAP_OR_INTO_OPTION, &methods::SEARCH_IS_SOME, @@ -1360,6 +1361,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::UNINIT_ASSUMED_INIT), LintId::of(&methods::UNNECESSARY_FILTER_MAP), LintId::of(&methods::UNNECESSARY_FOLD), + LintId::of(&methods::UNNECESSARY_LAZY_EVALUATION), LintId::of(&methods::USELESS_ASREF), LintId::of(&methods::WRONG_SELF_CONVENTION), LintId::of(&methods::ZST_OFFSET), @@ -1610,6 +1612,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::FILTER_NEXT), LintId::of(&methods::FLAT_MAP_IDENTITY), LintId::of(&methods::OPTION_AS_REF_DEREF), + LintId::of(&methods::UNNECESSARY_LAZY_EVALUATION), LintId::of(&methods::SEARCH_IS_SOME), LintId::of(&methods::SKIP_WHILE_NEXT), LintId::of(&methods::SUSPICIOUS_MAP), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2330978e67f..61b7f2647ee 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1329,6 +1329,32 @@ declare_clippy_lint! { "`push_str()` used with a single-character string literal as parameter" } +declare_clippy_lint! { + /// **What it does:** Looks for unnecessary lazily evaluated closures on `Option` and `Result`. + /// + /// **Why is this bad?** Using eager evaluation is shorter and simpler in some cases. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code where clippy issues a warning + /// let opt: Option<u32> = None; + /// + /// opt.unwrap_or_else(|| 42); + /// ``` + /// Use instead: + /// ```rust + /// let opt: Option<u32> = None; + /// + /// opt.unwrap_or(42); + /// ``` + pub UNNECESSARY_LAZY_EVALUATION, + style, + "using unnecessary lazy evaluation, which can be replaced with simpler eager evaluation" +} + declare_lint_pass!(Methods => [ UNWRAP_USED, EXPECT_USED, @@ -1378,6 +1404,7 @@ declare_lint_pass!(Methods => [ ZST_OFFSET, FILETYPE_IS_FILE, OPTION_AS_REF_DEREF, + UNNECESSARY_LAZY_EVALUATION, ]); impl<'tcx> LateLintPass<'tcx> for Methods { @@ -1398,13 +1425,18 @@ impl<'tcx> LateLintPass<'tcx> for Methods { ["expect", "ok"] => lint_ok_expect(cx, expr, arg_lists[1]), ["expect", ..] => lint_expect(cx, expr, arg_lists[0]), ["unwrap_or", "map"] => option_map_unwrap_or::lint(cx, expr, arg_lists[1], arg_lists[0], method_spans[1]), - ["unwrap_or_else", "map"] => lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0]), + ["unwrap_or_else", "map"] => { + lint_lazy_eval(cx, expr, arg_lists[0], true, "unwrap_or"); + lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0]); + }, ["map_or", ..] => lint_map_or_none(cx, expr, arg_lists[0]), ["and_then", ..] => { + lint_lazy_eval(cx, expr, arg_lists[0], false, "and"); bind_instead_of_map::OptionAndThenSome::lint(cx, expr, arg_lists[0]); bind_instead_of_map::ResultAndThenOk::lint(cx, expr, arg_lists[0]); }, ["or_else", ..] => { + lint_lazy_eval(cx, expr, arg_lists[0], false, "or"); bind_instead_of_map::ResultOrElseErrInfo::lint(cx, expr, arg_lists[0]); }, ["next", "filter"] => lint_filter_next(cx, expr, arg_lists[1]), @@ -1448,6 +1480,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods { ["is_file", ..] => lint_filetype_is_file(cx, expr, arg_lists[0]), ["map", "as_ref"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], false), ["map", "as_mut"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], true), + ["unwrap_or_else", ..] => lint_lazy_eval(cx, expr, arg_lists[0], true, "unwrap_or"), + ["get_or_insert_with", ..] => lint_lazy_eval(cx, expr, arg_lists[0], true, "get_or_insert"), + ["ok_or_else", ..] => lint_lazy_eval(cx, expr, arg_lists[0], true, "ok_or"), _ => {}, } @@ -2663,6 +2698,99 @@ fn lint_map_flatten<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map } } +/// lint use of `<fn>_else(simple closure)` for `Option`s and `Result`s that can be +/// replaced with `<fn>(return value of simple closure)` +fn lint_lazy_eval<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + expr: &'tcx hir::Expr<'_>, + args: &'tcx [hir::Expr<'_>], + allow_variant_calls: bool, + simplify_using: &str, +) { + let is_option = is_type_diagnostic_item(cx, cx.tables.expr_ty(&args[0]), sym!(option_type)); + let is_result = is_type_diagnostic_item(cx, cx.tables.expr_ty(&args[0]), sym!(result_type)); + + if !is_option && !is_result { + return; + } + + // Return true if the expression is an accessor of any of the arguments + fn expr_uses_argument(expr: &hir::Expr<'_>, params: &[hir::Param<'_>]) -> bool { + params.iter().any(|arg| { + if_chain! { + if let hir::PatKind::Binding(_, _, ident, _) = arg.pat.kind; + if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.kind; + if let [p, ..] = path.segments; + then { + ident.name == p.ident.name + } else { + false + } + } + }) + } + + fn match_any_qpath(path: &hir::QPath<'_>, paths: &[&[&str]]) -> bool { + paths.iter().any(|candidate| match_qpath(path, candidate)) + } + + if let hir::ExprKind::Closure(_, _, eid, _, _) = args[1].kind { + let body = cx.tcx.hir().body(eid); + let ex = &body.value; + let params = &body.params; + + let simplify = match ex.kind { + // Closures returning literals can be unconditionally simplified + hir::ExprKind::Lit(_) => true, + + // Reading fields can be simplified if the object is not an argument of the closure + hir::ExprKind::Field(ref object, _) => !expr_uses_argument(object, params), + + // Paths can be simplified if the root is not the argument, this also covers None + hir::ExprKind::Path(_) => !expr_uses_argument(ex, params), + + // Calls to Some, Ok, Err can be considered literals if they don't derive an argument + hir::ExprKind::Call(ref func, ref args) => if_chain! { + if allow_variant_calls; // Disable lint when rules conflict with bind_instead_of_map + if let hir::ExprKind::Path(ref path) = func.kind; + if match_any_qpath(path, &[&["Some"], &["Ok"], &["Err"]]); + then { + !args.iter().any(|arg| expr_uses_argument(arg, params)) + } else { + false + } + }, + + // For anything more complex than the above, a closure is probably the right solution, + // or the case is handled by an other lint + _ => false, + }; + + if simplify { + let msg = if is_option { + "unnecessary closure used to substitute value for `Option::None`" + } else { + "unnecessary closure used to substitute value for `Result::Err`" + }; + + span_lint_and_sugg( + cx, + UNNECESSARY_LAZY_EVALUATION, + expr.span, + msg, + &format!("Use `{}` instead", simplify_using), + format!( + "{0}.{1}({2})", + snippet(cx, args[0].span, ".."), + simplify_using, + snippet(cx, ex.span, ".."), + ), + Applicability::MachineApplicable, + ); + } + } +} + /// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s fn lint_map_unwrap_or_else<'tcx>( cx: &LateContext<'tcx>, diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 233f95deedd..1e76163f946 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2383,6 +2383,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "methods", }, + Lint { + name: "unnecessary_lazy_eval", + group: "style", + desc: "using unnecessary lazy evaluation, which can be replaced with simpler eager evaluation", + deprecation: None, + module: "methods", + }, Lint { name: "unnecessary_mut_passed", group: "style", diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed new file mode 100644 index 00000000000..fcfa6dfe12d --- /dev/null +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -0,0 +1,105 @@ +// run-rustfix +#![warn(clippy::unnecessary_lazy_evaluation)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::bind_instead_of_map)] + +struct Deep(Option<u32>); + +#[derive(Copy, Clone)] +struct SomeStruct { + some_field: u32, +} + +impl SomeStruct { + fn return_some_field(&self) -> u32 { + self.some_field + } +} + +fn some_call<T: Default>() -> T { + T::default() +} + +fn main() { + let astronomers_pi = 10; + let ext_str = SomeStruct { some_field: 10 }; + + // Should lint - Option + let mut opt = Some(42); + let ext_opt = Some(42); + let _ = opt.unwrap_or(2); + let _ = opt.unwrap_or(astronomers_pi); + let _ = opt.unwrap_or(ext_str.some_field); + let _ = opt.and(ext_opt); + let _ = opt.or(ext_opt); + let _ = opt.or(None); + let _ = opt.get_or_insert(2); + let _ = opt.ok_or(2); + + // Cases when unwrap is not called on a simple variable + let _ = Some(10).unwrap_or(2); + let _ = Some(10).and(ext_opt); + let _: Option<u32> = None.or(ext_opt); + let _ = None.get_or_insert(2); + let _: Result<u32, u32> = None.ok_or(2); + let _: Option<u32> = None.or(None); + + let mut deep = Deep(Some(42)); + let _ = deep.0.unwrap_or(2); + let _ = deep.0.and(ext_opt); + let _ = deep.0.or(None); + let _ = deep.0.get_or_insert(2); + let _ = deep.0.ok_or(2); + + // Should not lint - Option + let _ = opt.unwrap_or_else(|| ext_str.return_some_field()); + let _ = opt.or_else(some_call); + let _ = opt.or_else(|| some_call()); + let _: Result<u32, u32> = opt.ok_or_else(|| some_call()); + let _: Result<u32, u32> = opt.ok_or_else(some_call); + let _ = deep.0.get_or_insert_with(|| some_call()); + let _ = deep.0.or_else(some_call); + let _ = deep.0.or_else(|| some_call()); + + // These are handled by bind_instead_of_map + let _: Option<u32> = None.or_else(|| Some(3)); + let _ = deep.0.or_else(|| Some(3)); + let _ = opt.or_else(|| Some(3)); + + // Should lint - Result + let res: Result<u32, u32> = Err(5); + let res2: Result<u32, SomeStruct> = Err(SomeStruct { some_field: 5 }); + + let _ = res2.unwrap_or(2); + let _ = res2.unwrap_or(astronomers_pi); + let _ = res2.unwrap_or(ext_str.some_field); + + // Should not lint - Result + let _ = res.unwrap_or_else(|err| err); + let _ = res2.unwrap_or_else(|err| err.some_field); + let _ = res2.unwrap_or_else(|err| err.return_some_field()); + let _ = res2.unwrap_or_else(|_| ext_str.return_some_field()); + + let _: Result<u32, u32> = res.and_then(|x| Ok(x)); + let _: Result<u32, u32> = res.and_then(|x| Err(x)); + + let _: Result<u32, u32> = res.or_else(|err| Ok(err)); + let _: Result<u32, u32> = res.or_else(|err| Err(err)); + + // These are handled by bind_instead_of_map + let _: Result<u32, u32> = res.and_then(|_| Ok(2)); + let _: Result<u32, u32> = res.and_then(|_| Ok(astronomers_pi)); + let _: Result<u32, u32> = res.and_then(|_| Ok(ext_str.some_field)); + + let _: Result<u32, u32> = res.and_then(|_| Err(2)); + let _: Result<u32, u32> = res.and_then(|_| Err(astronomers_pi)); + let _: Result<u32, u32> = res.and_then(|_| Err(ext_str.some_field)); + + let _: Result<u32, u32> = res.or_else(|_| Ok(2)); + let _: Result<u32, u32> = res.or_else(|_| Ok(astronomers_pi)); + let _: Result<u32, u32> = res.or_else(|_| Ok(ext_str.some_field)); + + let _: Result<u32, u32> = res.or_else(|_| Err(2)); + let _: Result<u32, u32> = res.or_else(|_| Err(astronomers_pi)); + let _: Result<u32, u32> = res.or_else(|_| Err(ext_str.some_field)); +} diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs new file mode 100644 index 00000000000..04b3c8ae1e2 --- /dev/null +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -0,0 +1,105 @@ +// run-rustfix +#![warn(clippy::unnecessary_lazy_eval)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::bind_instead_of_map)] + +struct Deep(Option<u32>); + +#[derive(Copy, Clone)] +struct SomeStruct { + some_field: u32, +} + +impl SomeStruct { + fn return_some_field(&self) -> u32 { + self.some_field + } +} + +fn some_call<T: Default>() -> T { + T::default() +} + +fn main() { + let astronomers_pi = 10; + let ext_str = SomeStruct { some_field: 10 }; + + // Should lint - Option + let mut opt = Some(42); + let ext_opt = Some(42); + let _ = opt.unwrap_or_else(|| 2); + let _ = opt.unwrap_or_else(|| astronomers_pi); + let _ = opt.unwrap_or_else(|| ext_str.some_field); + let _ = opt.and_then(|_| ext_opt); + let _ = opt.or_else(|| ext_opt); + let _ = opt.or_else(|| None); + let _ = opt.get_or_insert_with(|| 2); + let _ = opt.ok_or_else(|| 2); + + // Cases when unwrap is not called on a simple variable + let _ = Some(10).unwrap_or_else(|| 2); + let _ = Some(10).and_then(|_| ext_opt); + let _: Option<u32> = None.or_else(|| ext_opt); + let _ = None.get_or_insert_with(|| 2); + let _: Result<u32, u32> = None.ok_or_else(|| 2); + let _: Option<u32> = None.or_else(|| None); + + let mut deep = Deep(Some(42)); + let _ = deep.0.unwrap_or_else(|| 2); + let _ = deep.0.and_then(|_| ext_opt); + let _ = deep.0.or_else(|| None); + let _ = deep.0.get_or_insert_with(|| 2); + let _ = deep.0.ok_or_else(|| 2); + + // Should not lint - Option + let _ = opt.unwrap_or_else(|| ext_str.return_some_field()); + let _ = opt.or_else(some_call); + let _ = opt.or_else(|| some_call()); + let _: Result<u32, u32> = opt.ok_or_else(|| some_call()); + let _: Result<u32, u32> = opt.ok_or_else(some_call); + let _ = deep.0.get_or_insert_with(|| some_call()); + let _ = deep.0.or_else(some_call); + let _ = deep.0.or_else(|| some_call()); + + // These are handled by bind_instead_of_map + let _: Option<u32> = None.or_else(|| Some(3)); + let _ = deep.0.or_else(|| Some(3)); + let _ = opt.or_else(|| Some(3)); + + // Should lint - Result + let res: Result<u32, u32> = Err(5); + let res2: Result<u32, SomeStruct> = Err(SomeStruct { some_field: 5 }); + + let _ = res2.unwrap_or_else(|_| 2); + let _ = res2.unwrap_or_else(|_| astronomers_pi); + let _ = res2.unwrap_or_else(|_| ext_str.some_field); + + // Should not lint - Result + let _ = res.unwrap_or_else(|err| err); + let _ = res2.unwrap_or_else(|err| err.some_field); + let _ = res2.unwrap_or_else(|err| err.return_some_field()); + let _ = res2.unwrap_or_else(|_| ext_str.return_some_field()); + + let _: Result<u32, u32> = res.and_then(|x| Ok(x)); + let _: Result<u32, u32> = res.and_then(|x| Err(x)); + + let _: Result<u32, u32> = res.or_else(|err| Ok(err)); + let _: Result<u32, u32> = res.or_else(|err| Err(err)); + + // These are handled by bind_instead_of_map + let _: Result<u32, u32> = res.and_then(|_| Ok(2)); + let _: Result<u32, u32> = res.and_then(|_| Ok(astronomers_pi)); + let _: Result<u32, u32> = res.and_then(|_| Ok(ext_str.some_field)); + + let _: Result<u32, u32> = res.and_then(|_| Err(2)); + let _: Result<u32, u32> = res.and_then(|_| Err(astronomers_pi)); + let _: Result<u32, u32> = res.and_then(|_| Err(ext_str.some_field)); + + let _: Result<u32, u32> = res.or_else(|_| Ok(2)); + let _: Result<u32, u32> = res.or_else(|_| Ok(astronomers_pi)); + let _: Result<u32, u32> = res.or_else(|_| Ok(ext_str.some_field)); + + let _: Result<u32, u32> = res.or_else(|_| Err(2)); + let _: Result<u32, u32> = res.or_else(|_| Err(astronomers_pi)); + let _: Result<u32, u32> = res.or_else(|_| Err(ext_str.some_field)); +} diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr new file mode 100644 index 00000000000..b941bf84246 --- /dev/null +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -0,0 +1,144 @@ +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:30:13 + | +LL | let _ = opt.unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(2)` + | + = note: `-D clippy::unnecessary-lazy-evaluation` implied by `-D warnings` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:31:13 + | +LL | let _ = opt.unwrap_or_else(|| astronomers_pi); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(astronomers_pi)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:32:13 + | +LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(ext_str.some_field)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:33:13 + | +LL | let _ = opt.and_then(|_| ext_opt); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `opt.and(ext_opt)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:34:13 + | +LL | let _ = opt.or_else(|| ext_opt); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `opt.or(ext_opt)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:35:13 + | +LL | let _ = opt.or_else(|| None); + | ^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `opt.or(None)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:36:13 + | +LL | let _ = opt.get_or_insert_with(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `opt.get_or_insert(2)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:37:13 + | +LL | let _ = opt.ok_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `opt.ok_or(2)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:40:13 + | +LL | let _ = Some(10).unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `Some(10).unwrap_or(2)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:41:13 + | +LL | let _ = Some(10).and_then(|_| ext_opt); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `Some(10).and(ext_opt)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:42:26 + | +LL | let _: Option<u32> = None.or_else(|| ext_opt); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(ext_opt)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:43:13 + | +LL | let _ = None.get_or_insert_with(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `None.get_or_insert(2)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:44:31 + | +LL | let _: Result<u32, u32> = None.ok_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `None.ok_or(2)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:45:26 + | +LL | let _: Option<u32> = None.or_else(|| None); + | ^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(None)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:48:13 + | +LL | let _ = deep.0.unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `deep.0.unwrap_or(2)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:49:13 + | +LL | let _ = deep.0.and_then(|_| ext_opt); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `deep.0.and(ext_opt)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:50:13 + | +LL | let _ = deep.0.or_else(|| None); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `deep.0.or(None)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:51:13 + | +LL | let _ = deep.0.get_or_insert_with(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `deep.0.get_or_insert(2)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:52:13 + | +LL | let _ = deep.0.ok_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `deep.0.ok_or(2)` + +error: unnecessary closure used to substitute value for `Result::Err` + --> $DIR/unnecessary_lazy_eval.rs:73:13 + | +LL | let _ = res2.unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(2)` + +error: unnecessary closure used to substitute value for `Result::Err` + --> $DIR/unnecessary_lazy_eval.rs:74:13 + | +LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(astronomers_pi)` + +error: unnecessary closure used to substitute value for `Result::Err` + --> $DIR/unnecessary_lazy_eval.rs:75:13 + | +LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(ext_str.some_field)` + +error: unknown clippy lint: clippy::unnecessary_lazy_eval + --> $DIR/unnecessary_lazy_eval.rs:2:9 + | +LL | #![warn(clippy::unnecessary_lazy_eval)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::unnecessary_lazy_evaluation` + | + = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` + +error: aborting due to 23 previous errors + From 923d61222cc9de9e662e90570e4725ef00f48d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Mon, 15 Jun 2020 11:48:14 +0200 Subject: [PATCH 450/526] Rename the changelog footnote as well --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c21190e9b9c..54489751014 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1646,7 +1646,6 @@ Released 2018-09-13 [`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn [`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option -[`option_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_unwrap_or_else [`or_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call [`out_of_bounds_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#out_of_bounds_indexing [`overflow_check_conditional`]: https://rust-lang.github.io/rust-clippy/master/index.html#overflow_check_conditional @@ -1755,6 +1754,7 @@ Released 2018-09-13 [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold +[`unnecessary_lazy_eval`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_eval [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation [`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by From 848af393103d769458a206547ea4506fd0229304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Mon, 15 Jun 2020 14:55:23 +0200 Subject: [PATCH 451/526] Add note to `or_fun_call`, list checked methods --- clippy_lints/src/methods/mod.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 61b7f2647ee..c672ca41dec 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1330,11 +1330,21 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Looks for unnecessary lazily evaluated closures on `Option` and `Result`. + /// **What it does:** As the counterpart to `or_fun_call`, this lint looks for unnecessary + /// lazily evaluated closures on `Option` and `Result`. + /// + /// This lint suggests changing the following functions, when eager evaluation results in + /// simpler code: + /// - `unwrap_or_else` to `unwrap_or` + /// - `and_then` to `and` + /// - `or_else` to `or` + /// - `get_or_insert_with` to `get_or_insert` + /// - `ok_or_else` to `ok_or` /// /// **Why is this bad?** Using eager evaluation is shorter and simpler in some cases. /// - /// **Known problems:** None. + /// **Known problems:** It is possible, but not recommended for `Deref` and `Index` to have + /// side effects. Eagerly evaluating them can change the semantics of the program. /// /// **Example:** /// From a7cc5d40683b9351c35a627b05886f43fdec684f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Mon, 15 Jun 2020 15:26:02 +0200 Subject: [PATCH 452/526] Also simplify if the closure body is an index expression --- clippy_lints/src/methods/mod.rs | 10 ++++ tests/ui/unnecessary_lazy_eval.fixed | 60 ++++++++++++----------- tests/ui/unnecessary_lazy_eval.rs | 60 ++++++++++++----------- tests/ui/unnecessary_lazy_eval.stderr | 68 ++++++++++++++++----------- 4 files changed, 116 insertions(+), 82 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index c672ca41dec..ed8eaba75d1 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2753,6 +2753,16 @@ fn lint_lazy_eval<'a, 'tcx>( // Closures returning literals can be unconditionally simplified hir::ExprKind::Lit(_) => true, + hir::ExprKind::Index(ref object, ref index) => { + // arguments are not being indexed into + if !expr_uses_argument(object, params) { + // arguments are not used as index + !expr_uses_argument(index, params) + } else { + false + } + }, + // Reading fields can be simplified if the object is not an argument of the closure hir::ExprKind::Field(ref object, _) => !expr_uses_argument(object, params), diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index fcfa6dfe12d..c806cf8dce4 100644 --- a/tests/ui/unnecessary_lazy_eval.fixed +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -3,15 +3,15 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] -struct Deep(Option<u32>); +struct Deep(Option<usize>); #[derive(Copy, Clone)] struct SomeStruct { - some_field: u32, + some_field: usize, } impl SomeStruct { - fn return_some_field(&self) -> u32 { + fn return_some_field(&self) -> usize { self.some_field } } @@ -22,6 +22,7 @@ fn some_call<T: Default>() -> T { fn main() { let astronomers_pi = 10; + let ext_arr: [usize; 1] = [2]; let ext_str = SomeStruct { some_field: 10 }; // Should lint - Option @@ -30,19 +31,21 @@ fn main() { let _ = opt.unwrap_or(2); let _ = opt.unwrap_or(astronomers_pi); let _ = opt.unwrap_or(ext_str.some_field); + let _ = opt.unwrap_or(ext_arr[0]); let _ = opt.and(ext_opt); let _ = opt.or(ext_opt); let _ = opt.or(None); let _ = opt.get_or_insert(2); let _ = opt.ok_or(2); + let _ = opt.ok_or(ext_arr[0]); // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or(2); let _ = Some(10).and(ext_opt); - let _: Option<u32> = None.or(ext_opt); + let _: Option<usize> = None.or(ext_opt); let _ = None.get_or_insert(2); - let _: Result<u32, u32> = None.ok_or(2); - let _: Option<u32> = None.or(None); + let _: Result<usize, usize> = None.ok_or(2); + let _: Option<usize> = None.or(None); let mut deep = Deep(Some(42)); let _ = deep.0.unwrap_or(2); @@ -55,20 +58,22 @@ fn main() { let _ = opt.unwrap_or_else(|| ext_str.return_some_field()); let _ = opt.or_else(some_call); let _ = opt.or_else(|| some_call()); - let _: Result<u32, u32> = opt.ok_or_else(|| some_call()); - let _: Result<u32, u32> = opt.ok_or_else(some_call); + let _: Result<usize, usize> = opt.ok_or_else(|| some_call()); + let _: Result<usize, usize> = opt.ok_or_else(some_call); let _ = deep.0.get_or_insert_with(|| some_call()); let _ = deep.0.or_else(some_call); let _ = deep.0.or_else(|| some_call()); // These are handled by bind_instead_of_map - let _: Option<u32> = None.or_else(|| Some(3)); + let _ = Some(10).and_then(|idx| Some(ext_arr[idx])); + let _ = Some(10).and_then(|idx| Some(idx)); + let _: Option<usize> = None.or_else(|| Some(3)); let _ = deep.0.or_else(|| Some(3)); let _ = opt.or_else(|| Some(3)); // Should lint - Result - let res: Result<u32, u32> = Err(5); - let res2: Result<u32, SomeStruct> = Err(SomeStruct { some_field: 5 }); + let res: Result<usize, usize> = Err(5); + let res2: Result<usize, SomeStruct> = Err(SomeStruct { some_field: 5 }); let _ = res2.unwrap_or(2); let _ = res2.unwrap_or(astronomers_pi); @@ -76,30 +81,31 @@ fn main() { // Should not lint - Result let _ = res.unwrap_or_else(|err| err); + let _ = res.unwrap_or_else(|err| ext_arr[err]); let _ = res2.unwrap_or_else(|err| err.some_field); let _ = res2.unwrap_or_else(|err| err.return_some_field()); let _ = res2.unwrap_or_else(|_| ext_str.return_some_field()); - let _: Result<u32, u32> = res.and_then(|x| Ok(x)); - let _: Result<u32, u32> = res.and_then(|x| Err(x)); + let _: Result<usize, usize> = res.and_then(|x| Ok(x)); + let _: Result<usize, usize> = res.and_then(|x| Err(x)); - let _: Result<u32, u32> = res.or_else(|err| Ok(err)); - let _: Result<u32, u32> = res.or_else(|err| Err(err)); + let _: Result<usize, usize> = res.or_else(|err| Ok(err)); + let _: Result<usize, usize> = res.or_else(|err| Err(err)); // These are handled by bind_instead_of_map - let _: Result<u32, u32> = res.and_then(|_| Ok(2)); - let _: Result<u32, u32> = res.and_then(|_| Ok(astronomers_pi)); - let _: Result<u32, u32> = res.and_then(|_| Ok(ext_str.some_field)); + let _: Result<usize, usize> = res.and_then(|_| Ok(2)); + let _: Result<usize, usize> = res.and_then(|_| Ok(astronomers_pi)); + let _: Result<usize, usize> = res.and_then(|_| Ok(ext_str.some_field)); - let _: Result<u32, u32> = res.and_then(|_| Err(2)); - let _: Result<u32, u32> = res.and_then(|_| Err(astronomers_pi)); - let _: Result<u32, u32> = res.and_then(|_| Err(ext_str.some_field)); + let _: Result<usize, usize> = res.and_then(|_| Err(2)); + let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi)); + let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field)); - let _: Result<u32, u32> = res.or_else(|_| Ok(2)); - let _: Result<u32, u32> = res.or_else(|_| Ok(astronomers_pi)); - let _: Result<u32, u32> = res.or_else(|_| Ok(ext_str.some_field)); + let _: Result<usize, usize> = res.or_else(|_| Ok(2)); + let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi)); + let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field)); - let _: Result<u32, u32> = res.or_else(|_| Err(2)); - let _: Result<u32, u32> = res.or_else(|_| Err(astronomers_pi)); - let _: Result<u32, u32> = res.or_else(|_| Err(ext_str.some_field)); + let _: Result<usize, usize> = res.or_else(|_| Err(2)); + let _: Result<usize, usize> = res.or_else(|_| Err(astronomers_pi)); + let _: Result<usize, usize> = res.or_else(|_| Err(ext_str.some_field)); } diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index 04b3c8ae1e2..dfc6d3ba573 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -3,15 +3,15 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] -struct Deep(Option<u32>); +struct Deep(Option<usize>); #[derive(Copy, Clone)] struct SomeStruct { - some_field: u32, + some_field: usize, } impl SomeStruct { - fn return_some_field(&self) -> u32 { + fn return_some_field(&self) -> usize { self.some_field } } @@ -22,6 +22,7 @@ fn some_call<T: Default>() -> T { fn main() { let astronomers_pi = 10; + let ext_arr: [usize; 1] = [2]; let ext_str = SomeStruct { some_field: 10 }; // Should lint - Option @@ -30,19 +31,21 @@ fn main() { let _ = opt.unwrap_or_else(|| 2); let _ = opt.unwrap_or_else(|| astronomers_pi); let _ = opt.unwrap_or_else(|| ext_str.some_field); + let _ = opt.unwrap_or_else(|| ext_arr[0]); let _ = opt.and_then(|_| ext_opt); let _ = opt.or_else(|| ext_opt); let _ = opt.or_else(|| None); let _ = opt.get_or_insert_with(|| 2); let _ = opt.ok_or_else(|| 2); + let _ = opt.ok_or_else(|| ext_arr[0]); // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or_else(|| 2); let _ = Some(10).and_then(|_| ext_opt); - let _: Option<u32> = None.or_else(|| ext_opt); + let _: Option<usize> = None.or_else(|| ext_opt); let _ = None.get_or_insert_with(|| 2); - let _: Result<u32, u32> = None.ok_or_else(|| 2); - let _: Option<u32> = None.or_else(|| None); + let _: Result<usize, usize> = None.ok_or_else(|| 2); + let _: Option<usize> = None.or_else(|| None); let mut deep = Deep(Some(42)); let _ = deep.0.unwrap_or_else(|| 2); @@ -55,20 +58,22 @@ fn main() { let _ = opt.unwrap_or_else(|| ext_str.return_some_field()); let _ = opt.or_else(some_call); let _ = opt.or_else(|| some_call()); - let _: Result<u32, u32> = opt.ok_or_else(|| some_call()); - let _: Result<u32, u32> = opt.ok_or_else(some_call); + let _: Result<usize, usize> = opt.ok_or_else(|| some_call()); + let _: Result<usize, usize> = opt.ok_or_else(some_call); let _ = deep.0.get_or_insert_with(|| some_call()); let _ = deep.0.or_else(some_call); let _ = deep.0.or_else(|| some_call()); // These are handled by bind_instead_of_map - let _: Option<u32> = None.or_else(|| Some(3)); + let _ = Some(10).and_then(|idx| Some(ext_arr[idx])); + let _ = Some(10).and_then(|idx| Some(idx)); + let _: Option<usize> = None.or_else(|| Some(3)); let _ = deep.0.or_else(|| Some(3)); let _ = opt.or_else(|| Some(3)); // Should lint - Result - let res: Result<u32, u32> = Err(5); - let res2: Result<u32, SomeStruct> = Err(SomeStruct { some_field: 5 }); + let res: Result<usize, usize> = Err(5); + let res2: Result<usize, SomeStruct> = Err(SomeStruct { some_field: 5 }); let _ = res2.unwrap_or_else(|_| 2); let _ = res2.unwrap_or_else(|_| astronomers_pi); @@ -76,30 +81,31 @@ fn main() { // Should not lint - Result let _ = res.unwrap_or_else(|err| err); + let _ = res.unwrap_or_else(|err| ext_arr[err]); let _ = res2.unwrap_or_else(|err| err.some_field); let _ = res2.unwrap_or_else(|err| err.return_some_field()); let _ = res2.unwrap_or_else(|_| ext_str.return_some_field()); - let _: Result<u32, u32> = res.and_then(|x| Ok(x)); - let _: Result<u32, u32> = res.and_then(|x| Err(x)); + let _: Result<usize, usize> = res.and_then(|x| Ok(x)); + let _: Result<usize, usize> = res.and_then(|x| Err(x)); - let _: Result<u32, u32> = res.or_else(|err| Ok(err)); - let _: Result<u32, u32> = res.or_else(|err| Err(err)); + let _: Result<usize, usize> = res.or_else(|err| Ok(err)); + let _: Result<usize, usize> = res.or_else(|err| Err(err)); // These are handled by bind_instead_of_map - let _: Result<u32, u32> = res.and_then(|_| Ok(2)); - let _: Result<u32, u32> = res.and_then(|_| Ok(astronomers_pi)); - let _: Result<u32, u32> = res.and_then(|_| Ok(ext_str.some_field)); + let _: Result<usize, usize> = res.and_then(|_| Ok(2)); + let _: Result<usize, usize> = res.and_then(|_| Ok(astronomers_pi)); + let _: Result<usize, usize> = res.and_then(|_| Ok(ext_str.some_field)); - let _: Result<u32, u32> = res.and_then(|_| Err(2)); - let _: Result<u32, u32> = res.and_then(|_| Err(astronomers_pi)); - let _: Result<u32, u32> = res.and_then(|_| Err(ext_str.some_field)); + let _: Result<usize, usize> = res.and_then(|_| Err(2)); + let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi)); + let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field)); - let _: Result<u32, u32> = res.or_else(|_| Ok(2)); - let _: Result<u32, u32> = res.or_else(|_| Ok(astronomers_pi)); - let _: Result<u32, u32> = res.or_else(|_| Ok(ext_str.some_field)); + let _: Result<usize, usize> = res.or_else(|_| Ok(2)); + let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi)); + let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field)); - let _: Result<u32, u32> = res.or_else(|_| Err(2)); - let _: Result<u32, u32> = res.or_else(|_| Err(astronomers_pi)); - let _: Result<u32, u32> = res.or_else(|_| Err(ext_str.some_field)); + let _: Result<usize, usize> = res.or_else(|_| Err(2)); + let _: Result<usize, usize> = res.or_else(|_| Err(astronomers_pi)); + let _: Result<usize, usize> = res.or_else(|_| Err(ext_str.some_field)); } diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr index b941bf84246..15591817540 100644 --- a/tests/ui/unnecessary_lazy_eval.stderr +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -1,5 +1,5 @@ error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:30:13 + --> $DIR/unnecessary_lazy_eval.rs:31:13 | LL | let _ = opt.unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(2)` @@ -7,43 +7,49 @@ LL | let _ = opt.unwrap_or_else(|| 2); = note: `-D clippy::unnecessary-lazy-evaluation` implied by `-D warnings` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:31:13 + --> $DIR/unnecessary_lazy_eval.rs:32:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:32:13 + --> $DIR/unnecessary_lazy_eval.rs:33:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:33:13 + --> $DIR/unnecessary_lazy_eval.rs:34:13 + | +LL | let _ = opt.unwrap_or_else(|| ext_arr[0]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(ext_arr[0])` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:35:13 | LL | let _ = opt.and_then(|_| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `opt.and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:34:13 + --> $DIR/unnecessary_lazy_eval.rs:36:13 | LL | let _ = opt.or_else(|| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `opt.or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:35:13 + --> $DIR/unnecessary_lazy_eval.rs:37:13 | LL | let _ = opt.or_else(|| None); | ^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `opt.or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:36:13 + --> $DIR/unnecessary_lazy_eval.rs:38:13 | LL | let _ = opt.get_or_insert_with(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `opt.get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:37:13 + --> $DIR/unnecessary_lazy_eval.rs:39:13 | LL | let _ = opt.ok_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `opt.ok_or(2)` @@ -51,83 +57,89 @@ LL | let _ = opt.ok_or_else(|| 2); error: unnecessary closure used to substitute value for `Option::None` --> $DIR/unnecessary_lazy_eval.rs:40:13 | +LL | let _ = opt.ok_or_else(|| ext_arr[0]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `opt.ok_or(ext_arr[0])` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:43:13 + | LL | let _ = Some(10).unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `Some(10).unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:41:13 + --> $DIR/unnecessary_lazy_eval.rs:44:13 | LL | let _ = Some(10).and_then(|_| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `Some(10).and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:42:26 + --> $DIR/unnecessary_lazy_eval.rs:45:28 | -LL | let _: Option<u32> = None.or_else(|| ext_opt); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(ext_opt)` +LL | let _: Option<usize> = None.or_else(|| ext_opt); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:43:13 + --> $DIR/unnecessary_lazy_eval.rs:46:13 | LL | let _ = None.get_or_insert_with(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `None.get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:44:31 + --> $DIR/unnecessary_lazy_eval.rs:47:35 | -LL | let _: Result<u32, u32> = None.ok_or_else(|| 2); - | ^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `None.ok_or(2)` +LL | let _: Result<usize, usize> = None.ok_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `None.ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:45:26 + --> $DIR/unnecessary_lazy_eval.rs:48:28 | -LL | let _: Option<u32> = None.or_else(|| None); - | ^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(None)` +LL | let _: Option<usize> = None.or_else(|| None); + | ^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:48:13 + --> $DIR/unnecessary_lazy_eval.rs:51:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `deep.0.unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:49:13 + --> $DIR/unnecessary_lazy_eval.rs:52:13 | LL | let _ = deep.0.and_then(|_| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `deep.0.and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:50:13 + --> $DIR/unnecessary_lazy_eval.rs:53:13 | LL | let _ = deep.0.or_else(|| None); | ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `deep.0.or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:51:13 + --> $DIR/unnecessary_lazy_eval.rs:54:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `deep.0.get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:52:13 + --> $DIR/unnecessary_lazy_eval.rs:55:13 | LL | let _ = deep.0.ok_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `deep.0.ok_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:73:13 + --> $DIR/unnecessary_lazy_eval.rs:78:13 | LL | let _ = res2.unwrap_or_else(|_| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:74:13 + --> $DIR/unnecessary_lazy_eval.rs:79:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:75:13 + --> $DIR/unnecessary_lazy_eval.rs:80:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(ext_str.some_field)` @@ -140,5 +152,5 @@ LL | #![warn(clippy::unnecessary_lazy_eval)] | = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` -error: aborting due to 23 previous errors +error: aborting due to 25 previous errors From d7220dbd9143422a5b3a1ebf4dd46b708f83f1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Mon, 15 Jun 2020 15:22:22 +0200 Subject: [PATCH 453/526] Run cargo dev update_lints --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 4 ++-- src/lintlist/mod.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54489751014..675dfd420a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1754,7 +1754,7 @@ Released 2018-09-13 [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold -[`unnecessary_lazy_eval`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_eval +[`unnecessary_lazy_evaluation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluation [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation [`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index cb29f71387b..ae7045884f7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -672,7 +672,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::OK_EXPECT, &methods::OPTION_AS_REF_DEREF, &methods::OPTION_MAP_OR_NONE, - &methods::UNNECESSARY_LAZY_EVALUATION, &methods::OR_FUN_CALL, &methods::RESULT_MAP_OR_INTO_OPTION, &methods::SEARCH_IS_SOME, @@ -686,6 +685,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::UNINIT_ASSUMED_INIT, &methods::UNNECESSARY_FILTER_MAP, &methods::UNNECESSARY_FOLD, + &methods::UNNECESSARY_LAZY_EVALUATION, &methods::UNWRAP_USED, &methods::USELESS_ASREF, &methods::WRONG_PUB_SELF_CONVENTION, @@ -1542,6 +1542,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::SINGLE_CHAR_PUSH_STR), LintId::of(&methods::STRING_EXTEND_CHARS), LintId::of(&methods::UNNECESSARY_FOLD), + LintId::of(&methods::UNNECESSARY_LAZY_EVALUATION), LintId::of(&methods::WRONG_SELF_CONVENTION), LintId::of(&misc::TOPLEVEL_REF_ARG), LintId::of(&misc::ZERO_PTR), @@ -1612,7 +1613,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::FILTER_NEXT), LintId::of(&methods::FLAT_MAP_IDENTITY), LintId::of(&methods::OPTION_AS_REF_DEREF), - LintId::of(&methods::UNNECESSARY_LAZY_EVALUATION), LintId::of(&methods::SEARCH_IS_SOME), LintId::of(&methods::SKIP_WHILE_NEXT), LintId::of(&methods::SUSPICIOUS_MAP), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 1e76163f946..2a66d3495ed 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2384,7 +2384,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ module: "methods", }, Lint { - name: "unnecessary_lazy_eval", + name: "unnecessary_lazy_evaluation", group: "style", desc: "using unnecessary lazy evaluation, which can be replaced with simpler eager evaluation", deprecation: None, From 75637c1edac6db37b3c8aa17ef6b5a91db699a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Mon, 15 Jun 2020 20:01:18 +0200 Subject: [PATCH 454/526] Catch function calls in argument lists, add tests that tuples don't get linted --- clippy_lints/src/methods/mod.rs | 25 ++++++++------ tests/ui/unnecessary_lazy_eval.fixed | 8 ++++- tests/ui/unnecessary_lazy_eval.rs | 8 ++++- tests/ui/unnecessary_lazy_eval.stderr | 48 +++++++++++++-------------- 4 files changed, 52 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index ed8eaba75d1..463ef48f62c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2744,12 +2744,8 @@ fn lint_lazy_eval<'a, 'tcx>( paths.iter().any(|candidate| match_qpath(path, candidate)) } - if let hir::ExprKind::Closure(_, _, eid, _, _) = args[1].kind { - let body = cx.tcx.hir().body(eid); - let ex = &body.value; - let params = &body.params; - - let simplify = match ex.kind { + fn can_simplify(expr: &hir::Expr<'_>, params: &[hir::Param<'_>], variant_calls: bool) -> bool { + match expr.kind { // Closures returning literals can be unconditionally simplified hir::ExprKind::Lit(_) => true, @@ -2767,15 +2763,16 @@ fn lint_lazy_eval<'a, 'tcx>( hir::ExprKind::Field(ref object, _) => !expr_uses_argument(object, params), // Paths can be simplified if the root is not the argument, this also covers None - hir::ExprKind::Path(_) => !expr_uses_argument(ex, params), + hir::ExprKind::Path(_) => !expr_uses_argument(expr, params), // Calls to Some, Ok, Err can be considered literals if they don't derive an argument hir::ExprKind::Call(ref func, ref args) => if_chain! { - if allow_variant_calls; // Disable lint when rules conflict with bind_instead_of_map + if variant_calls; // Disable lint when rules conflict with bind_instead_of_map if let hir::ExprKind::Path(ref path) = func.kind; if match_any_qpath(path, &[&["Some"], &["Ok"], &["Err"]]); then { - !args.iter().any(|arg| expr_uses_argument(arg, params)) + // Recursively check all arguments + args.iter().all(|arg| can_simplify(arg, params, variant_calls)) } else { false } @@ -2784,9 +2781,15 @@ fn lint_lazy_eval<'a, 'tcx>( // For anything more complex than the above, a closure is probably the right solution, // or the case is handled by an other lint _ => false, - }; + } + } - if simplify { + if let hir::ExprKind::Closure(_, _, eid, _, _) = args[1].kind { + let body = cx.tcx.hir().body(eid); + let ex = &body.value; + let params = &body.params; + + if can_simplify(ex, params, allow_variant_calls) { let msg = if is_option { "unnecessary closure used to substitute value for `Option::None`" } else { diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index c806cf8dce4..7f9d90a8569 100644 --- a/tests/ui/unnecessary_lazy_eval.fixed +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -25,9 +25,12 @@ fn main() { let ext_arr: [usize; 1] = [2]; let ext_str = SomeStruct { some_field: 10 }; - // Should lint - Option let mut opt = Some(42); let ext_opt = Some(42); + let nested_opt = Some(Some(42)); + let nested_tuple_opt = Some(Some((42, 43))); + + // Should lint - Option let _ = opt.unwrap_or(2); let _ = opt.unwrap_or(astronomers_pi); let _ = opt.unwrap_or(ext_str.some_field); @@ -56,6 +59,9 @@ fn main() { // Should not lint - Option let _ = opt.unwrap_or_else(|| ext_str.return_some_field()); + let _ = nested_opt.unwrap_or_else(|| Some(some_call())); + let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); + let _ = nested_tuple_opt.unwrap_or_else(|| Some((some_call(), some_call()))); let _ = opt.or_else(some_call); let _ = opt.or_else(|| some_call()); let _: Result<usize, usize> = opt.ok_or_else(|| some_call()); diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index dfc6d3ba573..ca8238d6dcf 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -25,9 +25,12 @@ fn main() { let ext_arr: [usize; 1] = [2]; let ext_str = SomeStruct { some_field: 10 }; - // Should lint - Option let mut opt = Some(42); let ext_opt = Some(42); + let nested_opt = Some(Some(42)); + let nested_tuple_opt = Some(Some((42, 43))); + + // Should lint - Option let _ = opt.unwrap_or_else(|| 2); let _ = opt.unwrap_or_else(|| astronomers_pi); let _ = opt.unwrap_or_else(|| ext_str.some_field); @@ -56,6 +59,9 @@ fn main() { // Should not lint - Option let _ = opt.unwrap_or_else(|| ext_str.return_some_field()); + let _ = nested_opt.unwrap_or_else(|| Some(some_call())); + let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); + let _ = nested_tuple_opt.unwrap_or_else(|| Some((some_call(), some_call()))); let _ = opt.or_else(some_call); let _ = opt.or_else(|| some_call()); let _: Result<usize, usize> = opt.ok_or_else(|| some_call()); diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr index 15591817540..b8ec654e5c7 100644 --- a/tests/ui/unnecessary_lazy_eval.stderr +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -1,5 +1,5 @@ error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:31:13 + --> $DIR/unnecessary_lazy_eval.rs:34:13 | LL | let _ = opt.unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(2)` @@ -7,139 +7,139 @@ LL | let _ = opt.unwrap_or_else(|| 2); = note: `-D clippy::unnecessary-lazy-evaluation` implied by `-D warnings` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:32:13 + --> $DIR/unnecessary_lazy_eval.rs:35:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:33:13 + --> $DIR/unnecessary_lazy_eval.rs:36:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:34:13 + --> $DIR/unnecessary_lazy_eval.rs:37:13 | LL | let _ = opt.unwrap_or_else(|| ext_arr[0]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(ext_arr[0])` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:35:13 + --> $DIR/unnecessary_lazy_eval.rs:38:13 | LL | let _ = opt.and_then(|_| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `opt.and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:36:13 + --> $DIR/unnecessary_lazy_eval.rs:39:13 | LL | let _ = opt.or_else(|| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `opt.or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:37:13 + --> $DIR/unnecessary_lazy_eval.rs:40:13 | LL | let _ = opt.or_else(|| None); | ^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `opt.or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:38:13 + --> $DIR/unnecessary_lazy_eval.rs:41:13 | LL | let _ = opt.get_or_insert_with(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `opt.get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:39:13 + --> $DIR/unnecessary_lazy_eval.rs:42:13 | LL | let _ = opt.ok_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `opt.ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:40:13 + --> $DIR/unnecessary_lazy_eval.rs:43:13 | LL | let _ = opt.ok_or_else(|| ext_arr[0]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `opt.ok_or(ext_arr[0])` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:43:13 + --> $DIR/unnecessary_lazy_eval.rs:46:13 | LL | let _ = Some(10).unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `Some(10).unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:44:13 + --> $DIR/unnecessary_lazy_eval.rs:47:13 | LL | let _ = Some(10).and_then(|_| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `Some(10).and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:45:28 + --> $DIR/unnecessary_lazy_eval.rs:48:28 | LL | let _: Option<usize> = None.or_else(|| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:46:13 + --> $DIR/unnecessary_lazy_eval.rs:49:13 | LL | let _ = None.get_or_insert_with(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `None.get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:47:35 + --> $DIR/unnecessary_lazy_eval.rs:50:35 | LL | let _: Result<usize, usize> = None.ok_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `None.ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:48:28 + --> $DIR/unnecessary_lazy_eval.rs:51:28 | LL | let _: Option<usize> = None.or_else(|| None); | ^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:51:13 + --> $DIR/unnecessary_lazy_eval.rs:54:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `deep.0.unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:52:13 + --> $DIR/unnecessary_lazy_eval.rs:55:13 | LL | let _ = deep.0.and_then(|_| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `deep.0.and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:53:13 + --> $DIR/unnecessary_lazy_eval.rs:56:13 | LL | let _ = deep.0.or_else(|| None); | ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `deep.0.or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:54:13 + --> $DIR/unnecessary_lazy_eval.rs:57:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `deep.0.get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:55:13 + --> $DIR/unnecessary_lazy_eval.rs:58:13 | LL | let _ = deep.0.ok_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `deep.0.ok_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:78:13 + --> $DIR/unnecessary_lazy_eval.rs:84:13 | LL | let _ = res2.unwrap_or_else(|_| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:79:13 + --> $DIR/unnecessary_lazy_eval.rs:85:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:80:13 + --> $DIR/unnecessary_lazy_eval.rs:86:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(ext_str.some_field)` From a7083eea1c8821ff187218f55a1ac17b0f2c0fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Sun, 26 Jul 2020 20:18:12 +0200 Subject: [PATCH 455/526] Removed the extra lifetime parameter --- clippy_lints/src/methods/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 463ef48f62c..6693c358a02 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2710,8 +2710,8 @@ fn lint_map_flatten<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map /// lint use of `<fn>_else(simple closure)` for `Option`s and `Result`s that can be /// replaced with `<fn>(return value of simple closure)` -fn lint_lazy_eval<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_lazy_eval<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, args: &'tcx [hir::Expr<'_>], allow_variant_calls: bool, From 94cf90e5a56bbd9adbf6d6181d046ede9b96a7d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Sun, 26 Jul 2020 20:52:00 +0200 Subject: [PATCH 456/526] Apply suggested change Co-authored-by: Philipp Krones <hello@philkrones.com> --- clippy_lints/src/methods/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 6693c358a02..4578c228107 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2717,8 +2717,8 @@ fn lint_lazy_eval<'tcx>( allow_variant_calls: bool, simplify_using: &str, ) { - let is_option = is_type_diagnostic_item(cx, cx.tables.expr_ty(&args[0]), sym!(option_type)); - let is_result = is_type_diagnostic_item(cx, cx.tables.expr_ty(&args[0]), sym!(result_type)); + let is_option = is_type_diagnostic_item(cx, cx.tables().expr_ty(&args[0]), sym!(option_type)); + let is_result = is_type_diagnostic_item(cx, cx.tables().expr_ty(&args[0]), sym!(result_type)); if !is_option && !is_result { return; From 9c41822d34c69dbfded4d9d8b4b8962564be80f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Sun, 26 Jul 2020 21:08:07 +0200 Subject: [PATCH 457/526] Apply suggested change Co-authored-by: Philipp Krones <hello@philkrones.com> --- clippy_lints/src/methods/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 4578c228107..70a6b1f5021 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2717,8 +2717,8 @@ fn lint_lazy_eval<'tcx>( allow_variant_calls: bool, simplify_using: &str, ) { - let is_option = is_type_diagnostic_item(cx, cx.tables().expr_ty(&args[0]), sym!(option_type)); - let is_result = is_type_diagnostic_item(cx, cx.tables().expr_ty(&args[0]), sym!(result_type)); + let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym!(option_type)); + let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym!(result_type)); if !is_option && !is_result { return; From d8f0a14da1b79f409bb9fb4493dc001986a72ae0 Mon Sep 17 00:00:00 2001 From: Hactar <6060305+HactarCE@users.noreply.github.com> Date: Sun, 16 Aug 2020 14:43:34 -0400 Subject: [PATCH 458/526] Fix typo in description of unnecessary_mut_passed --- clippy_lints/src/mut_reference.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index be3ae7ab380..c506440ed79 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -9,8 +9,8 @@ declare_clippy_lint! { /// **What it does:** Detects passing a mutable reference to a function that only /// requires an immutable reference. /// - /// **Why is this bad?** The immutable reference rules out all other references - /// to the value. Also the code misleads about the intent of the call site. + /// **Why is this bad?** The mutable reference rules out all other references to + /// the value. Also the code misleads about the intent of the call site. /// /// **Known problems:** None. /// From d71b418ac511ee604af9320e401a7ff3fd115482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Sun, 16 Aug 2020 20:47:50 +0200 Subject: [PATCH 459/526] Moved to submodule, don't trigger if map_unwrap_or does --- clippy_lints/src/methods/mod.rs | 136 +++--------------- .../src/methods/unnecessary_lazy_eval.rs | 113 +++++++++++++++ 2 files changed, 132 insertions(+), 117 deletions(-) create mode 100644 clippy_lints/src/methods/unnecessary_lazy_eval.rs diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 70a6b1f5021..bfc89a74742 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3,6 +3,7 @@ mod inefficient_to_string; mod manual_saturating_arithmetic; mod option_map_unwrap_or; mod unnecessary_filter_map; +mod unnecessary_lazy_eval; use std::borrow::Cow; use std::fmt; @@ -1436,17 +1437,18 @@ impl<'tcx> LateLintPass<'tcx> for Methods { ["expect", ..] => lint_expect(cx, expr, arg_lists[0]), ["unwrap_or", "map"] => option_map_unwrap_or::lint(cx, expr, arg_lists[1], arg_lists[0], method_spans[1]), ["unwrap_or_else", "map"] => { - lint_lazy_eval(cx, expr, arg_lists[0], true, "unwrap_or"); - lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0]); + if !lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0]) { + unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], true, "unwrap_or"); + } }, ["map_or", ..] => lint_map_or_none(cx, expr, arg_lists[0]), ["and_then", ..] => { - lint_lazy_eval(cx, expr, arg_lists[0], false, "and"); + unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], false, "and"); bind_instead_of_map::OptionAndThenSome::lint(cx, expr, arg_lists[0]); bind_instead_of_map::ResultAndThenOk::lint(cx, expr, arg_lists[0]); }, ["or_else", ..] => { - lint_lazy_eval(cx, expr, arg_lists[0], false, "or"); + unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], false, "or"); bind_instead_of_map::ResultOrElseErrInfo::lint(cx, expr, arg_lists[0]); }, ["next", "filter"] => lint_filter_next(cx, expr, arg_lists[1]), @@ -1490,9 +1492,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods { ["is_file", ..] => lint_filetype_is_file(cx, expr, arg_lists[0]), ["map", "as_ref"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], false), ["map", "as_mut"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], true), - ["unwrap_or_else", ..] => lint_lazy_eval(cx, expr, arg_lists[0], true, "unwrap_or"), - ["get_or_insert_with", ..] => lint_lazy_eval(cx, expr, arg_lists[0], true, "get_or_insert"), - ["ok_or_else", ..] => lint_lazy_eval(cx, expr, arg_lists[0], true, "ok_or"), + ["unwrap_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], true, "unwrap_or"), + ["get_or_insert_with", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], true, "get_or_insert"), + ["ok_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], true, "ok_or"), _ => {}, } @@ -2708,119 +2710,13 @@ fn lint_map_flatten<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map } } -/// lint use of `<fn>_else(simple closure)` for `Option`s and `Result`s that can be -/// replaced with `<fn>(return value of simple closure)` -fn lint_lazy_eval<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - args: &'tcx [hir::Expr<'_>], - allow_variant_calls: bool, - simplify_using: &str, -) { - let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym!(option_type)); - let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym!(result_type)); - - if !is_option && !is_result { - return; - } - - // Return true if the expression is an accessor of any of the arguments - fn expr_uses_argument(expr: &hir::Expr<'_>, params: &[hir::Param<'_>]) -> bool { - params.iter().any(|arg| { - if_chain! { - if let hir::PatKind::Binding(_, _, ident, _) = arg.pat.kind; - if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.kind; - if let [p, ..] = path.segments; - then { - ident.name == p.ident.name - } else { - false - } - } - }) - } - - fn match_any_qpath(path: &hir::QPath<'_>, paths: &[&[&str]]) -> bool { - paths.iter().any(|candidate| match_qpath(path, candidate)) - } - - fn can_simplify(expr: &hir::Expr<'_>, params: &[hir::Param<'_>], variant_calls: bool) -> bool { - match expr.kind { - // Closures returning literals can be unconditionally simplified - hir::ExprKind::Lit(_) => true, - - hir::ExprKind::Index(ref object, ref index) => { - // arguments are not being indexed into - if !expr_uses_argument(object, params) { - // arguments are not used as index - !expr_uses_argument(index, params) - } else { - false - } - }, - - // Reading fields can be simplified if the object is not an argument of the closure - hir::ExprKind::Field(ref object, _) => !expr_uses_argument(object, params), - - // Paths can be simplified if the root is not the argument, this also covers None - hir::ExprKind::Path(_) => !expr_uses_argument(expr, params), - - // Calls to Some, Ok, Err can be considered literals if they don't derive an argument - hir::ExprKind::Call(ref func, ref args) => if_chain! { - if variant_calls; // Disable lint when rules conflict with bind_instead_of_map - if let hir::ExprKind::Path(ref path) = func.kind; - if match_any_qpath(path, &[&["Some"], &["Ok"], &["Err"]]); - then { - // Recursively check all arguments - args.iter().all(|arg| can_simplify(arg, params, variant_calls)) - } else { - false - } - }, - - // For anything more complex than the above, a closure is probably the right solution, - // or the case is handled by an other lint - _ => false, - } - } - - if let hir::ExprKind::Closure(_, _, eid, _, _) = args[1].kind { - let body = cx.tcx.hir().body(eid); - let ex = &body.value; - let params = &body.params; - - if can_simplify(ex, params, allow_variant_calls) { - let msg = if is_option { - "unnecessary closure used to substitute value for `Option::None`" - } else { - "unnecessary closure used to substitute value for `Result::Err`" - }; - - span_lint_and_sugg( - cx, - UNNECESSARY_LAZY_EVALUATION, - expr.span, - msg, - &format!("Use `{}` instead", simplify_using), - format!( - "{0}.{1}({2})", - snippet(cx, args[0].span, ".."), - simplify_using, - snippet(cx, ex.span, ".."), - ), - Applicability::MachineApplicable, - ); - } - } -} - /// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s fn lint_map_unwrap_or_else<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map_args: &'tcx [hir::Expr<'_>], unwrap_args: &'tcx [hir::Expr<'_>], -) { +) -> bool { // lint if the caller of `map()` is an `Option` let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym!(option_type)); let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym!(result_type)); @@ -2832,10 +2728,10 @@ fn lint_map_unwrap_or_else<'tcx>( let unwrap_mutated_vars = mutated_variables(&unwrap_args[1], cx); if let (Some(map_mutated_vars), Some(unwrap_mutated_vars)) = (map_mutated_vars, unwrap_mutated_vars) { if map_mutated_vars.intersection(&unwrap_mutated_vars).next().is_some() { - return; + return false; } } else { - return; + return false; } // lint message @@ -2865,9 +2761,15 @@ fn lint_map_unwrap_or_else<'tcx>( map_snippet, unwrap_snippet, ), ); + true } else if same_span && multiline { span_lint(cx, MAP_UNWRAP_OR, expr.span, msg); - }; + true + } else { + false + } + } else { + false } } diff --git a/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs new file mode 100644 index 00000000000..0dbedc4919c --- /dev/null +++ b/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -0,0 +1,113 @@ +use crate::utils::{match_qpath, span_lint_and_sugg, snippet, is_type_diagnostic_item}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; + +use super::UNNECESSARY_LAZY_EVALUATION; + +/// lint use of `<fn>_else(simple closure)` for `Option`s and `Result`s that can be +/// replaced with `<fn>(return value of simple closure)` +pub(super) fn lint<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + args: &'tcx [hir::Expr<'_>], + allow_variant_calls: bool, + simplify_using: &str, +) { + let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym!(option_type)); + let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym!(result_type)); + + if !is_option && !is_result { + return; + } + + // Return true if the expression is an accessor of any of the arguments + fn expr_uses_argument(expr: &hir::Expr<'_>, params: &[hir::Param<'_>]) -> bool { + params.iter().any(|arg| { + if_chain! { + if let hir::PatKind::Binding(_, _, ident, _) = arg.pat.kind; + if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.kind; + if let [p, ..] = path.segments; + then { + ident.name == p.ident.name + } else { + false + } + } + }) + } + + fn match_any_qpath(path: &hir::QPath<'_>, paths: &[&[&str]]) -> bool { + paths.iter().any(|candidate| match_qpath(path, candidate)) + } + + fn can_simplify(expr: &hir::Expr<'_>, params: &[hir::Param<'_>], variant_calls: bool) -> bool { + match expr.kind { + // Closures returning literals can be unconditionally simplified + hir::ExprKind::Lit(_) => true, + + hir::ExprKind::Index(ref object, ref index) => { + // arguments are not being indexed into + if !expr_uses_argument(object, params) { + // arguments are not used as index + !expr_uses_argument(index, params) + } else { + false + } + }, + + // Reading fields can be simplified if the object is not an argument of the closure + hir::ExprKind::Field(ref object, _) => !expr_uses_argument(object, params), + + // Paths can be simplified if the root is not the argument, this also covers None + hir::ExprKind::Path(_) => !expr_uses_argument(expr, params), + + // Calls to Some, Ok, Err can be considered literals if they don't derive an argument + hir::ExprKind::Call(ref func, ref args) => if_chain! { + if variant_calls; // Disable lint when rules conflict with bind_instead_of_map + if let hir::ExprKind::Path(ref path) = func.kind; + if match_any_qpath(path, &[&["Some"], &["Ok"], &["Err"]]); + then { + // Recursively check all arguments + args.iter().all(|arg| can_simplify(arg, params, variant_calls)) + } else { + false + } + }, + + // For anything more complex than the above, a closure is probably the right solution, + // or the case is handled by an other lint + _ => false, + } + } + + if let hir::ExprKind::Closure(_, _, eid, _, _) = args[1].kind { + let body = cx.tcx.hir().body(eid); + let ex = &body.value; + let params = &body.params; + + if can_simplify(ex, params, allow_variant_calls) { + let msg = if is_option { + "unnecessary closure used to substitute value for `Option::None`" + } else { + "unnecessary closure used to substitute value for `Result::Err`" + }; + + span_lint_and_sugg( + cx, + UNNECESSARY_LAZY_EVALUATION, + expr.span, + msg, + &format!("Use `{}` instead", simplify_using), + format!( + "{0}.{1}({2})", + snippet(cx, args[0].span, ".."), + simplify_using, + snippet(cx, ex.span, ".."), + ), + Applicability::MachineApplicable, + ); + } + } +} From 8a14c115369f163e7f96544df48b26376a06a3fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Sun, 16 Aug 2020 20:50:30 +0200 Subject: [PATCH 460/526] Cleanup, explain return value --- clippy_lints/src/methods/mod.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index bfc89a74742..c2b2cb98012 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2711,6 +2711,7 @@ fn lint_map_flatten<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map } /// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s +/// Return true if lint triggered fn lint_map_unwrap_or_else<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, @@ -2761,16 +2762,14 @@ fn lint_map_unwrap_or_else<'tcx>( map_snippet, unwrap_snippet, ), ); - true + return true; } else if same_span && multiline { span_lint(cx, MAP_UNWRAP_OR, expr.span, msg); - true - } else { - false + return true; } - } else { - false } + + false } /// lint use of `_.map_or(None, _)` for `Option`s and `Result`s From 3b52d7f780f2023d6596fe73c0a71f663b26bc33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Sun, 16 Aug 2020 20:51:16 +0200 Subject: [PATCH 461/526] run cargo dev fmt --- clippy_lints/src/methods/unnecessary_lazy_eval.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs index 0dbedc4919c..b44089f7bfc 100644 --- a/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -1,4 +1,4 @@ -use crate::utils::{match_qpath, span_lint_and_sugg, snippet, is_type_diagnostic_item}; +use crate::utils::{is_type_diagnostic_item, match_qpath, snippet, span_lint_and_sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; From b7ee8685ac83e0f3f32ac5ab5d597d5451d07057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Sun, 16 Aug 2020 21:04:02 +0200 Subject: [PATCH 462/526] Fix dogfooding test errors --- .../src/methods/unnecessary_lazy_eval.rs | 172 +++++++++--------- 1 file changed, 85 insertions(+), 87 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs index b44089f7bfc..a3e7e9971f8 100644 --- a/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -6,6 +6,66 @@ use rustc_lint::LateContext; use super::UNNECESSARY_LAZY_EVALUATION; +// Return true if the expression is an accessor of any of the arguments +fn expr_uses_argument(expr: &hir::Expr<'_>, params: &[hir::Param<'_>]) -> bool { + params.iter().any(|arg| { + if_chain! { + if let hir::PatKind::Binding(_, _, ident, _) = arg.pat.kind; + if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.kind; + if let [p, ..] = path.segments; + then { + ident.name == p.ident.name + } else { + false + } + } + }) +} + +fn match_any_qpath(path: &hir::QPath<'_>, paths: &[&[&str]]) -> bool { + paths.iter().any(|candidate| match_qpath(path, candidate)) +} + +fn can_simplify(expr: &hir::Expr<'_>, params: &[hir::Param<'_>], variant_calls: bool) -> bool { + match expr.kind { + // Closures returning literals can be unconditionally simplified + hir::ExprKind::Lit(_) => true, + + hir::ExprKind::Index(ref object, ref index) => { + // arguments are not being indexed into + if expr_uses_argument(object, params) { + false + } else { + // arguments are not used as index + !expr_uses_argument(index, params) + } + }, + + // Reading fields can be simplified if the object is not an argument of the closure + hir::ExprKind::Field(ref object, _) => !expr_uses_argument(object, params), + + // Paths can be simplified if the root is not the argument, this also covers None + hir::ExprKind::Path(_) => !expr_uses_argument(expr, params), + + // Calls to Some, Ok, Err can be considered literals if they don't derive an argument + hir::ExprKind::Call(ref func, ref args) => if_chain! { + if variant_calls; // Disable lint when rules conflict with bind_instead_of_map + if let hir::ExprKind::Path(ref path) = func.kind; + if match_any_qpath(path, &[&["Some"], &["Ok"], &["Err"]]); + then { + // Recursively check all arguments + args.iter().all(|arg| can_simplify(arg, params, variant_calls)) + } else { + false + } + }, + + // For anything more complex than the above, a closure is probably the right solution, + // or the case is handled by an other lint + _ => false, + } +} + /// lint use of `<fn>_else(simple closure)` for `Option`s and `Result`s that can be /// replaced with `<fn>(return value of simple closure)` pub(super) fn lint<'tcx>( @@ -18,96 +78,34 @@ pub(super) fn lint<'tcx>( let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym!(option_type)); let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym!(result_type)); - if !is_option && !is_result { - return; - } + if is_option || is_result { + if let hir::ExprKind::Closure(_, _, eid, _, _) = args[1].kind { + let body = cx.tcx.hir().body(eid); + let ex = &body.value; + let params = &body.params; - // Return true if the expression is an accessor of any of the arguments - fn expr_uses_argument(expr: &hir::Expr<'_>, params: &[hir::Param<'_>]) -> bool { - params.iter().any(|arg| { - if_chain! { - if let hir::PatKind::Binding(_, _, ident, _) = arg.pat.kind; - if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.kind; - if let [p, ..] = path.segments; - then { - ident.name == p.ident.name + if can_simplify(ex, params, allow_variant_calls) { + let msg = if is_option { + "unnecessary closure used to substitute value for `Option::None`" } else { - false - } + "unnecessary closure used to substitute value for `Result::Err`" + }; + + span_lint_and_sugg( + cx, + UNNECESSARY_LAZY_EVALUATION, + expr.span, + msg, + &format!("Use `{}` instead", simplify_using), + format!( + "{0}.{1}({2})", + snippet(cx, args[0].span, ".."), + simplify_using, + snippet(cx, ex.span, ".."), + ), + Applicability::MachineApplicable, + ); } - }) - } - - fn match_any_qpath(path: &hir::QPath<'_>, paths: &[&[&str]]) -> bool { - paths.iter().any(|candidate| match_qpath(path, candidate)) - } - - fn can_simplify(expr: &hir::Expr<'_>, params: &[hir::Param<'_>], variant_calls: bool) -> bool { - match expr.kind { - // Closures returning literals can be unconditionally simplified - hir::ExprKind::Lit(_) => true, - - hir::ExprKind::Index(ref object, ref index) => { - // arguments are not being indexed into - if !expr_uses_argument(object, params) { - // arguments are not used as index - !expr_uses_argument(index, params) - } else { - false - } - }, - - // Reading fields can be simplified if the object is not an argument of the closure - hir::ExprKind::Field(ref object, _) => !expr_uses_argument(object, params), - - // Paths can be simplified if the root is not the argument, this also covers None - hir::ExprKind::Path(_) => !expr_uses_argument(expr, params), - - // Calls to Some, Ok, Err can be considered literals if they don't derive an argument - hir::ExprKind::Call(ref func, ref args) => if_chain! { - if variant_calls; // Disable lint when rules conflict with bind_instead_of_map - if let hir::ExprKind::Path(ref path) = func.kind; - if match_any_qpath(path, &[&["Some"], &["Ok"], &["Err"]]); - then { - // Recursively check all arguments - args.iter().all(|arg| can_simplify(arg, params, variant_calls)) - } else { - false - } - }, - - // For anything more complex than the above, a closure is probably the right solution, - // or the case is handled by an other lint - _ => false, - } - } - - if let hir::ExprKind::Closure(_, _, eid, _, _) = args[1].kind { - let body = cx.tcx.hir().body(eid); - let ex = &body.value; - let params = &body.params; - - if can_simplify(ex, params, allow_variant_calls) { - let msg = if is_option { - "unnecessary closure used to substitute value for `Option::None`" - } else { - "unnecessary closure used to substitute value for `Result::Err`" - }; - - span_lint_and_sugg( - cx, - UNNECESSARY_LAZY_EVALUATION, - expr.span, - msg, - &format!("Use `{}` instead", simplify_using), - format!( - "{0}.{1}({2})", - snippet(cx, args[0].span, ".."), - simplify_using, - snippet(cx, ex.span, ".."), - ), - Applicability::MachineApplicable, - ); } } } From b175642a85f5d1507b35b8ef269ecbdaef9aa27d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Sun, 16 Aug 2020 21:33:29 +0200 Subject: [PATCH 463/526] Fix missed rename --- tests/ui/unnecessary_lazy_eval.rs | 2 +- tests/ui/unnecessary_lazy_eval.stderr | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index ca8238d6dcf..fd8f8ed0329 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::unnecessary_lazy_eval)] +#![warn(clippy::unnecessary_lazy_evaluation)] #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr index b8ec654e5c7..e86b7ed6253 100644 --- a/tests/ui/unnecessary_lazy_eval.stderr +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -144,13 +144,5 @@ error: unnecessary closure used to substitute value for `Result::Err` LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(ext_str.some_field)` -error: unknown clippy lint: clippy::unnecessary_lazy_eval - --> $DIR/unnecessary_lazy_eval.rs:2:9 - | -LL | #![warn(clippy::unnecessary_lazy_eval)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::unnecessary_lazy_evaluation` - | - = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` - -error: aborting due to 25 previous errors +error: aborting due to 24 previous errors From fc1e07e0c1803edb3ade2db2f46034cf227642c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= <bugadani@gmail.com> Date: Sun, 16 Aug 2020 22:16:39 +0200 Subject: [PATCH 464/526] Rename lint to use plural form --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 6 +++--- clippy_lints/src/methods/mod.rs | 4 ++-- clippy_lints/src/methods/unnecessary_lazy_eval.rs | 4 ++-- src/lintlist/mod.rs | 2 +- tests/ui/unnecessary_lazy_eval.fixed | 2 +- tests/ui/unnecessary_lazy_eval.rs | 2 +- tests/ui/unnecessary_lazy_eval.stderr | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 675dfd420a7..f662de122f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1754,7 +1754,7 @@ Released 2018-09-13 [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold -[`unnecessary_lazy_evaluation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluation +[`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation [`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ae7045884f7..17501e8e6da 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -685,7 +685,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::UNINIT_ASSUMED_INIT, &methods::UNNECESSARY_FILTER_MAP, &methods::UNNECESSARY_FOLD, - &methods::UNNECESSARY_LAZY_EVALUATION, + &methods::UNNECESSARY_LAZY_EVALUATIONS, &methods::UNWRAP_USED, &methods::USELESS_ASREF, &methods::WRONG_PUB_SELF_CONVENTION, @@ -1361,7 +1361,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::UNINIT_ASSUMED_INIT), LintId::of(&methods::UNNECESSARY_FILTER_MAP), LintId::of(&methods::UNNECESSARY_FOLD), - LintId::of(&methods::UNNECESSARY_LAZY_EVALUATION), + LintId::of(&methods::UNNECESSARY_LAZY_EVALUATIONS), LintId::of(&methods::USELESS_ASREF), LintId::of(&methods::WRONG_SELF_CONVENTION), LintId::of(&methods::ZST_OFFSET), @@ -1542,7 +1542,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::SINGLE_CHAR_PUSH_STR), LintId::of(&methods::STRING_EXTEND_CHARS), LintId::of(&methods::UNNECESSARY_FOLD), - LintId::of(&methods::UNNECESSARY_LAZY_EVALUATION), + LintId::of(&methods::UNNECESSARY_LAZY_EVALUATIONS), LintId::of(&methods::WRONG_SELF_CONVENTION), LintId::of(&misc::TOPLEVEL_REF_ARG), LintId::of(&misc::ZERO_PTR), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index c2b2cb98012..0f50a4c813a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1361,7 +1361,7 @@ declare_clippy_lint! { /// /// opt.unwrap_or(42); /// ``` - pub UNNECESSARY_LAZY_EVALUATION, + pub UNNECESSARY_LAZY_EVALUATIONS, style, "using unnecessary lazy evaluation, which can be replaced with simpler eager evaluation" } @@ -1415,7 +1415,7 @@ declare_lint_pass!(Methods => [ ZST_OFFSET, FILETYPE_IS_FILE, OPTION_AS_REF_DEREF, - UNNECESSARY_LAZY_EVALUATION, + UNNECESSARY_LAZY_EVALUATIONS, ]); impl<'tcx> LateLintPass<'tcx> for Methods { diff --git a/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs index a3e7e9971f8..31517659c34 100644 --- a/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -4,7 +4,7 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use super::UNNECESSARY_LAZY_EVALUATION; +use super::UNNECESSARY_LAZY_EVALUATIONS; // Return true if the expression is an accessor of any of the arguments fn expr_uses_argument(expr: &hir::Expr<'_>, params: &[hir::Param<'_>]) -> bool { @@ -93,7 +93,7 @@ pub(super) fn lint<'tcx>( span_lint_and_sugg( cx, - UNNECESSARY_LAZY_EVALUATION, + UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, &format!("Use `{}` instead", simplify_using), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 2a66d3495ed..3229c8da507 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2384,7 +2384,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ module: "methods", }, Lint { - name: "unnecessary_lazy_evaluation", + name: "unnecessary_lazy_evaluations", group: "style", desc: "using unnecessary lazy evaluation, which can be replaced with simpler eager evaluation", deprecation: None, diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index 7f9d90a8569..fa66e68794e 100644 --- a/tests/ui/unnecessary_lazy_eval.fixed +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::unnecessary_lazy_evaluation)] +#![warn(clippy::unnecessary_lazy_evaluations)] #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index fd8f8ed0329..04f47d1aa29 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::unnecessary_lazy_evaluation)] +#![warn(clippy::unnecessary_lazy_evaluations)] #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr index e86b7ed6253..5c1b2eb1f14 100644 --- a/tests/ui/unnecessary_lazy_eval.stderr +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -4,7 +4,7 @@ error: unnecessary closure used to substitute value for `Option::None` LL | let _ = opt.unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(2)` | - = note: `-D clippy::unnecessary-lazy-evaluation` implied by `-D warnings` + = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` error: unnecessary closure used to substitute value for `Option::None` --> $DIR/unnecessary_lazy_eval.rs:35:13 From 6afa4ef60f973218c901d0f802d586fe6c43017d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com> Date: Sun, 16 Aug 2020 00:00:00 +0000 Subject: [PATCH 465/526] Introduce function for comparing expression values Introduce `eq_expr_value(cx, a, b)` as a shortcut for `SpanlessEq::new(cx).ignore_fn().eq_expr(cx, a, b)`. No functional changes intended. --- clippy_lints/src/assign_ops.rs | 14 +++++------ clippy_lints/src/booleans.rs | 10 ++++---- clippy_lints/src/copies.rs | 7 +++--- clippy_lints/src/double_comparison.rs | 5 ++-- clippy_lints/src/eq_op.rs | 4 ++-- clippy_lints/src/floating_point_arithmetic.rs | 24 ++++++++----------- clippy_lints/src/question_mark.rs | 6 ++--- clippy_lints/src/swap.rs | 14 +++++------ clippy_lints/src/utils/hir_utils.rs | 5 ++++ clippy_lints/src/utils/internal_lints.rs | 3 +-- clippy_lints/src/utils/mod.rs | 2 +- 11 files changed, 45 insertions(+), 49 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index dab1e96e282..b3185b88840 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -1,5 +1,5 @@ use crate::utils::{ - get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method, SpanlessEq, + eq_expr_value, get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method, }; use crate::utils::{higher, sugg}; use if_chain::if_chain; @@ -70,11 +70,11 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps { return; } // lhs op= l op r - if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, l) { + if eq_expr_value(cx, lhs, l) { lint_misrefactored_assign_op(cx, expr, *op, rhs, lhs, r); } // lhs op= l commutative_op r - if is_commutative(op.node) && SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, r) { + if is_commutative(op.node) && eq_expr_value(cx, lhs, r) { lint_misrefactored_assign_op(cx, expr, *op, rhs, lhs, l); } } @@ -161,14 +161,12 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps { if visitor.counter == 1 { // a = a op b - if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) { + if eq_expr_value(cx, assignee, l) { lint(assignee, r); } // a = b commutative_op a // Limited to primitive type as these ops are know to be commutative - if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) - && cx.typeck_results().expr_ty(assignee).is_primitive_ty() - { + if eq_expr_value(cx, assignee, r) && cx.typeck_results().expr_ty(assignee).is_primitive_ty() { match op.node { hir::BinOpKind::Add | hir::BinOpKind::Mul @@ -253,7 +251,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { type Map = Map<'tcx>; fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { - if SpanlessEq::new(self.cx).ignore_fn().eq_expr(self.assignee, expr) { + if eq_expr_value(self.cx, self.assignee, expr) { self.counter += 1; } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 18529f2113e..280a2c7fe67 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,6 +1,6 @@ use crate::utils::{ - get_trait_def_id, implements_trait, in_macro, is_type_diagnostic_item, paths, snippet_opt, span_lint_and_sugg, - span_lint_and_then, SpanlessEq, + eq_expr_value, get_trait_def_id, implements_trait, in_macro, is_type_diagnostic_item, paths, snippet_opt, + span_lint_and_sugg, span_lint_and_then, }; use if_chain::if_chain; use rustc_ast::ast::LitKind; @@ -128,7 +128,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { } } for (n, expr) in self.terminals.iter().enumerate() { - if SpanlessEq::new(self.cx).ignore_fn().eq_expr(e, expr) { + if eq_expr_value(self.cx, e, expr) { #[allow(clippy::cast_possible_truncation)] return Ok(Bool::Term(n as u8)); } @@ -138,8 +138,8 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { if implements_ord(self.cx, e_lhs); if let ExprKind::Binary(expr_binop, expr_lhs, expr_rhs) = &expr.kind; if negate(e_binop.node) == Some(expr_binop.node); - if SpanlessEq::new(self.cx).ignore_fn().eq_expr(e_lhs, expr_lhs); - if SpanlessEq::new(self.cx).ignore_fn().eq_expr(e_rhs, expr_rhs); + if eq_expr_value(self.cx, e_lhs, expr_lhs); + if eq_expr_value(self.cx, e_rhs, expr_rhs); then { #[allow(clippy::cast_possible_truncation)] return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 1f8bff8d71e..10a64769585 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,5 +1,5 @@ +use crate::utils::{eq_expr_value, SpanlessEq, SpanlessHash}; use crate::utils::{get_parent_expr, higher, if_sequence, snippet, span_lint_and_note, span_lint_and_then}; -use crate::utils::{SpanlessEq, SpanlessHash}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Arm, Block, Expr, ExprKind, MatchSource, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -197,8 +197,7 @@ fn lint_same_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) { h.finish() }; - let eq: &dyn Fn(&&Expr<'_>, &&Expr<'_>) -> bool = - &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) }; + let eq: &dyn Fn(&&Expr<'_>, &&Expr<'_>) -> bool = &|&lhs, &rhs| -> bool { eq_expr_value(cx, lhs, rhs) }; for (i, j) in search_same(conds, hash, eq) { span_lint_and_note( @@ -222,7 +221,7 @@ fn lint_same_fns_in_if_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) { let eq: &dyn Fn(&&Expr<'_>, &&Expr<'_>) -> bool = &|&lhs, &rhs| -> bool { // Do not spawn warning if `IFS_SAME_COND` already produced it. - if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) { + if eq_expr_value(cx, lhs, rhs) { return false; } SpanlessEq::new(cx).eq_expr(lhs, rhs) diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index bae7c4647d4..19f56195ec1 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -6,7 +6,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use crate::utils::{snippet_with_applicability, span_lint_and_sugg, SpanlessEq}; +use crate::utils::{eq_expr_value, snippet_with_applicability, span_lint_and_sugg}; declare_clippy_lint! { /// **What it does:** Checks for double comparisons that could be simplified to a single expression. @@ -46,8 +46,7 @@ impl<'tcx> DoubleComparisons { }, _ => return, }; - let mut spanless_eq = SpanlessEq::new(cx).ignore_fn(); - if !(spanless_eq.eq_expr(&llhs, &rlhs) && spanless_eq.eq_expr(&lrhs, &rrhs)) { + if !(eq_expr_value(cx, &llhs, &rlhs) && eq_expr_value(cx, &lrhs, &rrhs)) { return; } macro_rules! lint_double_comparison { diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 140cd21c34e..e16ec783fab 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -1,5 +1,5 @@ use crate::utils::{ - implements_trait, in_macro, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq, + eq_expr_value, implements_trait, in_macro, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, }; use rustc_errors::Applicability; use rustc_hir::{BinOp, BinOpKind, BorrowKind, Expr, ExprKind}; @@ -69,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { if macro_with_not_op(&left.kind) || macro_with_not_op(&right.kind) { return; } - if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) { + if is_valid_operator(op) && eq_expr_value(cx, left, right) { span_lint( cx, EQ_OP, diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 93f6ec92ec7..1b02cee126d 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -2,7 +2,7 @@ use crate::consts::{ constant, constant_simple, Constant, Constant::{Int, F32, F64}, }; -use crate::utils::{get_parent_expr, higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq}; +use crate::utils::{eq_expr_value, get_parent_expr, higher, numeric_literal, span_lint_and_sugg, sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp}; @@ -363,8 +363,8 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> { if_chain! { if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lmul_lhs, ref lmul_rhs) = add_lhs.kind; if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref rmul_lhs, ref rmul_rhs) = add_rhs.kind; - if are_exprs_equal(cx, lmul_lhs, lmul_rhs); - if are_exprs_equal(cx, rmul_lhs, rmul_rhs); + if eq_expr_value(cx, lmul_lhs, lmul_rhs); + if eq_expr_value(cx, rmul_lhs, rmul_rhs); then { return Some(format!("{}.hypot({})", Sugg::hir(cx, &lmul_lhs, ".."), Sugg::hir(cx, &rmul_lhs, ".."))); } @@ -502,8 +502,8 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { fn is_testing_positive(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { match op { - BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, right) && are_exprs_equal(cx, left, test), - BinOpKind::Lt | BinOpKind::Le => is_zero(cx, left) && are_exprs_equal(cx, right, test), + BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, right) && eq_expr_value(cx, left, test), + BinOpKind::Lt | BinOpKind::Le => is_zero(cx, left) && eq_expr_value(cx, right, test), _ => false, } } else { @@ -515,8 +515,8 @@ fn is_testing_positive(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) - fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { match op { - BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, left) && are_exprs_equal(cx, right, test), - BinOpKind::Lt | BinOpKind::Le => is_zero(cx, right) && are_exprs_equal(cx, left, test), + BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, left) && eq_expr_value(cx, right, test), + BinOpKind::Lt | BinOpKind::Le => is_zero(cx, right) && eq_expr_value(cx, left, test), _ => false, } } else { @@ -524,10 +524,6 @@ fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) - } } -fn are_exprs_equal(cx: &LateContext<'_>, expr1: &Expr<'_>, expr2: &Expr<'_>) -> bool { - SpanlessEq::new(cx).ignore_fn().eq_expr(expr1, expr2) -} - /// Returns true iff expr is some zero literal fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match constant_simple(cx, cx.typeck_results(), expr) { @@ -546,12 +542,12 @@ fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// returns None. fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>) -> Option<(bool, &'a Expr<'a>)> { if let ExprKind::Unary(UnOp::UnNeg, expr1_negated) = &expr1.kind { - if are_exprs_equal(cx, expr1_negated, expr2) { + if eq_expr_value(cx, expr1_negated, expr2) { return Some((false, expr2)); } } if let ExprKind::Unary(UnOp::UnNeg, expr2_negated) = &expr2.kind { - if are_exprs_equal(cx, expr1, expr2_negated) { + if eq_expr_value(cx, expr1, expr2_negated) { return Some((true, expr1)); } } @@ -614,7 +610,7 @@ fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_> args_a.len() == args_b.len() && ( ["ln", "log2", "log10"].contains(&&*method_name_a.as_str()) || - method_name_a.as_str() == "log" && args_a.len() == 2 && are_exprs_equal(cx, &args_a[1], &args_b[1]) + method_name_a.as_str() == "log" && args_a.len() == 2 && eq_expr_value(cx, &args_a[1], &args_b[1]) ); } } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index fb12c565afd..dbc676ae224 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -7,8 +7,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::sugg::Sugg; use crate::utils::{ - higher, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability, - span_lint_and_sugg, SpanlessEq, + eq_expr_value, higher, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability, + span_lint_and_sugg, }; declare_clippy_lint! { @@ -65,7 +65,7 @@ impl QuestionMark { if let ExprKind::Block(block, None) = &else_.kind; if block.stmts.is_empty(); if let Some(block_expr) = &block.expr; - if SpanlessEq::new(cx).ignore_fn().eq_expr(subject, block_expr); + if eq_expr_value(cx, subject, block_expr); then { replacement = Some(format!("Some({}?)", receiver_str)); } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 754f87e6b55..cc39f060fc7 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,7 +1,7 @@ use crate::utils::sugg::Sugg; use crate::utils::{ - differing_macro_contexts, is_type_diagnostic_item, snippet_with_applicability, span_lint_and_then, walk_ptrs_ty, - SpanlessEq, + differing_macro_contexts, eq_expr_value, is_type_diagnostic_item, snippet_with_applicability, span_lint_and_then, + walk_ptrs_ty, }; use if_chain::if_chain; use rustc_errors::Applicability; @@ -92,8 +92,8 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) { if rhs2.segments.len() == 1; if ident.as_str() == rhs2.segments[0].ident.as_str(); - if SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1); - if SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2); + if eq_expr_value(cx, tmp_init, lhs1); + if eq_expr_value(cx, rhs1, lhs2); then { if let ExprKind::Field(ref lhs1, _) = lhs1.kind { if let ExprKind::Field(ref lhs2, _) = lhs2.kind { @@ -193,7 +193,7 @@ enum Slice<'a> { fn check_for_slice<'a>(cx: &LateContext<'_>, lhs1: &'a Expr<'_>, lhs2: &'a Expr<'_>) -> Slice<'a> { if let ExprKind::Index(ref lhs1, ref idx1) = lhs1.kind { if let ExprKind::Index(ref lhs2, ref idx2) = lhs2.kind { - if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { + if eq_expr_value(cx, lhs1, lhs2) { let ty = walk_ptrs_ty(cx.typeck_results().expr_ty(lhs1)); if matches!(ty.kind, ty::Slice(_)) @@ -221,8 +221,8 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) { if !differing_macro_contexts(first.span, second.span); if let ExprKind::Assign(ref lhs0, ref rhs0, _) = first.kind; if let ExprKind::Assign(ref lhs1, ref rhs1, _) = second.kind; - if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1); - if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0); + if eq_expr_value(cx, lhs0, rhs1); + if eq_expr_value(cx, lhs1, rhs0); then { let lhs0 = Sugg::hir_opt(cx, lhs0); let rhs0 = Sugg::hir_opt(cx, rhs0); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 28fb6ed12a0..785c409260e 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -340,6 +340,11 @@ pub fn over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) - left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } +/// Checks if two expressions evaluate to the same value, and don't contain any side effects. +pub fn eq_expr_value(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>) -> bool { + SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) +} + /// Type used to hash an ast element. This is different from the `Hash` trait /// on ast types as this /// trait would consider IDs and spans. diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 6c235679914..0b8d0bd9e11 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,7 +1,6 @@ -use crate::utils::SpanlessEq; use crate::utils::{ is_expn_of, match_def_path, match_qpath, match_type, method_calls, paths, run_lints, snippet, span_lint, - span_lint_and_help, span_lint_and_sugg, walk_ptrs_ty, + span_lint_and_help, span_lint_and_sugg, walk_ptrs_ty, SpanlessEq, }; use if_chain::if_chain; use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, NodeId}; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 223628cc610..530552f7940 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -21,7 +21,7 @@ pub mod sugg; pub mod usage; pub use self::attrs::*; pub use self::diagnostics::*; -pub use self::hir_utils::{both, over, SpanlessEq, SpanlessHash}; +pub use self::hir_utils::{both, eq_expr_value, over, SpanlessEq, SpanlessHash}; use std::borrow::Cow; use std::mem; From 9b800b1e929d6023e1813b2b189336a4bddcffd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com> Date: Sun, 16 Aug 2020 00:00:00 +0000 Subject: [PATCH 466/526] Rename SpanlessEq::ignore_fn to deny_side_effects No functional changes intended. --- clippy_lints/src/utils/hir_utils.rs | 19 +++++++++---------- clippy_lints/src/utils/internal_lints.rs | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 785c409260e..1014546ff89 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -23,9 +23,7 @@ pub struct SpanlessEq<'a, 'tcx> { /// Context used to evaluate constant expressions. cx: &'a LateContext<'tcx>, maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>, - /// If is true, never consider as equal expressions containing function - /// calls. - ignore_fn: bool, + allow_side_effects: bool, } impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { @@ -33,13 +31,14 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { Self { cx, maybe_typeck_results: cx.maybe_typeck_results(), - ignore_fn: false, + allow_side_effects: true, } } - pub fn ignore_fn(self) -> Self { + /// Consider expressions containing potential side effects as not equal. + pub fn deny_side_effects(self) -> Self { Self { - ignore_fn: true, + allow_side_effects: false, ..self } } @@ -67,7 +66,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { #[allow(clippy::similar_names)] pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool { - if self.ignore_fn && differing_macro_contexts(left.span, right.span) { + if !self.allow_side_effects && differing_macro_contexts(left.span, right.span) { return false; } @@ -108,7 +107,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { }, (&ExprKind::Box(ref l), &ExprKind::Box(ref r)) => self.eq_expr(l, r), (&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => { - !self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) + self.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) }, (&ExprKind::Cast(ref lx, ref lt), &ExprKind::Cast(ref rx, ref rt)) | (&ExprKind::Type(ref lx, ref lt), &ExprKind::Type(ref rx, ref rt)) => { @@ -134,7 +133,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { }) }, (&ExprKind::MethodCall(l_path, _, l_args, _), &ExprKind::MethodCall(r_path, _, r_args, _)) => { - !self.ignore_fn && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args) + self.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args) }, (&ExprKind::Repeat(ref le, ref ll_id), &ExprKind::Repeat(ref re, ref rl_id)) => { let mut celcx = constant_context(self.cx, self.cx.tcx.typeck_body(ll_id.body)); @@ -342,7 +341,7 @@ pub fn over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) - /// Checks if two expressions evaluate to the same value, and don't contain any side effects. pub fn eq_expr_value(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>) -> bool { - SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) + SpanlessEq::new(cx).deny_side_effects().eq_expr(left, right) } /// Type used to hash an ast element. This is different from the `Hash` trait diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 0b8d0bd9e11..8fa5d22210a 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -492,7 +492,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { if let StmtKind::Semi(only_expr) = &stmts[0].kind; if let ExprKind::MethodCall(ref ps, _, ref span_call_args, _) = &only_expr.kind; let and_then_snippets = get_and_then_snippets(cx, and_then_args); - let mut sle = SpanlessEq::new(cx).ignore_fn(); + let mut sle = SpanlessEq::new(cx).deny_side_effects(); then { match &*ps.ident.as_str() { "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => { From d1dbf7913ad83954337e94b094f22f1d9d8b83f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com> Date: Sun, 16 Aug 2020 00:00:00 +0000 Subject: [PATCH 467/526] Expresions with Assign / AssignOp have side effects --- clippy_lints/src/utils/hir_utils.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 1014546ff89..cacc9f8d6f2 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -89,10 +89,10 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { both(&li.label, &ri.label, |l, r| l.ident.as_str() == r.ident.as_str()) }, (&ExprKind::Assign(ref ll, ref lr, _), &ExprKind::Assign(ref rl, ref rr, _)) => { - self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + self.allow_side_effects && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }, (&ExprKind::AssignOp(ref lo, ref ll, ref lr), &ExprKind::AssignOp(ref ro, ref rl, ref rr)) => { - lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + self.allow_side_effects && lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }, (&ExprKind::Block(ref l, _), &ExprKind::Block(ref r, _)) => self.eq_block(l, r), (&ExprKind::Binary(l_op, ref ll, ref lr), &ExprKind::Binary(r_op, ref rl, ref rr)) => { From 4f4abf4e0640edbb1614f3dcb8ff62e8afc54801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com> Date: Sun, 16 Aug 2020 00:00:00 +0000 Subject: [PATCH 468/526] Warn about explicit self-assignment Warn about assignments where left-hand side place expression is the same as right-hand side value expression. For example, warn about assignment in: ```rust pub struct Event { id: usize, x: i32, y: i32, } pub fn copy_position(a: &mut Event, b: &Event) { a.x = b.x; a.y = a.y; } ``` --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 +++ clippy_lints/src/self_assignment.rs | 51 +++++++++++++++++++++ src/lintlist/mod.rs | 7 +++ tests/ui/self_assignment.rs | 67 +++++++++++++++++++++++++++ tests/ui/self_assignment.stderr | 70 +++++++++++++++++++++++++++++ 6 files changed, 201 insertions(+) create mode 100644 clippy_lints/src/self_assignment.rs create mode 100644 tests/ui/self_assignment.rs create mode 100644 tests/ui/self_assignment.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index f662de122f9..5ce63c0a157 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1690,6 +1690,7 @@ Released 2018-09-13 [`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition [`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some +[`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse [`shadow_same`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_same diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 17501e8e6da..87c297e72eb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -284,6 +284,7 @@ mod reference; mod regex; mod repeat_once; mod returns; +mod self_assignment; mod serde_api; mod shadow; mod single_component_path_imports; @@ -773,6 +774,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &repeat_once::REPEAT_ONCE, &returns::LET_AND_RETURN, &returns::NEEDLESS_RETURN, + &self_assignment::SELF_ASSIGNMENT, &serde_api::SERDE_API_MISUSE, &shadow::SHADOW_REUSE, &shadow::SHADOW_SAME, @@ -1090,6 +1092,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch); store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive); store.register_late_pass(|| box repeat_once::RepeatOnce); + store.register_late_pass(|| box self_assignment::SelfAssignment); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1421,6 +1424,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&repeat_once::REPEAT_ONCE), LintId::of(&returns::LET_AND_RETURN), LintId::of(&returns::NEEDLESS_RETURN), + LintId::of(&self_assignment::SELF_ASSIGNMENT), LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), @@ -1714,6 +1718,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&ptr::MUT_FROM_REF), LintId::of(&ranges::REVERSED_EMPTY_RANGES), LintId::of(®ex::INVALID_REGEX), + LintId::of(&self_assignment::SELF_ASSIGNMENT), LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), diff --git a/clippy_lints/src/self_assignment.rs b/clippy_lints/src/self_assignment.rs new file mode 100644 index 00000000000..e096c9aebc1 --- /dev/null +++ b/clippy_lints/src/self_assignment.rs @@ -0,0 +1,51 @@ +use crate::utils::{eq_expr_value, snippet, span_lint}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Checks for explicit self-assignments. + /// + /// **Why is this bad?** Self-assignments are redundant and unlikely to be + /// intentional. + /// + /// **Known problems:** If expression contains any deref coercions or + /// indexing operations they are assumed not to have any side effects. + /// + /// **Example:** + /// + /// ```rust + /// struct Event { + /// id: usize, + /// x: i32, + /// y: i32, + /// } + /// + /// fn copy_position(a: &mut Event, b: &Event) { + /// a.x = b.x; + /// a.y = a.y; + /// } + /// ``` + pub SELF_ASSIGNMENT, + correctness, + "explicit self-assignment" +} + +declare_lint_pass!(SelfAssignment => [SELF_ASSIGNMENT]); + +impl<'tcx> LateLintPass<'tcx> for SelfAssignment { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if let ExprKind::Assign(lhs, rhs, _) = &expr.kind { + if eq_expr_value(cx, lhs, rhs) { + let lhs = snippet(cx, lhs.span, "<lhs>"); + let rhs = snippet(cx, rhs.span, "<rhs>"); + span_lint( + cx, + SELF_ASSIGNMENT, + expr.span, + &format!("self-assignment of `{}` to `{}`", rhs, lhs), + ); + } + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 3229c8da507..bf58c117aaa 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1956,6 +1956,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "methods", }, + Lint { + name: "self_assignment", + group: "correctness", + desc: "explicit self-assignment", + deprecation: None, + module: "self_assignment", + }, Lint { name: "serde_api_misuse", group: "correctness", diff --git a/tests/ui/self_assignment.rs b/tests/ui/self_assignment.rs new file mode 100644 index 00000000000..a7cbb9cd78b --- /dev/null +++ b/tests/ui/self_assignment.rs @@ -0,0 +1,67 @@ +#![warn(clippy::self_assignment)] + +pub struct S<'a> { + a: i32, + b: [i32; 10], + c: Vec<Vec<i32>>, + e: &'a mut i32, + f: &'a mut i32, +} + +pub fn positives(mut a: usize, b: &mut u32, mut s: S) { + a = a; + *b = *b; + s = s; + s.a = s.a; + s.b[10] = s.b[5 + 5]; + s.c[0][1] = s.c[0][1]; + s.b[a] = s.b[a]; + *s.e = *s.e; + s.b[a + 10] = s.b[10 + a]; + + let mut t = (0, 1); + t.1 = t.1; + t.0 = (t.0); +} + +pub fn negatives_not_equal(mut a: usize, b: &mut usize, mut s: S) { + dbg!(&a); + a = *b; + dbg!(&a); + s.b[1] += s.b[1]; + s.b[1] = s.b[2]; + s.c[1][0] = s.c[0][1]; + s.b[a] = s.b[*b]; + s.b[a + 10] = s.b[a + 11]; + *s.e = *s.f; + + let mut t = (0, 1); + t.0 = t.1; +} + +#[allow(clippy::eval_order_dependence)] +pub fn negatives_side_effects() { + let mut v = vec![1, 2, 3, 4, 5]; + let mut i = 0; + v[{ + i += 1; + i + }] = v[{ + i += 1; + i + }]; + + fn next(n: &mut usize) -> usize { + let v = *n; + *n += 1; + v + } + + let mut w = vec![1, 2, 3, 4, 5]; + let mut i = 0; + let i = &mut i; + w[next(i)] = w[next(i)]; + w[next(i)] = w[next(i)]; +} + +fn main() {} diff --git a/tests/ui/self_assignment.stderr b/tests/ui/self_assignment.stderr new file mode 100644 index 00000000000..826e0d0ba88 --- /dev/null +++ b/tests/ui/self_assignment.stderr @@ -0,0 +1,70 @@ +error: self-assignment of `a` to `a` + --> $DIR/self_assignment.rs:12:5 + | +LL | a = a; + | ^^^^^ + | + = note: `-D clippy::self-assignment` implied by `-D warnings` + +error: self-assignment of `*b` to `*b` + --> $DIR/self_assignment.rs:13:5 + | +LL | *b = *b; + | ^^^^^^^ + +error: self-assignment of `s` to `s` + --> $DIR/self_assignment.rs:14:5 + | +LL | s = s; + | ^^^^^ + +error: self-assignment of `s.a` to `s.a` + --> $DIR/self_assignment.rs:15:5 + | +LL | s.a = s.a; + | ^^^^^^^^^ + +error: self-assignment of `s.b[5 + 5]` to `s.b[10]` + --> $DIR/self_assignment.rs:16:5 + | +LL | s.b[10] = s.b[5 + 5]; + | ^^^^^^^^^^^^^^^^^^^^ + +error: self-assignment of `s.c[0][1]` to `s.c[0][1]` + --> $DIR/self_assignment.rs:17:5 + | +LL | s.c[0][1] = s.c[0][1]; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: self-assignment of `s.b[a]` to `s.b[a]` + --> $DIR/self_assignment.rs:18:5 + | +LL | s.b[a] = s.b[a]; + | ^^^^^^^^^^^^^^^ + +error: self-assignment of `*s.e` to `*s.e` + --> $DIR/self_assignment.rs:19:5 + | +LL | *s.e = *s.e; + | ^^^^^^^^^^^ + +error: self-assignment of `s.b[10 + a]` to `s.b[a + 10]` + --> $DIR/self_assignment.rs:20:5 + | +LL | s.b[a + 10] = s.b[10 + a]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: self-assignment of `t.1` to `t.1` + --> $DIR/self_assignment.rs:23:5 + | +LL | t.1 = t.1; + | ^^^^^^^^^ + +error: self-assignment of `(t.0)` to `t.0` + --> $DIR/self_assignment.rs:24:5 + | +LL | t.0 = (t.0); + | ^^^^^^^^^^^ + +error: aborting due to 11 previous errors + From 99ba290a14c6654164cea8339b827d8da0ff600d Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Mon, 17 Aug 2020 08:36:02 +0900 Subject: [PATCH 469/526] Improve code style --- clippy_lints/src/loops.rs | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f7db2563d2b..df06031d999 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1145,29 +1145,24 @@ fn detect_same_item_push<'tcx>( let vec_str = snippet_with_macro_callsite(cx, vec.span, ""); let item_str = snippet_with_macro_callsite(cx, pushed_item.span, ""); if let ExprKind::Path(ref qpath) = pushed_item.kind { - if let Res::Local(hir_id) = qpath_res(cx, qpath, pushed_item.hir_id) { + if_chain! { + if let Res::Local(hir_id) = qpath_res(cx, qpath, pushed_item.hir_id); let node = cx.tcx.hir().get(hir_id); - if_chain! { - if let Node::Binding(pat) = node; - if let PatKind::Binding(bind_ann, ..) = pat.kind; - then { - match bind_ann { - BindingAnnotation::RefMut | BindingAnnotation::Mutable => {}, - _ => { - span_lint_and_help( - cx, - SAME_ITEM_PUSH, - vec.span, - "it looks like the same item is being pushed into this Vec", - None, - &format!( - "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})", - item_str, vec_str, item_str - ), - ) - } - } - } + if let Node::Binding(pat) = node; + if let PatKind::Binding(bind_ann, ..) = pat.kind; + if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable); + then { + span_lint_and_help( + cx, + SAME_ITEM_PUSH, + vec.span, + "it looks like the same item is being pushed into this Vec", + None, + &format!( + "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})", + item_str, vec_str, item_str + ), + ) } } } else if mutated_variables(pushed_item, cx).map_or(false, |mutvars| mutvars.is_empty()) { From 262db3b5e6c3f3278c9fb2a91817f3a66cf0a5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Mon, 17 Aug 2020 12:19:32 +0200 Subject: [PATCH 470/526] deps: bump cargo_metadata and semver cargo_metadata 0.9.1 -> 0.11.1 semver 0.9.0 -> 0.10.0 --- Cargo.toml | 4 ++-- clippy_lints/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 836897927b0..c7a3099b8ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,13 +31,13 @@ path = "src/driver.rs" # begin automatic update clippy_lints = { version = "0.0.212", path = "clippy_lints" } # end automatic update -semver = "0.9" +semver = "0.10" rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} tempfile = { version = "3.1.0", optional = true } lazy_static = "1.0" [dev-dependencies] -cargo_metadata = "0.9.1" +cargo_metadata = "0.11.1" compiletest_rs = { version = "0.5.0", features = ["tmp"] } tester = "0.7" lazy_static = "1.0" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index e959c1a6511..cc7d3a04f00 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -17,7 +17,7 @@ keywords = ["clippy", "lint", "plugin"] edition = "2018" [dependencies] -cargo_metadata = "0.9.1" +cargo_metadata = "0.11.1" if_chain = "1.0.0" itertools = "0.9" lazy_static = "1.0.2" @@ -28,7 +28,7 @@ serde = { version = "1.0", features = ["derive"] } smallvec = { version = "1", features = ["union"] } toml = "0.5.3" unicode-normalization = "0.1" -semver = "0.9.0" +semver = "0.10.0" # NOTE: cargo requires serde feat in its url dep # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864> url = { version = "2.1.0", features = ["serde"] } From df4d42fc2debf7a7d43226c79480c71037be42b8 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Tue, 18 Aug 2020 01:00:11 +0200 Subject: [PATCH 471/526] transmute: avoid suggesting from/to bits in const --- clippy_lints/src/transmute.rs | 10 +++-- tests/ui/transmute.rs | 15 ++++++-- tests/ui/transmute.stderr | 52 +++++++++++++------------- tests/ui/transmute_float_to_int.rs | 11 +++++- tests/ui/transmute_float_to_int.stderr | 12 +++--- 5 files changed, 61 insertions(+), 39 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 28fd55f6ff0..1d238b242b0 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,5 +1,5 @@ use crate::utils::{ - is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_sugg, + in_constant, is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, sugg, }; use if_chain::if_chain; @@ -331,6 +331,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::TRANSMUTE); then { + // Avoid suggesting f32::(from|to)_bits in const contexts. + // See https://github.com/rust-lang/rust/issues/73736 for progress on making them `const fn`. + let const_context = in_constant(cx, e.hir_id); + let from_ty = cx.typeck_results().expr_ty(&args[0]); let to_ty = cx.typeck_results().expr_ty(e); @@ -544,7 +548,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { }, ) }, - (ty::Int(_) | ty::Uint(_), ty::Float(_)) => span_lint_and_then( + (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => span_lint_and_then( cx, TRANSMUTE_INT_TO_FLOAT, e.span, @@ -567,7 +571,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { ); }, ), - (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) => span_lint_and_then( + (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => span_lint_and_then( cx, TRANSMUTE_FLOAT_TO_INT, e.span, diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index bb853d23704..7caad34edb3 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -1,3 +1,4 @@ +#![feature(const_fn_transmute)] #![allow(dead_code)] extern crate core; @@ -81,9 +82,17 @@ fn int_to_bool() { } #[warn(clippy::transmute_int_to_float)] -fn int_to_float() { - let _: f32 = unsafe { std::mem::transmute(0_u32) }; - let _: f32 = unsafe { std::mem::transmute(0_i32) }; +mod int_to_float { + fn test() { + let _: f32 = unsafe { std::mem::transmute(0_u32) }; + let _: f32 = unsafe { std::mem::transmute(0_i32) }; + } + + // See issue #5747 + const VALUE: f32 = unsafe { std::mem::transmute(0_u32) }; + const fn from_bits(v: u32) -> f32 { + unsafe { std::mem::transmute(v) } + } } fn bytes_to_str(b: &[u8], mb: &mut [u8]) { diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 8582080498f..d817c08b52f 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -1,5 +1,5 @@ error: transmute from a type (`&T`) to itself - --> $DIR/transmute.rs:19:20 + --> $DIR/transmute.rs:20:20 | LL | let _: &'a T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,67 +7,67 @@ LL | let _: &'a T = core::intrinsics::transmute(t); = note: `-D clippy::useless-transmute` implied by `-D warnings` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:23:23 + --> $DIR/transmute.rs:24:23 | LL | let _: *const T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:25:21 + --> $DIR/transmute.rs:26:21 | LL | let _: *mut T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:27:23 + --> $DIR/transmute.rs:28:23 | LL | let _: *const U = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U` error: transmute from a type (`std::vec::Vec<i32>`) to itself - --> $DIR/transmute.rs:33:27 + --> $DIR/transmute.rs:34:27 | LL | let _: Vec<i32> = core::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec<i32>`) to itself - --> $DIR/transmute.rs:35:27 + --> $DIR/transmute.rs:36:27 | LL | let _: Vec<i32> = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec<i32>`) to itself - --> $DIR/transmute.rs:37:27 + --> $DIR/transmute.rs:38:27 | LL | let _: Vec<i32> = std::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec<i32>`) to itself - --> $DIR/transmute.rs:39:27 + --> $DIR/transmute.rs:40:27 | LL | let _: Vec<i32> = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec<i32>`) to itself - --> $DIR/transmute.rs:41:27 + --> $DIR/transmute.rs:42:27 | LL | let _: Vec<i32> = my_transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^ error: transmute from an integer to a pointer - --> $DIR/transmute.rs:43:31 + --> $DIR/transmute.rs:44:31 | LL | let _: *const usize = std::mem::transmute(5_isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` error: transmute from an integer to a pointer - --> $DIR/transmute.rs:47:31 + --> $DIR/transmute.rs:48:31 | LL | let _: *const usize = std::mem::transmute(1 + 1usize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize` error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:62:24 + --> $DIR/transmute.rs:63:24 | LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,25 +75,25 @@ LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); = note: `-D clippy::crosspointer-transmute` implied by `-D warnings` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:64:24 + --> $DIR/transmute.rs:65:24 | LL | let _: Usize = core::intrinsics::transmute(int_mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - --> $DIR/transmute.rs:66:31 + --> $DIR/transmute.rs:67:31 | LL | let _: *const Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) - --> $DIR/transmute.rs:68:29 + --> $DIR/transmute.rs:69:29 | LL | let _: *mut Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a `u32` to a `char` - --> $DIR/transmute.rs:74:28 + --> $DIR/transmute.rs:75:28 | LL | let _: char = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` @@ -101,13 +101,13 @@ LL | let _: char = unsafe { std::mem::transmute(0_u32) }; = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` error: transmute from a `i32` to a `char` - --> $DIR/transmute.rs:75:28 + --> $DIR/transmute.rs:76:28 | LL | let _: char = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` error: transmute from a `u8` to a `bool` - --> $DIR/transmute.rs:80:28 + --> $DIR/transmute.rs:81:28 | LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` @@ -115,21 +115,21 @@ LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` error: transmute from a `u32` to a `f32` - --> $DIR/transmute.rs:85:27 + --> $DIR/transmute.rs:87:31 | -LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` +LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` | = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` error: transmute from a `i32` to a `f32` - --> $DIR/transmute.rs:86:27 + --> $DIR/transmute.rs:88:31 | -LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` +LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:90:28 + --> $DIR/transmute.rs:99:28 | LL | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` @@ -137,7 +137,7 @@ LL | let _: &str = unsafe { std::mem::transmute(b) }; = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:91:32 + --> $DIR/transmute.rs:100:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs index ce942751ada..8173944d959 100644 --- a/tests/ui/transmute_float_to_int.rs +++ b/tests/ui/transmute_float_to_int.rs @@ -1,4 +1,5 @@ -#[warn(clippy::transmute_float_to_int)] +#![feature(const_fn_transmute)] +#![warn(clippy::transmute_float_to_int)] fn float_to_int() { let _: u32 = unsafe { std::mem::transmute(1f32) }; @@ -9,4 +10,12 @@ fn float_to_int() { let _: u64 = unsafe { std::mem::transmute(-1.0) }; } +mod issue_5747 { + const VALUE: u32 = unsafe { std::mem::transmute(1f32) }; + + const fn to_bits(v: f32) -> u32 { + unsafe { std::mem::transmute(v) } + } +} + fn main() {} diff --git a/tests/ui/transmute_float_to_int.stderr b/tests/ui/transmute_float_to_int.stderr index eb786bb39f9..5a40cf381d6 100644 --- a/tests/ui/transmute_float_to_int.stderr +++ b/tests/ui/transmute_float_to_int.stderr @@ -1,5 +1,5 @@ error: transmute from a `f32` to a `u32` - --> $DIR/transmute_float_to_int.rs:4:27 + --> $DIR/transmute_float_to_int.rs:5:27 | LL | let _: u32 = unsafe { std::mem::transmute(1f32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits()` @@ -7,31 +7,31 @@ LL | let _: u32 = unsafe { std::mem::transmute(1f32) }; = note: `-D clippy::transmute-float-to-int` implied by `-D warnings` error: transmute from a `f32` to a `i32` - --> $DIR/transmute_float_to_int.rs:5:27 + --> $DIR/transmute_float_to_int.rs:6:27 | LL | let _: i32 = unsafe { std::mem::transmute(1f32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32` error: transmute from a `f64` to a `u64` - --> $DIR/transmute_float_to_int.rs:6:27 + --> $DIR/transmute_float_to_int.rs:7:27 | LL | let _: u64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()` error: transmute from a `f64` to a `i64` - --> $DIR/transmute_float_to_int.rs:7:27 + --> $DIR/transmute_float_to_int.rs:8:27 | LL | let _: i64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits() as i64` error: transmute from a `f64` to a `u64` - --> $DIR/transmute_float_to_int.rs:8:27 + --> $DIR/transmute_float_to_int.rs:9:27 | LL | let _: u64 = unsafe { std::mem::transmute(1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.0f64.to_bits()` error: transmute from a `f64` to a `u64` - --> $DIR/transmute_float_to_int.rs:9:27 + --> $DIR/transmute_float_to_int.rs:10:27 | LL | let _: u64 = unsafe { std::mem::transmute(-1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()` From 6a12bae1941bdef7c2716ffefed5594e5d7e9f8e Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Tue, 18 Aug 2020 22:19:30 +0200 Subject: [PATCH 472/526] no from/to bits in const: add tests cases for f64 --- clippy_lints/src/transmute.rs | 2 +- tests/ui/transmute.rs | 17 +++++++++++++---- tests/ui/transmute.stderr | 18 +++++++++++++++--- tests/ui/transmute_float_to_int.rs | 9 +++++++-- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 1d238b242b0..50d9c93f9d4 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -331,7 +331,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::TRANSMUTE); then { - // Avoid suggesting f32::(from|to)_bits in const contexts. + // Avoid suggesting from/to bits in const contexts. // See https://github.com/rust-lang/rust/issues/73736 for progress on making them `const fn`. let const_context = in_constant(cx, e.hir_id); diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 7caad34edb3..9f1948359e7 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -86,12 +86,21 @@ mod int_to_float { fn test() { let _: f32 = unsafe { std::mem::transmute(0_u32) }; let _: f32 = unsafe { std::mem::transmute(0_i32) }; + let _: f64 = unsafe { std::mem::transmute(0_u64) }; + let _: f64 = unsafe { std::mem::transmute(0_i64) }; } - // See issue #5747 - const VALUE: f32 = unsafe { std::mem::transmute(0_u32) }; - const fn from_bits(v: u32) -> f32 { - unsafe { std::mem::transmute(v) } + mod issue_5747 { + const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) }; + const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) }; + + const fn from_bits_32(v: i32) -> f32 { + unsafe { std::mem::transmute(v) } + } + + const fn from_bits_64(v: u64) -> f64 { + unsafe { std::mem::transmute(v) } + } } } diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index d817c08b52f..ad9953d12bc 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -128,8 +128,20 @@ error: transmute from a `i32` to a `f32` LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` +error: transmute from a `u64` to a `f64` + --> $DIR/transmute.rs:89:31 + | +LL | let _: f64 = unsafe { std::mem::transmute(0_u64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)` + +error: transmute from a `i64` to a `f64` + --> $DIR/transmute.rs:90:31 + | +LL | let _: f64 = unsafe { std::mem::transmute(0_i64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` + error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:99:28 + --> $DIR/transmute.rs:108:28 | LL | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` @@ -137,10 +149,10 @@ LL | let _: &str = unsafe { std::mem::transmute(b) }; = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:100:32 + --> $DIR/transmute.rs:109:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` -error: aborting due to 22 previous errors +error: aborting due to 24 previous errors diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs index 8173944d959..1040fee4b34 100644 --- a/tests/ui/transmute_float_to_int.rs +++ b/tests/ui/transmute_float_to_int.rs @@ -11,9 +11,14 @@ fn float_to_int() { } mod issue_5747 { - const VALUE: u32 = unsafe { std::mem::transmute(1f32) }; + const VALUE32: i32 = unsafe { std::mem::transmute(1f32) }; + const VALUE64: u64 = unsafe { std::mem::transmute(1f64) }; - const fn to_bits(v: f32) -> u32 { + const fn to_bits_32(v: f32) -> u32 { + unsafe { std::mem::transmute(v) } + } + + const fn to_bits_64(v: f64) -> i64 { unsafe { std::mem::transmute(v) } } } From 902b28275ef6e06826f269bdf2459c4ba4562145 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Wed, 19 Aug 2020 22:31:34 +0900 Subject: [PATCH 473/526] Improve lint message in `to_string_in_display` --- clippy_lints/src/to_string_in_display.rs | 4 ++-- src/lintlist/mod.rs | 2 +- tests/ui/to_string_in_display.stderr | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/to_string_in_display.rs b/clippy_lints/src/to_string_in_display.rs index 11bdd27d9b1..4b6a0a6a0c9 100644 --- a/clippy_lints/src/to_string_in_display.rs +++ b/clippy_lints/src/to_string_in_display.rs @@ -39,7 +39,7 @@ declare_clippy_lint! { /// ``` pub TO_STRING_IN_DISPLAY, correctness, - "to_string method used while implementing Display trait" + "`to_string` method used while implementing `Display` trait" } #[derive(Default)] @@ -80,7 +80,7 @@ impl LateLintPass<'_> for ToStringInDisplay { cx, TO_STRING_IN_DISPLAY, expr.span, - "Using to_string in fmt::Display implementation might lead to infinite recursion", + "using `to_string` in `fmt::Display` implementation might lead to infinite recursion", ); } } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index bf58c117aaa..c50c6b900ae 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2183,7 +2183,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ Lint { name: "to_string_in_display", group: "correctness", - desc: "to_string method used while implementing Display trait", + desc: "`to_string` method used while implementing `Display` trait", deprecation: None, module: "to_string_in_display", }, diff --git a/tests/ui/to_string_in_display.stderr b/tests/ui/to_string_in_display.stderr index cbc0a41036b..5f26ef413e2 100644 --- a/tests/ui/to_string_in_display.stderr +++ b/tests/ui/to_string_in_display.stderr @@ -1,4 +1,4 @@ -error: Using to_string in fmt::Display implementation might lead to infinite recursion +error: using `to_string` in `fmt::Display` implementation might lead to infinite recursion --> $DIR/to_string_in_display.rs:25:25 | LL | write!(f, "{}", self.to_string()) From c236c0fb5694948353b5fcbe46010cf04d5a7107 Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Thu, 20 Aug 2020 06:34:48 +0200 Subject: [PATCH 474/526] Fix false positive in `PRECEDENCE` lint Extend the lint to handle chains of methods combined with unary negation. Closes #5924 --- clippy_lints/src/precedence.rs | 59 +++++++++++++++++----------------- tests/ui/precedence.fixed | 8 +++++ tests/ui/precedence.rs | 8 +++++ tests/ui/precedence.stderr | 20 +++++++++++- 4 files changed, 65 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 4797771e7bd..c9d18c3cb72 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,4 +1,5 @@ use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; +use if_chain::if_chain; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; @@ -102,36 +103,36 @@ impl EarlyLintPass for Precedence { } } - if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.kind { - if let ExprKind::MethodCall(ref path_segment, ref args, _) = rhs.kind { + if let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind { + let mut arg = operand; + + let mut all_odd = true; + while let ExprKind::MethodCall(path_segment, args, _) = &arg.kind { let path_segment_str = path_segment.ident.name.as_str(); - if let Some(slf) = args.first() { - if let ExprKind::Lit(ref lit) = slf.kind { - match lit.kind { - LitKind::Int(..) | LitKind::Float(..) => { - if ALLOWED_ODD_FUNCTIONS - .iter() - .any(|odd_function| **odd_function == *path_segment_str) - { - return; - } - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - PRECEDENCE, - expr.span, - "unary minus has lower precedence than method call", - "consider adding parentheses to clarify your intent", - format!( - "-({})", - snippet_with_applicability(cx, rhs.span, "..", &mut applicability) - ), - applicability, - ); - }, - _ => (), - } - } + all_odd &= ALLOWED_ODD_FUNCTIONS + .iter() + .any(|odd_function| **odd_function == *path_segment_str); + arg = args.first().expect("A method always has a receiver."); + } + + if_chain! { + if !all_odd; + if let ExprKind::Lit(lit) = &arg.kind; + if let LitKind::Int(..) | LitKind::Float(..) = &lit.kind; + then { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + PRECEDENCE, + expr.span, + "unary minus has lower precedence than method call", + "consider adding parentheses to clarify your intent", + format!( + "-({})", + snippet_with_applicability(cx, operand.span, "..", &mut applicability) + ), + applicability, + ); } } } diff --git a/tests/ui/precedence.fixed b/tests/ui/precedence.fixed index 4d284ae1319..163bd044c17 100644 --- a/tests/ui/precedence.fixed +++ b/tests/ui/precedence.fixed @@ -48,6 +48,14 @@ fn main() { let _ = -1f64.to_degrees(); let _ = -1f64.to_radians(); + // Chains containing any non-odd function should trigger (issue #5924) + let _ = -(1.0_f64.cos().cos()); + let _ = -(1.0_f64.cos().sin()); + let _ = -(1.0_f64.sin().cos()); + + // Chains of odd functions shouldn't trigger + let _ = -1f64.sin().sin(); + let b = 3; trip!(b * 8); } diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index 2d08e82f349..8c849e3209b 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -48,6 +48,14 @@ fn main() { let _ = -1f64.to_degrees(); let _ = -1f64.to_radians(); + // Chains containing any non-odd function should trigger (issue #5924) + let _ = -1.0_f64.cos().cos(); + let _ = -1.0_f64.cos().sin(); + let _ = -1.0_f64.sin().cos(); + + // Chains of odd functions shouldn't trigger + let _ = -1f64.sin().sin(); + let b = 3; trip!(b * 8); } diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index a2ed5392bfc..03d585b3975 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -54,5 +54,23 @@ error: unary minus has lower precedence than method call LL | -1f32.abs(); | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` -error: aborting due to 9 previous errors +error: unary minus has lower precedence than method call + --> $DIR/precedence.rs:52:13 + | +LL | let _ = -1.0_f64.cos().cos(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.cos().cos())` + +error: unary minus has lower precedence than method call + --> $DIR/precedence.rs:53:13 + | +LL | let _ = -1.0_f64.cos().sin(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.cos().sin())` + +error: unary minus has lower precedence than method call + --> $DIR/precedence.rs:54:13 + | +LL | let _ = -1.0_f64.sin().cos(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.sin().cos())` + +error: aborting due to 12 previous errors From 11efd75aeb8637bd5444104a57f1051b86c0d62b Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Fri, 21 Aug 2020 07:23:04 +0200 Subject: [PATCH 475/526] Fix false negative in `option_as_ref_deref` --- clippy_lints/src/methods/mod.rs | 7 ++++++- tests/ui/option_as_ref_deref.fixed | 3 +++ tests/ui/option_as_ref_deref.rs | 3 +++ tests/ui/option_as_ref_deref.stderr | 8 +++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2498c48f067..22942d9fb0c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3421,7 +3421,12 @@ fn lint_option_as_ref_deref<'tcx>( ]; let is_deref = match map_args[1].kind { - hir::ExprKind::Path(ref expr_qpath) => deref_aliases.iter().any(|path| match_qpath(expr_qpath, path)), + hir::ExprKind::Path(ref expr_qpath) => cx + .qpath_res(expr_qpath, map_args[1].hir_id) + .opt_def_id() + .map_or(false, |fun_def_id| { + deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path)) + }), hir::ExprKind::Closure(_, _, body_id, _, _) => { let closure_body = cx.tcx.hir().body(body_id); let closure_expr = remove_blocks(&closure_body.value); diff --git a/tests/ui/option_as_ref_deref.fixed b/tests/ui/option_as_ref_deref.fixed index 076692e6445..07d7f0b45b0 100644 --- a/tests/ui/option_as_ref_deref.fixed +++ b/tests/ui/option_as_ref_deref.fixed @@ -38,4 +38,7 @@ fn main() { let _ = opt.as_deref(); let _ = opt.as_deref_mut(); + + // Issue #5927 + let _ = opt.as_deref(); } diff --git a/tests/ui/option_as_ref_deref.rs b/tests/ui/option_as_ref_deref.rs index 3bf5f715f83..6ae059c9425 100644 --- a/tests/ui/option_as_ref_deref.rs +++ b/tests/ui/option_as_ref_deref.rs @@ -41,4 +41,7 @@ fn main() { let _ = opt.as_ref().map(|x| &**x); let _ = opt.as_mut().map(|x| &mut **x); + + // Issue #5927 + let _ = opt.as_ref().map(std::ops::Deref::deref); } diff --git a/tests/ui/option_as_ref_deref.stderr b/tests/ui/option_as_ref_deref.stderr index a106582a633..62f28232475 100644 --- a/tests/ui/option_as_ref_deref.stderr +++ b/tests/ui/option_as_ref_deref.stderr @@ -100,5 +100,11 @@ error: called `.as_mut().map(|x| &mut **x)` on an Option value. This can be done LL | let _ = opt.as_mut().map(|x| &mut **x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` -error: aborting due to 16 previous errors +error: called `.as_ref().map(std::ops::Deref::deref)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead + --> $DIR/option_as_ref_deref.rs:46:13 + | +LL | let _ = opt.as_ref().map(std::ops::Deref::deref); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` + +error: aborting due to 17 previous errors From 146e352db4eade947f6f358cd38c308e95783d7b Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sat, 22 Aug 2020 00:59:42 +0200 Subject: [PATCH 476/526] run cargo dev fmt --- clippy_lints/src/unnested_or_patterns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 0dca6a5da0c..7f4f16f8faf 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -340,7 +340,7 @@ fn take_pat(from: &mut Pat) -> Pat { id: DUMMY_NODE_ID, kind: Wild, span: DUMMY_SP, - tokens: None + tokens: None, }; mem::replace(from, dummy) } From 03bc7aed441240190030c9dfdcce6405014178dd Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Fri, 21 Aug 2020 08:18:05 +0200 Subject: [PATCH 477/526] Add async test case for `wrong_self_convention` lint --- tests/ui/wrong_self_convention.rs | 13 +++++++++++++ tests/ui/wrong_self_convention.stderr | 24 ++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index 99652ca4470..f44305d7e48 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -1,3 +1,4 @@ +// edition:2018 #![warn(clippy::wrong_self_convention)] #![warn(clippy::wrong_pub_self_convention)] #![allow(dead_code)] @@ -75,3 +76,15 @@ mod issue4293 { fn into_t3(self: Arc<T>) {} } } + +// False positive for async (see #4037) +mod issue4037 { + pub struct Foo; + pub struct Bar; + + impl Foo { + pub async fn into_bar(self) -> Bar { + Bar + } + } +} diff --git a/tests/ui/wrong_self_convention.stderr b/tests/ui/wrong_self_convention.stderr index 0d0eb19cd07..ef3ad73ebc7 100644 --- a/tests/ui/wrong_self_convention.stderr +++ b/tests/ui/wrong_self_convention.stderr @@ -1,5 +1,5 @@ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:17:17 + --> $DIR/wrong_self_convention.rs:18:17 | LL | fn from_i32(self) {} | ^^^^ @@ -7,67 +7,67 @@ LL | fn from_i32(self) {} = note: `-D clippy::wrong-self-convention` implied by `-D warnings` error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:23:21 + --> $DIR/wrong_self_convention.rs:24:21 | LL | pub fn from_i64(self) {} | ^^^^ error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:35:15 + --> $DIR/wrong_self_convention.rs:36:15 | LL | fn as_i32(self) {} | ^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:37:17 + --> $DIR/wrong_self_convention.rs:38:17 | LL | fn into_i32(&self) {} | ^^^^^ error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:39:15 + --> $DIR/wrong_self_convention.rs:40:15 | LL | fn is_i32(self) {} | ^^^^ error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:41:15 + --> $DIR/wrong_self_convention.rs:42:15 | LL | fn to_i32(self) {} | ^^^^ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:43:17 + --> $DIR/wrong_self_convention.rs:44:17 | LL | fn from_i32(self) {} | ^^^^ error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:45:19 + --> $DIR/wrong_self_convention.rs:46:19 | LL | pub fn as_i64(self) {} | ^^^^ error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:46:21 + --> $DIR/wrong_self_convention.rs:47:21 | LL | pub fn into_i64(&self) {} | ^^^^^ error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:47:19 + --> $DIR/wrong_self_convention.rs:48:19 | LL | pub fn is_i64(self) {} | ^^^^ error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:48:19 + --> $DIR/wrong_self_convention.rs:49:19 | LL | pub fn to_i64(self) {} | ^^^^ error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:49:21 + --> $DIR/wrong_self_convention.rs:50:21 | LL | pub fn from_i64(self) {} | ^^^^ From 191b6c798fa40334ec8898d07b4d28fd76743120 Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Sat, 22 Aug 2020 10:35:18 +0200 Subject: [PATCH 478/526] Don't lint if it has always inline attribute --- clippy_lints/src/trivially_copy_pass_by_ref.rs | 9 +++++++-- tests/ui/trivially_copy_pass_by_ref.rs | 18 ++++++++++++++++++ tests/ui/trivially_copy_pass_by_ref.stderr | 14 +++++++++++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 7948d99162b..92f42168a1e 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -2,6 +2,7 @@ use std::cmp; use crate::utils::{is_copy, is_self_ty, snippet, span_lint_and_sugg}; use if_chain::if_chain; +use rustc_ast::attr; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; @@ -155,8 +156,12 @@ impl<'tcx> LateLintPass<'tcx> for TriviallyCopyPassByRef { return; } for a in attrs { - if a.meta_item_list().is_some() && a.has_name(sym!(proc_macro_derive)) { - return; + if let Some(meta_items) = a.meta_item_list() { + if a.has_name(sym!(proc_macro_derive)) + || (a.has_name(sym!(inline)) && attr::list_contains_name(&meta_items, sym!(always))) + { + return; + } } } }, diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index 316426f1cf1..e7e0a31febc 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -97,6 +97,24 @@ mod issue3992 { pub fn c(d: &u16) {} } +mod issue5876 { + // Don't lint here as it is always inlined + #[inline(always)] + fn foo_always(x: &i32) { + println!("{}", x); + } + + #[inline(never)] + fn foo_never(x: &i32) { + println!("{}", x); + } + + #[inline] + fn foo(x: &i32) { + println!("{}", x); + } +} + fn main() { let (mut foo, bar) = (Foo(0), Bar([0; 24])); let (mut a, b, c, x, y, z) = (0, 0, Bar([0; 24]), 0, Foo(0), 0); diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index be0914e4a79..ccc3cdb2b74 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -94,5 +94,17 @@ error: this argument (N byte) is passed by reference, but would be more efficien LL | fn trait_method2(&self, _color: &Color); | ^^^^^^ help: consider passing by value instead: `Color` -error: aborting due to 15 previous errors +error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) + --> $DIR/trivially_copy_pass_by_ref.rs:108:21 + | +LL | fn foo_never(x: &i32) { + | ^^^^ help: consider passing by value instead: `i32` + +error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) + --> $DIR/trivially_copy_pass_by_ref.rs:113:15 + | +LL | fn foo(x: &i32) { + | ^^^^ help: consider passing by value instead: `i32` + +error: aborting due to 17 previous errors From 5b07b9ed61d1979320e9e63219b5d0d6f4b350f7 Mon Sep 17 00:00:00 2001 From: Christian Stefanescu <chris@0chris.com> Date: Thu, 20 Aug 2020 22:49:39 +0200 Subject: [PATCH 479/526] Widen understanding of prelude import Prelude imports are exempt from wildcard import warnings. Until now only imports of the form ``` use ...::prelude::*; ``` were considered. This change makes it so that the segment `prelude` can show up anywhere, for instance: ``` use ...::prelude::v1::*; ``` Fixes #5917 --- clippy_lints/src/wildcard_imports.rs | 7 ++----- tests/ui/auxiliary/wildcard_imports_helper.rs | 6 ++++++ tests/ui/wildcard_imports.rs | 2 ++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index e7eb7c2e980..717741129a8 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -195,13 +195,10 @@ impl WildcardImports { } } -// Allow "...prelude::*" imports. +// Allow "...prelude::..::*" imports. // Many crates have a prelude, and it is imported as a glob by design. fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { - segments - .iter() - .last() - .map_or(false, |ps| ps.ident.as_str() == "prelude") + segments.iter().filter(|ps| ps.ident.as_str() == "prelude").count() > 0 } // Allow "super::*" imports in tests. diff --git a/tests/ui/auxiliary/wildcard_imports_helper.rs b/tests/ui/auxiliary/wildcard_imports_helper.rs index 414477aedd7..d75cdd625f9 100644 --- a/tests/ui/auxiliary/wildcard_imports_helper.rs +++ b/tests/ui/auxiliary/wildcard_imports_helper.rs @@ -19,3 +19,9 @@ mod extern_exports { A, } } + +pub mod prelude { + pub mod v1 { + pub struct PreludeModAnywhere; + } +} diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 3ad1a29aeba..1f261159f4a 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -20,6 +20,7 @@ use wildcard_imports_helper::inner::inner_for_self_import::*; use wildcard_imports_helper::*; use std::io::prelude::*; +use wildcard_imports_helper::prelude::v1::*; struct ReadFoo; @@ -75,6 +76,7 @@ fn main() { let _ = A; let _ = inner_struct_mod::C; let _ = ExternA; + let _ = PreludeModAnywhere; double_struct_import_test!(); double_struct_import_test!(); From 53508aeb65963c389233c956105202466128a900 Mon Sep 17 00:00:00 2001 From: Christian Stefanescu <chris@0chris.com> Date: Thu, 20 Aug 2020 22:54:46 +0200 Subject: [PATCH 480/526] Run sh tests/ui/update-all-references.sh --- tests/ui/wildcard_imports.fixed | 2 ++ tests/ui/wildcard_imports.stderr | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 67423e6ec1d..287f8935327 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -20,6 +20,7 @@ use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; use wildcard_imports_helper::{ExternA, extern_foo}; use std::io::prelude::*; +use wildcard_imports_helper::prelude::v1::*; struct ReadFoo; @@ -75,6 +76,7 @@ fn main() { let _ = A; let _ = inner_struct_mod::C; let _ = ExternA; + let _ = PreludeModAnywhere; double_struct_import_test!(); double_struct_import_test!(); diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index fab43b738eb..351988f31ea 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -37,55 +37,55 @@ LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:89:13 + --> $DIR/wildcard_imports.rs:91:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:95:75 + --> $DIR/wildcard_imports.rs:97:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:96:13 + --> $DIR/wildcard_imports.rs:98:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:107:20 + --> $DIR/wildcard_imports.rs:109:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:107:30 + --> $DIR/wildcard_imports.rs:109:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:114:13 + --> $DIR/wildcard_imports.rs:116:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:143:9 + --> $DIR/wildcard_imports.rs:145:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:152:9 + --> $DIR/wildcard_imports.rs:154:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:153:9 + --> $DIR/wildcard_imports.rs:155:9 | LL | use crate:: fn_mod:: | _________^ @@ -93,31 +93,31 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:164:13 + --> $DIR/wildcard_imports.rs:166:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:199:17 + --> $DIR/wildcard_imports.rs:201:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:207:13 + --> $DIR/wildcard_imports.rs:209:13 | LL | use super_imports::*; | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:216:17 + --> $DIR/wildcard_imports.rs:218:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:225:13 + --> $DIR/wildcard_imports.rs:227:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` From e615a26ae4fe293cda83961470907e78e4b2ee75 Mon Sep 17 00:00:00 2001 From: Christian Stefanescu <chris@0chris.com> Date: Fri, 21 Aug 2020 14:03:42 +0200 Subject: [PATCH 481/526] Use more elegant way to check for prelude string --- clippy_lints/src/wildcard_imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 717741129a8..5683a71efea 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -198,7 +198,7 @@ impl WildcardImports { // Allow "...prelude::..::*" imports. // Many crates have a prelude, and it is imported as a glob by design. fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { - segments.iter().filter(|ps| ps.ident.as_str() == "prelude").count() > 0 + segments.iter().any(|ps| ps.ident.as_str() == "prelude") } // Allow "super::*" imports in tests. From e8d33d73dc3f9d0daf9b3affe65a2431f5a3e13a Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Sun, 23 Aug 2020 07:50:59 +0200 Subject: [PATCH 482/526] Fix `let_and_return` bad suggestion Add a cast to the suggestion when the return expression has adjustments. These adjustments are lost when the suggestion is applied. This is similar to the problem in issue #4437. Closes #5729 --- clippy_lints/src/returns.rs | 5 ++++- tests/ui/let_and_return.rs | 21 +++++++++++++++++++++ tests/ui/let_and_return.stderr | 16 +++++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 3c5541e64b4..a6e4252a0c8 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -99,7 +99,10 @@ impl<'tcx> LateLintPass<'tcx> for Return { |err| { err.span_label(local.span, "unnecessary `let` binding"); - if let Some(snippet) = snippet_opt(cx, initexpr.span) { + if let Some(mut snippet) = snippet_opt(cx, initexpr.span) { + if !cx.typeck_results().expr_adjustments(&retexpr).is_empty() { + snippet.push_str(" as _"); + } err.multipart_suggestion( "return the expression directly", vec![ diff --git a/tests/ui/let_and_return.rs b/tests/ui/let_and_return.rs index 09614b8c1ad..73e550b3df8 100644 --- a/tests/ui/let_and_return.rs +++ b/tests/ui/let_and_return.rs @@ -135,4 +135,25 @@ mod no_lint_if_stmt_borrows { } } +mod issue_5729 { + use std::sync::Arc; + + trait Foo {} + + trait FooStorage { + fn foo_cloned(&self) -> Arc<dyn Foo>; + } + + struct FooStorageImpl<T: Foo> { + foo: Arc<T>, + } + + impl<T: Foo + 'static> FooStorage for FooStorageImpl<T> { + fn foo_cloned(&self) -> Arc<dyn Foo> { + let clone = Arc::clone(&self.foo); + clone + } + } +} + fn main() {} diff --git a/tests/ui/let_and_return.stderr b/tests/ui/let_and_return.stderr index eacf948b392..fe878e5f206 100644 --- a/tests/ui/let_and_return.stderr +++ b/tests/ui/let_and_return.stderr @@ -27,5 +27,19 @@ LL | LL | 5 | -error: aborting due to 2 previous errors +error: returning the result of a `let` binding from a block + --> $DIR/let_and_return.rs:154:13 + | +LL | let clone = Arc::clone(&self.foo); + | ---------------------------------- unnecessary `let` binding +LL | clone + | ^^^^^ + | +help: return the expression directly + | +LL | +LL | Arc::clone(&self.foo) as _ + | + +error: aborting due to 3 previous errors From 6dd65b8e6a548071b19507826c53bf9a7c36b323 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 20 Aug 2020 23:47:04 +0200 Subject: [PATCH 483/526] Fix cargo dev new_lint for late lint passes --- .github/workflows/clippy.yml | 7 +++++++ clippy_dev/src/new_lint.rs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 5fa8009a8b4..99e371631b1 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -92,6 +92,13 @@ jobs: env: OS: ${{ runner.os }} + - name: Test cargo dev new lint + run: | + cargo dev new_lint --name new_early_pass --pass early + cargo dev new_lint --name new_late_pass --pass late + cargo check + git reset --hard HEAD + # Cleanup - name: Run cargo-cache --autoclean run: | diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 1e032a7bc20..d951ca0e630 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -47,7 +47,7 @@ pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str fn create_lint(lint: &LintData) -> io::Result<()> { let (pass_type, pass_lifetimes, pass_import, context_import) = match lint.pass { "early" => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"), - "late" => ("LateLintPass", "<'_, '_>", "use rustc_hir::*;", "LateContext"), + "late" => ("LateLintPass", "<'_>", "use rustc_hir::*;", "LateContext"), _ => { unreachable!("`pass_type` should only ever be `early` or `late`!"); }, From eb8ede7f659da6c07d1f475aff9b0d46e5b49a79 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sun, 23 Aug 2020 11:29:06 +0200 Subject: [PATCH 484/526] Improve documentation related to the sync process --- CONTRIBUTING.md | 56 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5f7b1e85ee9..631064cd92c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -189,6 +189,35 @@ Clippy in the `rust-lang/rust` repository. For general information about `subtree`s in the Rust repository see [Rust's `CONTRIBUTING.md`][subtree]. +### Patching git-subtree to work with big repos + +Currently there's a bug in `git-subtree` that prevents it from working properly +with the [`rust-lang/rust`] repo. There's an open PR to fix that, but it's stall. +Before continuing with the following steps, we need to manually apply that fix to +our local copy of `git-subtree`. + +You can get the patched version of `git-subtree` from [here][gitgitgadget-pr]. +Put this file under `/usr/lib/git-core` (taking a backup of the previous file) +and make sure it has the proper permissions: + +```bash +sudo cp --backup /path/to/patched/git-subtree.sh /usr/lib/git-core/git-subtree +sudo chmod --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subtree +sudo chown root:root /usr/lib/git-core/git-subtree +``` + +_Note:_ The first time running `git subtree push` a cache has to be built. This +involves going through the complete Clippy history once. For this you have to +increase the stack limit though, which you can do with `ulimit -s 60000`. +Make sure to run the `ulimit` command from the same session you call git subtree. + +_Note:_ If you are a Debian user, `dash` is the shell used by default for scripts instead of `sh`. +This shell has a hardcoded recursion limit set to 1000. In order to make this process work, +you need to force the script to run `bash` instead. You can do this by editing the first +line of the `git-subtree` script and changing `sh` to `bash`. + +### Performing the sync + Here is a TL;DR version of the sync process (all of the following commands have to be run inside the `rust` directory): @@ -198,6 +227,7 @@ to be run inside the `rust` directory): # Make sure to change `your-github-name` to your github name in the following command git subtree push -P src/tools/clippy git@github.com:your-github-name/rust-clippy sync-from-rust ``` + _Note:_ This will directly push to the remote repository. You can also push to your local copy by replacing the remote address with `/path/to/rust-clippy` directory. @@ -213,14 +243,28 @@ to be run inside the `rust` directory): 3. Open a PR to `rust-lang/rust-clippy` and wait for it to get merged (to accelerate the process ping the `@rust-lang/clippy` team in your PR and/or ~~annoy~~ ask them in the [Discord] channel.) -4. Sync the `rust-lang/rust-clippy` master to the rust-copy of Clippy: + +### Syncing back changes in Clippy to [`rust-lang/rust`] + +To avoid flooding the [`rust-lang/rust`] PR queue, changes in Clippy's repo are synced back +in a bi-weekly basis if there's no urgent changes. This is done starting on the day of +the Rust stable release and then every two other weeks. That way we guarantee that +every feature in Clippy is available for 2 weeks in nightly, before it can get to beta. +For reference, the first sync following this cadence was performed the 2020-08-27. + +1. Make sure Clippy itself is up-to-date by following the steps outlined in the previous +section if necessary. + +2. Sync the `rust-lang/rust-clippy` master to the rust-copy of Clippy: ```bash git checkout -b sync-from-clippy git subtree pull -P src/tools/clippy https://github.com/rust-lang/rust-clippy master ``` -5. Open a PR to [`rust-lang/rust`] +3. Open a PR to [`rust-lang/rust`] -Also, you may want to define remotes, so you don't have to type out the remote +### Defining remotes + +You may want to define remotes, so you don't have to type out the remote addresses on every sync. You can do this with the following commands (these commands still have to be run inside the `rust` directory): @@ -241,12 +285,6 @@ You can then sync with the remote names from above, e.g.: $ git subtree push -P src/tools/clippy clippy-local sync-from-rust ``` -_Note:_ The first time running `git subtree push` a cache has to be built. This -involves going through the complete Clippy history once. For this you have to -increase the stack limit though, which you can do with `ulimit -s 60000`. For -this to work, you will need the fix of `git subtree` available -[here][gitgitgadget-pr]. - [gitgitgadget-pr]: https://github.com/gitgitgadget/git/pull/493 [subtree]: https://rustc-dev-guide.rust-lang.org/contributing.html#external-dependencies-subtree [`rust-lang/rust`]: https://github.com/rust-lang/rust From 8776db9f6d5163ca40232336dc51ad77eeb2b5e5 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sun, 23 Aug 2020 12:05:34 +0200 Subject: [PATCH 485/526] Fix ICE in `repeat_once` lint --- clippy_lints/src/repeat_once.rs | 14 +++++++------- tests/ui/crashes/ice-5944.rs | 13 +++++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 tests/ui/crashes/ice-5944.rs diff --git a/clippy_lints/src/repeat_once.rs b/clippy_lints/src/repeat_once.rs index 77c206002ea..c0890018d46 100644 --- a/clippy_lints/src/repeat_once.rs +++ b/clippy_lints/src/repeat_once.rs @@ -39,12 +39,12 @@ declare_lint_pass!(RepeatOnce => [REPEAT_ONCE]); impl<'tcx> LateLintPass<'tcx> for RepeatOnce { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind; + if let ExprKind::MethodCall(path, _, [receiver, count], _) = &expr.kind; if path.ident.name == sym!(repeat); - if let Some(Constant::Int(1)) = constant_context(cx, cx.typeck_results()).expr(&args[1]); - if !in_macro(args[0].span); + if let Some(Constant::Int(1)) = constant_context(cx, cx.typeck_results()).expr(&count); + if !in_macro(receiver.span); then { - let ty = walk_ptrs_ty(cx.typeck_results().expr_ty(&args[0])); + let ty = walk_ptrs_ty(cx.typeck_results().expr_ty(&receiver)); if ty.is_str() { span_lint_and_sugg( cx, @@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce { expr.span, "calling `repeat(1)` on str", "consider using `.to_string()` instead", - format!("{}.to_string()", snippet(cx, args[0].span, r#""...""#)), + format!("{}.to_string()", snippet(cx, receiver.span, r#""...""#)), Applicability::MachineApplicable, ); } else if ty.builtin_index().is_some() { @@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce { expr.span, "calling `repeat(1)` on slice", "consider using `.to_vec()` instead", - format!("{}.to_vec()", snippet(cx, args[0].span, r#""...""#)), + format!("{}.to_vec()", snippet(cx, receiver.span, r#""...""#)), Applicability::MachineApplicable, ); } else if is_type_diagnostic_item(cx, ty, sym!(string_type)) { @@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce { expr.span, "calling `repeat(1)` on a string literal", "consider using `.clone()` instead", - format!("{}.clone()", snippet(cx, args[0].span, r#""...""#)), + format!("{}.clone()", snippet(cx, receiver.span, r#""...""#)), Applicability::MachineApplicable, ); } diff --git a/tests/ui/crashes/ice-5944.rs b/tests/ui/crashes/ice-5944.rs new file mode 100644 index 00000000000..5caf29c6197 --- /dev/null +++ b/tests/ui/crashes/ice-5944.rs @@ -0,0 +1,13 @@ +#![warn(clippy::repeat_once)] + +trait Repeat { + fn repeat(&self) {} +} + +impl Repeat for usize { + fn repeat(&self) {} +} + +fn main() { + let _ = 42.repeat(); +} From 91b200c62b7c464cb890c68230ab2d74605a60d0 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Sun, 23 Aug 2020 22:16:24 +1200 Subject: [PATCH 486/526] Fix fp in `borrow_interior_mutable_const` Fix false positive when referencing a field behind a pointer. --- clippy_lints/src/non_copy_const.rs | 15 +++++++- tests/ui/borrow_interior_mutable_const.rs | 35 ++++++++++++++++++- tests/ui/borrow_interior_mutable_const.stderr | 32 ++++++++--------- 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 031d69e86a1..f1df634701d 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -211,8 +211,21 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { needs_check_adjustment = false; }, ExprKind::Field(..) => { - dereferenced_expr = parent_expr; needs_check_adjustment = true; + + // Check whether implicit dereferences happened; + // if so, no need to go further up + // because of the same reason as the `ExprKind::Unary` case. + if cx + .typeck_results() + .expr_adjustments(dereferenced_expr) + .iter() + .any(|adj| matches!(adj.kind, Adjust::Deref(_))) + { + break; + } + + dereferenced_expr = parent_expr; }, ExprKind::Index(e, _) if ptr::eq(&**e, cur_expr) => { // `e[i]` => desugared to `*Index::index(&e, i)`, diff --git a/tests/ui/borrow_interior_mutable_const.rs b/tests/ui/borrow_interior_mutable_const.rs index fef9f4f39f8..310769cd002 100644 --- a/tests/ui/borrow_interior_mutable_const.rs +++ b/tests/ui/borrow_interior_mutable_const.rs @@ -2,7 +2,7 @@ #![allow(clippy::declare_interior_mutable_const, clippy::ref_in_deref)] use std::borrow::Cow; -use std::cell::Cell; +use std::cell::{Cell, UnsafeCell}; use std::fmt::Display; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Once; @@ -30,6 +30,37 @@ impl Trait<u32> for u64 { const ATOMIC: AtomicUsize = AtomicUsize::new(9); } +// This is just a pointer that can be safely dereferended, +// it's semantically the same as `&'static T`; +// but it isn't allowed make a static reference from an arbitrary integer value at the moment. +// For more information, please see the issue #5918. +pub struct StaticRef<T> { + ptr: *const T, +} + +impl<T> StaticRef<T> { + /// Create a new `StaticRef` from a raw pointer + /// + /// ## Safety + /// + /// Callers must pass in a reference to statically allocated memory which + /// does not overlap with other values. + pub const unsafe fn new(ptr: *const T) -> StaticRef<T> { + StaticRef { ptr } + } +} + +impl<T> std::ops::Deref for StaticRef<T> { + type Target = T; + + fn deref(&self) -> &'static T { + unsafe { &*self.ptr } + } +} + +// use a tuple to make sure referencing a field behind a pointer isn't linted. +const CELL_REF: StaticRef<(UnsafeCell<u32>,)> = unsafe { StaticRef::new(std::ptr::null()) }; + fn main() { ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability @@ -82,4 +113,6 @@ fn main() { assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability assert_eq!(NO_ANN.to_string(), "70"); // should never lint this. + + let _ = &CELL_REF.0; } diff --git a/tests/ui/borrow_interior_mutable_const.stderr b/tests/ui/borrow_interior_mutable_const.stderr index dc738064a17..1e0b3e4d20a 100644 --- a/tests/ui/borrow_interior_mutable_const.stderr +++ b/tests/ui/borrow_interior_mutable_const.stderr @@ -1,5 +1,5 @@ error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:34:5 + --> $DIR/borrow_interior_mutable_const.rs:65:5 | LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^ @@ -8,7 +8,7 @@ LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:35:16 + --> $DIR/borrow_interior_mutable_const.rs:66:16 | LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability | ^^^^^^ @@ -16,7 +16,7 @@ LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutabi = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:38:22 + --> $DIR/borrow_interior_mutable_const.rs:69:22 | LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -24,7 +24,7 @@ LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:39:25 + --> $DIR/borrow_interior_mutable_const.rs:70:25 | LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -32,7 +32,7 @@ LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:40:27 + --> $DIR/borrow_interior_mutable_const.rs:71:27 | LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -40,7 +40,7 @@ LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:41:26 + --> $DIR/borrow_interior_mutable_const.rs:72:26 | LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -48,7 +48,7 @@ LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:52:14 + --> $DIR/borrow_interior_mutable_const.rs:83:14 | LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:53:14 + --> $DIR/borrow_interior_mutable_const.rs:84:14 | LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:54:19 + --> $DIR/borrow_interior_mutable_const.rs:85:19 | LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:55:14 + --> $DIR/borrow_interior_mutable_const.rs:86:14 | LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:56:13 + --> $DIR/borrow_interior_mutable_const.rs:87:13 | LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mu = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:62:13 + --> $DIR/borrow_interior_mutable_const.rs:93:13 | LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:67:5 + --> $DIR/borrow_interior_mutable_const.rs:98:5 | LL | CELL.set(2); //~ ERROR interior mutability | ^^^^ @@ -104,7 +104,7 @@ LL | CELL.set(2); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:68:16 + --> $DIR/borrow_interior_mutable_const.rs:99:16 | LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability | ^^^^ @@ -112,7 +112,7 @@ LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:81:5 + --> $DIR/borrow_interior_mutable_const.rs:112:5 | LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/borrow_interior_mutable_const.rs:82:16 + --> $DIR/borrow_interior_mutable_const.rs:113:16 | LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability | ^^^^^^^^^^^ From b05077ea75f4585551650fc2d40a196ae437393d Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sun, 23 Aug 2020 22:20:55 +0200 Subject: [PATCH 487/526] Apply suggestions from PR review --- CONTRIBUTING.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 631064cd92c..54777810abb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -192,7 +192,7 @@ For general information about `subtree`s in the Rust repository see [Rust's ### Patching git-subtree to work with big repos Currently there's a bug in `git-subtree` that prevents it from working properly -with the [`rust-lang/rust`] repo. There's an open PR to fix that, but it's stall. +with the [`rust-lang/rust`] repo. There's an open PR to fix that, but it's stale. Before continuing with the following steps, we need to manually apply that fix to our local copy of `git-subtree`. @@ -203,7 +203,7 @@ and make sure it has the proper permissions: ```bash sudo cp --backup /path/to/patched/git-subtree.sh /usr/lib/git-core/git-subtree sudo chmod --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subtree -sudo chown root:root /usr/lib/git-core/git-subtree +sudo chown --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subtree ``` _Note:_ The first time running `git subtree push` a cache has to be built. This @@ -248,9 +248,11 @@ to be run inside the `rust` directory): To avoid flooding the [`rust-lang/rust`] PR queue, changes in Clippy's repo are synced back in a bi-weekly basis if there's no urgent changes. This is done starting on the day of -the Rust stable release and then every two other weeks. That way we guarantee that +the Rust stable release and then every other week. That way we guarantee that every feature in Clippy is available for 2 weeks in nightly, before it can get to beta. -For reference, the first sync following this cadence was performed the 2020-08-27. +For reference, the first sync following this cadence was performed the 2020-08-27. + +All of the following commands have to be run inside the `rust` directory. 1. Make sure Clippy itself is up-to-date by following the steps outlined in the previous section if necessary. From b2c226679251bb795d786d7cdd11d2e2c9d0e685 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Tue, 18 Aug 2020 23:00:21 +0900 Subject: [PATCH 488/526] Fix FP for `redundant_closure_call` Visit the nested things like function body when checking closure call. --- clippy_lints/src/redundant_closure_call.rs | 17 +++++++++++------ tests/ui/redundant_closure_call_late.rs | 12 ++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index 8aa478ea2d6..d8fad217e5a 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -95,12 +95,17 @@ impl EarlyLintPass for RedundantClosureCall { impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { - fn count_closure_usage<'tcx>(block: &'tcx hir::Block<'_>, path: &'tcx hir::Path<'tcx>) -> usize { - struct ClosureUsageCount<'tcx> { + fn count_closure_usage<'a, 'tcx>( + cx: &'a LateContext<'tcx>, + block: &'tcx hir::Block<'_>, + path: &'tcx hir::Path<'tcx>, + ) -> usize { + struct ClosureUsageCount<'a, 'tcx> { + cx: &'a LateContext<'tcx>, path: &'tcx hir::Path<'tcx>, count: usize, }; - impl<'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'tcx> { + impl<'a, 'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> { type Map = Map<'tcx>; fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { @@ -117,10 +122,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { } fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> { - hir_visit::NestedVisitorMap::None + hir_visit::NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) } }; - let mut closure_usage_count = ClosureUsageCount { path, count: 0 }; + let mut closure_usage_count = ClosureUsageCount { cx, path, count: 0 }; closure_usage_count.visit_block(block); closure_usage_count.count } @@ -136,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { if let hir::ExprKind::Call(ref closure, _) = call.kind; if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind; if ident == path.segments[0].ident; - if count_closure_usage(block, path) == 1; + if count_closure_usage(cx, block, path) == 1; then { span_lint( cx, diff --git a/tests/ui/redundant_closure_call_late.rs b/tests/ui/redundant_closure_call_late.rs index e29a1dce0c7..1f4864b7289 100644 --- a/tests/ui/redundant_closure_call_late.rs +++ b/tests/ui/redundant_closure_call_late.rs @@ -24,4 +24,16 @@ fn main() { let shadowed_closure = || 2; i = shadowed_closure(); i = shadowed_closure(); + + // Fix FP in #5916 + let mut x; + let create = || 2 * 2; + x = create(); + fun(move || { + x = create(); + }) +} + +fn fun<T: 'static + FnMut()>(mut f: T) { + f(); } From 9fe0ac36a53dfba14f5f33f5bab2fd243fb2c18e Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Mon, 24 Aug 2020 10:11:53 +0900 Subject: [PATCH 489/526] Avoid period in lint message according to convention --- clippy_lints/src/redundant_closure_call.rs | 2 +- tests/ui/redundant_closure_call_early.stderr | 4 ++-- tests/ui/redundant_closure_call_fixable.stderr | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index d8fad217e5a..49cb2ffc4e3 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -77,7 +77,7 @@ impl EarlyLintPass for RedundantClosureCall { cx, REDUNDANT_CLOSURE_CALL, expr.span, - "try not to call a closure in the expression where it is declared.", + "try not to call a closure in the expression where it is declared", |diag| { if decl.inputs.is_empty() { let mut app = Applicability::MachineApplicable; diff --git a/tests/ui/redundant_closure_call_early.stderr b/tests/ui/redundant_closure_call_early.stderr index 79f27663461..2735e41738f 100644 --- a/tests/ui/redundant_closure_call_early.stderr +++ b/tests/ui/redundant_closure_call_early.stderr @@ -1,4 +1,4 @@ -error: try not to call a closure in the expression where it is declared. +error: try not to call a closure in the expression where it is declared --> $DIR/redundant_closure_call_early.rs:9:17 | LL | let mut k = (|m| m + 1)(i); @@ -6,7 +6,7 @@ LL | let mut k = (|m| m + 1)(i); | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` -error: try not to call a closure in the expression where it is declared. +error: try not to call a closure in the expression where it is declared --> $DIR/redundant_closure_call_early.rs:12:9 | LL | k = (|a, b| a * b)(1, 5); diff --git a/tests/ui/redundant_closure_call_fixable.stderr b/tests/ui/redundant_closure_call_fixable.stderr index 644161d9f5d..afd704ef12a 100644 --- a/tests/ui/redundant_closure_call_fixable.stderr +++ b/tests/ui/redundant_closure_call_fixable.stderr @@ -1,4 +1,4 @@ -error: try not to call a closure in the expression where it is declared. +error: try not to call a closure in the expression where it is declared --> $DIR/redundant_closure_call_fixable.rs:7:13 | LL | let a = (|| 42)(); From ce8915c85cebaa30e6846322e0ab44a4f4f9cb65 Mon Sep 17 00:00:00 2001 From: rail-rain <12975677+rail-rain@users.noreply.github.com> Date: Mon, 24 Aug 2020 19:08:38 +1200 Subject: [PATCH 490/526] typo Co-authored-by: Thibaud <ThibsG@users.noreply.github.com> --- tests/ui/borrow_interior_mutable_const.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/borrow_interior_mutable_const.rs b/tests/ui/borrow_interior_mutable_const.rs index 310769cd002..a414832bcd3 100644 --- a/tests/ui/borrow_interior_mutable_const.rs +++ b/tests/ui/borrow_interior_mutable_const.rs @@ -32,7 +32,7 @@ impl Trait<u32> for u64 { // This is just a pointer that can be safely dereferended, // it's semantically the same as `&'static T`; -// but it isn't allowed make a static reference from an arbitrary integer value at the moment. +// but it isn't allowed to make a static reference from an arbitrary integer value at the moment. // For more information, please see the issue #5918. pub struct StaticRef<T> { ptr: *const T, From 3d820f71fe820c0bb7a1204e28ce549407a937cc Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Mon, 24 Aug 2020 14:01:27 +0200 Subject: [PATCH 491/526] Fix incorrect suggestion when `clone_on_ref_ptr` is triggered in macros --- clippy_lints/src/methods/mod.rs | 13 +++++++------ tests/ui/unnecessary_clone.rs | 18 ++++++++++++++++++ tests/ui/unnecessary_clone.stderr | 8 +++++++- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 22942d9fb0c..4f0a533592c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2150,18 +2150,19 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir:: return; }; + let snippet = if in_macro(arg.span) { + snippet_with_macro_callsite(cx, arg.span, "_") + } else { + snippet(cx, arg.span, "_") + }; + span_lint_and_sugg( cx, CLONE_ON_REF_PTR, expr.span, "using `.clone()` on a ref-counted pointer", "try this", - format!( - "{}::<{}>::clone(&{})", - caller_type, - subst.type_at(0), - snippet(cx, arg.span, "_") - ), + format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet), Applicability::Unspecified, // Sometimes unnecessary ::<_> after Rc/Arc/Weak ); } diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 2c9d4d39e6c..e785ac02feb 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -90,3 +90,21 @@ mod many_derefs { let _ = &encoded.clone(); } } + +mod issue2076 { + use std::rc::Rc; + + macro_rules! try_opt { + ($expr: expr) => { + match $expr { + Some(value) => value, + None => return None, + } + }; + } + + fn func() -> Option<Rc<u8>> { + let rc = Rc::new(42); + Some(try_opt!(Some(rc)).clone()) + } +} diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 113fab69009..5ffa6c4fd06 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -96,5 +96,11 @@ help: or try being explicit if you are sure, that you want to clone a reference LL | let _ = &<&[u8]>::clone(encoded); | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors +error: using `.clone()` on a ref-counted pointer + --> $DIR/unnecessary_clone.rs:108:14 + | +LL | Some(try_opt!(Some(rc)).clone()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Rc::<u8>::clone(&try_opt!(Some(rc)))` + +error: aborting due to 12 previous errors From 680c68153bced747c90947e0265c92076edcb838 Mon Sep 17 00:00:00 2001 From: Bastian <bastian@cmbt.de> Date: Mon, 24 Aug 2020 16:31:51 +0200 Subject: [PATCH 492/526] Added a lint which corrects expressions like (a - b) < f32::EPSILON --- CHANGELOG.md | 1 + .../src/float_equality_without_abs.rs | 112 ++++++++++++++++++ clippy_lints/src/lib.rs | 5 + src/lintlist/mod.rs | 7 ++ tests/ui/float_equality_without_abs.rs | 31 +++++ tests/ui/float_equality_without_abs.stderr | 70 +++++++++++ 6 files changed, 226 insertions(+) create mode 100644 clippy_lints/src/float_equality_without_abs.rs create mode 100644 tests/ui/float_equality_without_abs.rs create mode 100644 tests/ui/float_equality_without_abs.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ce63c0a157..a5da0f7b767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1498,6 +1498,7 @@ Released 2018-09-13 [`float_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_arithmetic [`float_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp [`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const +[`float_equality_without_abs`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_equality_without_abs [`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons [`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools [`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast diff --git a/clippy_lints/src/float_equality_without_abs.rs b/clippy_lints/src/float_equality_without_abs.rs new file mode 100644 index 00000000000..c8e53ce6f95 --- /dev/null +++ b/clippy_lints/src/float_equality_without_abs.rs @@ -0,0 +1,112 @@ +use crate::utils::{match_qpath, snippet, span_lint_and_sugg}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Spanned; + +declare_clippy_lint! { + /// **What it does:** Checks for statements of the form `(a - b) < f32::EPSILON` or + /// `(a - b) < f64::EPSILON`. Notes the missing `.abs()`. + /// + /// **Why is this bad?** The code without `.abs()` is more likely to have a bug. + /// + /// **Known problems:** If the user can ensure that b is larger than a, the `.abs()` is + /// technically unneccessary. However, it will make the code more robust and doesn't have any + /// large performance implications. If the abs call was deliberately left out for performance + /// reasons, it is probably better to state this explicitly in the code, which then can be done + /// with an allow. + /// + /// **Example:** + /// + /// ```rust + /// pub fn is_roughly_equal(a: f32, b: f32) -> bool { + /// (a - b) < f32::EPSILON + /// } + /// ``` + /// Use instead: + /// ```rust + /// pub fn is_roughly_equal(a: f32, b: f32) -> bool { + /// (a - b).abs() < f32::EPSILON + /// } + /// ``` + pub FLOAT_EQUALITY_WITHOUT_ABS, + correctness, + "float equality check without `.abs()`" +} + +declare_lint_pass!(FloatEqualityWithoutAbs => [FLOAT_EQUALITY_WITHOUT_ABS]); + +impl<'tcx> LateLintPass<'tcx> for FloatEqualityWithoutAbs { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + let lhs; + let rhs; + + // check if expr is a binary expression with a lt or gt operator + if let ExprKind::Binary(op, ref left, ref right) = expr.kind { + match op.node { + BinOpKind::Lt => { + lhs = left; + rhs = right; + }, + BinOpKind::Gt => { + lhs = right; + rhs = left; + }, + _ => return, + }; + } else { + return; + } + + if_chain! { + + // left hand side is a substraction + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Sub, + .. + }, + val_l, + val_r, + ) = lhs.kind; + + // right hand side matches either f32::EPSILON or f64::EPSILON + if let ExprKind::Path(ref epsilon_path) = rhs.kind; + if match_qpath(epsilon_path, &["f32", "EPSILON"]) || match_qpath(epsilon_path, &["f64", "EPSILON"]); + + // values of the substractions on the left hand side are of the type float + let t_val_l = cx.typeck_results().expr_ty(val_l); + let t_val_r = cx.typeck_results().expr_ty(val_r); + if let ty::Float(_) = t_val_l.kind; + if let ty::Float(_) = t_val_r.kind; + + then { + // get the snippet string + let lhs_string = snippet( + cx, + lhs.span, + "(...)", + ); + // format the suggestion + let suggestion = if lhs_string.starts_with('(') { + format!("{}.abs()", lhs_string) + } else { + format!("({}).abs()", lhs_string) + }; + // spans the lint + span_lint_and_sugg( + cx, + FLOAT_EQUALITY_WITHOUT_ABS, + expr.span, + "float equality check without `.abs()`", + "add `.abs()`", + suggestion, + Applicability::MaybeIncorrect, + ); + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d45394ab8d2..f78de7a175f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -193,6 +193,7 @@ mod excessive_bools; mod exit; mod explicit_write; mod fallible_impl_from; +mod float_equality_without_abs; mod float_literal; mod floating_point_arithmetic; mod format; @@ -549,6 +550,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &exit::EXIT, &explicit_write::EXPLICIT_WRITE, &fallible_impl_from::FALLIBLE_IMPL_FROM, + &float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS, &float_literal::EXCESSIVE_PRECISION, &float_literal::LOSSY_FLOAT_LITERAL, &floating_point_arithmetic::IMPRECISE_FLOPS, @@ -1093,6 +1095,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive); store.register_late_pass(|| box repeat_once::RepeatOnce); store.register_late_pass(|| box self_assignment::SelfAssignment); + store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1268,6 +1271,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&eval_order_dependence::DIVERGING_SUB_EXPRESSION), LintId::of(&eval_order_dependence::EVAL_ORDER_DEPENDENCE), LintId::of(&explicit_write::EXPLICIT_WRITE), + LintId::of(&float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), LintId::of(&float_literal::EXCESSIVE_PRECISION), LintId::of(&format::USELESS_FORMAT), LintId::of(&formatting::POSSIBLE_MISSING_COMMA), @@ -1686,6 +1690,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), LintId::of(&eq_op::EQ_OP), LintId::of(&erasing_op::ERASING_OP), + LintId::of(&float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), LintId::of(&formatting::POSSIBLE_MISSING_COMMA), LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF), LintId::of(&if_let_mutex::IF_LET_MUTEX), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index c50c6b900ae..eadd2621a40 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -661,6 +661,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "misc", }, + Lint { + name: "float_equality_without_abs", + group: "correctness", + desc: "float equality check without `.abs()`", + deprecation: None, + module: "float_equality_without_abs", + }, Lint { name: "fn_address_comparisons", group: "correctness", diff --git a/tests/ui/float_equality_without_abs.rs b/tests/ui/float_equality_without_abs.rs new file mode 100644 index 00000000000..d40fa00c315 --- /dev/null +++ b/tests/ui/float_equality_without_abs.rs @@ -0,0 +1,31 @@ +#![warn(clippy::float_equality_without_abs)] + +pub fn is_roughly_equal(a: f32, b: f32) -> bool { + (a - b) < f32::EPSILON +} + +pub fn main() { + // all errors + is_roughly_equal(1.0, 2.0); + let a = 0.05; + let b = 0.0500001; + + let _ = (a - b) < f32::EPSILON; + let _ = a - b < f32::EPSILON; + let _ = a - b.abs() < f32::EPSILON; + let _ = (a as f64 - b as f64) < f64::EPSILON; + let _ = 1.0 - 2.0 < f32::EPSILON; + + let _ = f32::EPSILON > (a - b); + let _ = f32::EPSILON > a - b; + let _ = f32::EPSILON > a - b.abs(); + let _ = f64::EPSILON > (a as f64 - b as f64); + let _ = f32::EPSILON > 1.0 - 2.0; + + // those are correct + let _ = (a - b).abs() < f32::EPSILON; + let _ = (a as f64 - b as f64).abs() < f64::EPSILON; + + let _ = f32::EPSILON > (a - b).abs(); + let _ = f64::EPSILON > (a as f64 - b as f64).abs(); +} diff --git a/tests/ui/float_equality_without_abs.stderr b/tests/ui/float_equality_without_abs.stderr new file mode 100644 index 00000000000..74b9078afe8 --- /dev/null +++ b/tests/ui/float_equality_without_abs.stderr @@ -0,0 +1,70 @@ +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:4:5 + | +LL | (a - b) < f32::EPSILON + | ^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b).abs()` + | + = note: `-D clippy::float-equality-without-abs` implied by `-D warnings` + +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:13:13 + | +LL | let _ = (a - b) < f32::EPSILON; + | ^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b).abs()` + +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:14:13 + | +LL | let _ = a - b < f32::EPSILON; + | ^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b).abs()` + +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:15:13 + | +LL | let _ = a - b.abs() < f32::EPSILON; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b.abs()).abs()` + +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:16:13 + | +LL | let _ = (a as f64 - b as f64) < f64::EPSILON; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a as f64 - b as f64).abs()` + +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:17:13 + | +LL | let _ = 1.0 - 2.0 < f32::EPSILON; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(1.0 - 2.0).abs()` + +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:19:13 + | +LL | let _ = f32::EPSILON > (a - b); + | ^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b).abs()` + +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:20:13 + | +LL | let _ = f32::EPSILON > a - b; + | ^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b).abs()` + +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:21:13 + | +LL | let _ = f32::EPSILON > a - b.abs(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b.abs()).abs()` + +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:22:13 + | +LL | let _ = f64::EPSILON > (a as f64 - b as f64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a as f64 - b as f64).abs()` + +error: float equality check without `.abs()` + --> $DIR/float_equality_without_abs.rs:23:13 + | +LL | let _ = f32::EPSILON > 1.0 - 2.0; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(1.0 - 2.0).abs()` + +error: aborting due to 11 previous errors + From e9964f2e8a1903d46e576f67122e234f719a90f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Fri, 21 Aug 2020 02:03:57 +0200 Subject: [PATCH 493/526] stable_sort_primitive: print the type that is being sorted in the lint message --- clippy_lints/src/stable_sort_primitive.rs | 10 +++++---- clippy_lints/src/utils/mod.rs | 27 +++++++++++++++++++---- tests/ui/stable_sort_primitive.stderr | 14 ++++++------ 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/stable_sort_primitive.rs b/clippy_lints/src/stable_sort_primitive.rs index 22c49a20451..99e4b293ac6 100644 --- a/clippy_lints/src/stable_sort_primitive.rs +++ b/clippy_lints/src/stable_sort_primitive.rs @@ -86,6 +86,7 @@ struct LintDetection { slice_name: String, method: SortingKind, method_args: String, + slice_type: String, } fn detect_stable_sort_primitive(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintDetection> { @@ -93,10 +94,10 @@ fn detect_stable_sort_primitive(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind; if let Some(slice) = &args.get(0); if let Some(method) = SortingKind::from_stable_name(&method_name.ident.name.as_str()); - if is_slice_of_primitives(cx, slice); + if let Some(slice_type) = is_slice_of_primitives(cx, slice); then { let args_str = args.iter().skip(1).map(|arg| Sugg::hir(cx, arg, "..").to_string()).collect::<Vec<String>>().join(", "); - Some(LintDetection { slice_name: Sugg::hir(cx, slice, "..").to_string(), method, method_args: args_str }) + Some(LintDetection { slice_name: Sugg::hir(cx, slice, "..").to_string(), method, method_args: args_str, slice_type }) } else { None } @@ -111,9 +112,10 @@ impl LateLintPass<'_> for StableSortPrimitive { STABLE_SORT_PRIMITIVE, expr.span, format!( - "used {} instead of {}", + "used {} instead of {} to sort primitive type `{}`", detection.method.stable_name(), - detection.method.unstable_name() + detection.method.unstable_name(), + detection.slice_type, ) .as_str(), "try", diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 2aef995cec4..25301d6dede 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1409,11 +1409,13 @@ pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool { } } -/// Returns true iff the given expression is a slice of primitives (as defined in the -/// `is_recursively_primitive_type` function). -pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { +/// Returns Option<String> where String is a textual representation of the type encapsulated in the +/// slice iff the given expression is a slice of primitives (as defined in the +/// `is_recursively_primitive_type` function) and None otherwise. +pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> { let expr_type = cx.typeck_results().expr_ty_adjusted(expr); - match expr_type.kind { + let expr_kind = &expr_type.kind; + let is_primitive = match expr_kind { ty::Slice(ref element_type) | ty::Ref( _, @@ -1424,7 +1426,24 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { _, ) => is_recursively_primitive_type(element_type), _ => false, + }; + + if is_primitive { + // if we have wrappers like Array, Slice or Tuple, print these + // and get the type enclosed in the slice ref + match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind { + ty::Slice(..) => return Some("slice".into()), + ty::Array(..) => return Some("array".into()), + ty::Tuple(..) => return Some("tuple".into()), + _ => { + // is_recursively_primitive_type() should have taken care + // of the rest and we can rely on the type that is found + let refs_peeled = expr_type.peel_refs(); + return Some(refs_peeled.walk().last().unwrap().to_string()); + }, + } } + None } #[macro_export] diff --git a/tests/ui/stable_sort_primitive.stderr b/tests/ui/stable_sort_primitive.stderr index b73012a4691..780389f32bc 100644 --- a/tests/ui/stable_sort_primitive.stderr +++ b/tests/ui/stable_sort_primitive.stderr @@ -1,4 +1,4 @@ -error: used sort instead of sort_unstable +error: used sort instead of sort_unstable to sort primitive type `i32` --> $DIR/stable_sort_primitive.rs:7:5 | LL | vec.sort(); @@ -6,37 +6,37 @@ LL | vec.sort(); | = note: `-D clippy::stable-sort-primitive` implied by `-D warnings` -error: used sort instead of sort_unstable +error: used sort instead of sort_unstable to sort primitive type `bool` --> $DIR/stable_sort_primitive.rs:9:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: used sort instead of sort_unstable +error: used sort instead of sort_unstable to sort primitive type `char` --> $DIR/stable_sort_primitive.rs:11:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: used sort instead of sort_unstable +error: used sort instead of sort_unstable to sort primitive type `str` --> $DIR/stable_sort_primitive.rs:13:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: used sort instead of sort_unstable +error: used sort instead of sort_unstable to sort primitive type `tuple` --> $DIR/stable_sort_primitive.rs:15:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: used sort instead of sort_unstable +error: used sort instead of sort_unstable to sort primitive type `array` --> $DIR/stable_sort_primitive.rs:17:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: used sort instead of sort_unstable +error: used sort instead of sort_unstable to sort primitive type `i32` --> $DIR/stable_sort_primitive.rs:19:5 | LL | arr.sort(); From 91028326927266af5051b5d172dc3162d147a4d9 Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Tue, 25 Aug 2020 05:53:28 +0200 Subject: [PATCH 494/526] Fix incorrect comment --- tests/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fmt.rs b/tests/fmt.rs index 3aff8741f60..ee3ce26ee40 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -7,7 +7,7 @@ fn fmt() { return; } - // Skip this test if rustup nightly is unavailable + // Skip this test if rustfmt nightly is unavailable let rustup_output = Command::new("rustup") .args(&["component", "list", "--toolchain", "nightly"]) .output() From 48d473691359f7c59d7348937f71de0e5aa4ae12 Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Tue, 25 Aug 2020 05:53:28 +0200 Subject: [PATCH 495/526] Simplify fmt test by using the clippy dev alias --- tests/fmt.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/fmt.rs b/tests/fmt.rs index ee3ce26ee40..d529952bc69 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -19,12 +19,9 @@ fn fmt() { } let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let dev_dir = root_dir.join("clippy_dev"); - let target_dir = root_dir.join("target"); - let target_dir = target_dir.to_str().unwrap(); let output = Command::new("cargo") - .current_dir(dev_dir) - .args(&["+nightly", "run", "--target-dir", target_dir, "--", "fmt", "--check"]) + .current_dir(root_dir) + .args(&["dev", "fmt", "--check"]) .output() .unwrap(); From c7dc9c3cf7dc8a810ed0456834cd162055847e9d Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Tue, 25 Aug 2020 05:53:28 +0200 Subject: [PATCH 496/526] Fix intermittent build error The fmt test will cause clippy dev to be compiled and run. The clippy dev dependencies are currently stored at `target/debug/deps` when this happens. This location sometimes causes conflicts with ui tests which result in the build error "thread 'compile_test' panicked at 'Found multiple rlibs for crate `regex` ...". This commit forces the clippy_dev dependencies to be stored under `clippy_dev/target/` which seems to resolve this problem. --- .cargo/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cargo/config b/.cargo/config index 2bad3b9c57f..e70da43ab47 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,6 +1,6 @@ [alias] uitest = "test --test compile-test" -dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --" +dev = "run --target-dir clippy_dev/target --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --" [build] rustflags = ["-Zunstable-options"] From 179df0bd15f9f866b4b3e275ed97aa8168a5b702 Mon Sep 17 00:00:00 2001 From: Bastian <bastian@cmbt.de> Date: Tue, 25 Aug 2020 13:41:39 +0200 Subject: [PATCH 497/526] Added F32::EPSILON and F64::EPSILON to paths.rs --- clippy_lints/src/float_equality_without_abs.rs | 4 ++-- clippy_lints/src/utils/paths.rs | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/float_equality_without_abs.rs b/clippy_lints/src/float_equality_without_abs.rs index c8e53ce6f95..dc1c3bfc9ff 100644 --- a/clippy_lints/src/float_equality_without_abs.rs +++ b/clippy_lints/src/float_equality_without_abs.rs @@ -1,4 +1,4 @@ -use crate::utils::{match_qpath, snippet, span_lint_and_sugg}; +use crate::utils::{match_qpath, paths, snippet, span_lint_and_sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatEqualityWithoutAbs { // right hand side matches either f32::EPSILON or f64::EPSILON if let ExprKind::Path(ref epsilon_path) = rhs.kind; - if match_qpath(epsilon_path, &["f32", "EPSILON"]) || match_qpath(epsilon_path, &["f64", "EPSILON"]); + if match_qpath(epsilon_path, &paths::F32_EPSILON) || match_qpath(epsilon_path, &paths::F64_EPSILON); // values of the substractions on the left hand side are of the type float let t_val_l = cx.typeck_results().expr_ty(val_l); diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index b6a1e0a6aa9..d44854aefe9 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -35,6 +35,8 @@ pub const DROP_TRAIT: [&str; 4] = ["core", "ops", "drop", "Drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"]; pub const EXIT: [&str; 3] = ["std", "process", "exit"]; +pub const F32_EPSILON: [&str; 2] = ["f32", "EPSILON"]; +pub const F64_EPSILON: [&str; 2] = ["f64", "EPSILON"]; pub const FILE: [&str; 3] = ["std", "fs", "File"]; pub const FILE_TYPE: [&str; 3] = ["std", "fs", "FileType"]; pub const FMT_ARGUMENTS_NEW_V1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"]; From acc6b6ce07a5816cbfdaba7798edfc5b22ac976b Mon Sep 17 00:00:00 2001 From: Philipp Krones <hello@philkrones.com> Date: Tue, 25 Aug 2020 18:01:08 +0200 Subject: [PATCH 498/526] Fix typo --- tests/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fmt.rs b/tests/fmt.rs index d529952bc69..7616d8001e8 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -7,7 +7,7 @@ fn fmt() { return; } - // Skip this test if rustfmt nightly is unavailable + // Skip this test if nightly rustfmt is unavailable let rustup_output = Command::new("rustup") .args(&["component", "list", "--toolchain", "nightly"]) .output() From 3b1e5d6ff79f93e0215c6fb4c802167834ea4e15 Mon Sep 17 00:00:00 2001 From: Scott McMurray <scottmcm@users.noreply.github.com> Date: Tue, 25 Aug 2020 12:05:02 -0700 Subject: [PATCH 499/526] Re-enable len_zero for ranges now that `is_empty` is stable on them --- clippy_lints/src/len_zero.rs | 17 +---------------- tests/ui/len_zero.fixed | 8 -------- tests/ui/len_zero.rs | 8 -------- tests/ui/len_zero_ranges.fixed | 10 ++++++---- tests/ui/len_zero_ranges.rs | 10 ++++++---- tests/ui/len_zero_ranges.stderr | 10 ++++++++-- 6 files changed, 21 insertions(+), 42 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index e5daa30f8ca..b691d363d2f 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,4 +1,4 @@ -use crate::utils::{get_item_name, higher, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::{get_item_name, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; use rustc_ast::ast::LitKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -260,17 +260,6 @@ fn check_len( /// Checks if this type has an `is_empty` method. fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - /// Special case ranges until `range_is_empty` is stabilized. See issue 3807. - fn should_skip_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - higher::range(expr).map_or(false, |_| { - !cx.tcx - .features() - .declared_lib_features - .iter() - .any(|(name, _)| name.as_str() == "range_is_empty") - }) - } - /// Gets an `AssocItem` and return true if it matches `is_empty(self)`. fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool { if let ty::AssocKind::Fn = item.kind { @@ -296,10 +285,6 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { }) } - if should_skip_range(cx, expr) { - return false; - } - let ty = &walk_ptrs_ty(cx.typeck_results().expr_ty(expr)); match ty.kind { ty::Dynamic(ref tt, ..) => tt.principal().map_or(false, |principal| { diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed index d81676a3d9f..1f3b8ac99b1 100644 --- a/tests/ui/len_zero.fixed +++ b/tests/ui/len_zero.fixed @@ -141,11 +141,3 @@ fn main() { fn test_slice(b: &[u8]) { if !b.is_empty() {} } - -mod issue_3807 { - // Avoid suggesting changes to ranges if the user did not enable `range_is_empty`. - // See https://github.com/rust-lang/rust/issues/48111#issuecomment-445132965 - fn no_suggestion() { - let _ = (0..42).len() == 0; - } -} diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index ecdba921a5d..dc21de0001b 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -141,11 +141,3 @@ fn main() { fn test_slice(b: &[u8]) { if b.len() != 0 {} } - -mod issue_3807 { - // Avoid suggesting changes to ranges if the user did not enable `range_is_empty`. - // See https://github.com/rust-lang/rust/issues/48111#issuecomment-445132965 - fn no_suggestion() { - let _ = (0..42).len() == 0; - } -} diff --git a/tests/ui/len_zero_ranges.fixed b/tests/ui/len_zero_ranges.fixed index eee3db9b7d4..79781766242 100644 --- a/tests/ui/len_zero_ranges.fixed +++ b/tests/ui/len_zero_ranges.fixed @@ -1,15 +1,17 @@ // run-rustfix -#![feature(range_is_empty)] #![warn(clippy::len_zero)] #![allow(unused)] -#![allow(stable_features)] // TODO: https://github.com/rust-lang/rust-clippy/issues/5956 +// Now that `Range(Inclusive)::is_empty` is stable (1.47), we can always suggest this mod issue_3807 { - // With the feature enabled, `is_empty` should be suggested - fn suggestion_is_fine() { + fn suggestion_is_fine_range() { let _ = (0..42).is_empty(); } + + fn suggestion_is_fine_range_inclusive() { + let _ = (0_u8..=42).is_empty(); + } } fn main() {} diff --git a/tests/ui/len_zero_ranges.rs b/tests/ui/len_zero_ranges.rs index be2e0f38fd1..a0eb51cc976 100644 --- a/tests/ui/len_zero_ranges.rs +++ b/tests/ui/len_zero_ranges.rs @@ -1,15 +1,17 @@ // run-rustfix -#![feature(range_is_empty)] #![warn(clippy::len_zero)] #![allow(unused)] -#![allow(stable_features)] // TODO: https://github.com/rust-lang/rust-clippy/issues/5956 +// Now that `Range(Inclusive)::is_empty` is stable (1.47), we can always suggest this mod issue_3807 { - // With the feature enabled, `is_empty` should be suggested - fn suggestion_is_fine() { + fn suggestion_is_fine_range() { let _ = (0..42).len() == 0; } + + fn suggestion_is_fine_range_inclusive() { + let _ = (0_u8..=42).len() == 0; + } } fn main() {} diff --git a/tests/ui/len_zero_ranges.stderr b/tests/ui/len_zero_ranges.stderr index acb85f7100a..d0defb5a79e 100644 --- a/tests/ui/len_zero_ranges.stderr +++ b/tests/ui/len_zero_ranges.stderr @@ -1,10 +1,16 @@ error: length comparison to zero - --> $DIR/len_zero_ranges.rs:11:17 + --> $DIR/len_zero_ranges.rs:9:17 | LL | let _ = (0..42).len() == 0; | ^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(0..42).is_empty()` | = note: `-D clippy::len-zero` implied by `-D warnings` -error: aborting due to previous error +error: length comparison to zero + --> $DIR/len_zero_ranges.rs:13:17 + | +LL | let _ = (0_u8..=42).len() == 0; + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(0_u8..=42).is_empty()` + +error: aborting due to 2 previous errors From 370fc45a0a2af502d43f0e1831def314e0580a92 Mon Sep 17 00:00:00 2001 From: Thibaud <ThibsG@users.noreply.github.com> Date: Tue, 25 Aug 2020 22:20:35 +0200 Subject: [PATCH 500/526] Update clippy_lints/src/methods/mod.rs Co-authored-by: Eduardo Broto <ebroto@tutanota.com> --- clippy_lints/src/methods/mod.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 4f0a533592c..1ef54d285f6 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2150,11 +2150,7 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir:: return; }; - let snippet = if in_macro(arg.span) { - snippet_with_macro_callsite(cx, arg.span, "_") - } else { - snippet(cx, arg.span, "_") - }; + let snippet = snippet_with_macro_callsite(cx, arg.span, "_"); span_lint_and_sugg( cx, From 9d18c24b56b6079fc0b66d93b8679c760cd364fb Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto <matsujika@gmail.com> Date: Wed, 26 Aug 2020 16:03:35 +0900 Subject: [PATCH 501/526] Fix typo --- clippy_lints/src/utils/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 25301d6dede..e6be5c4588f 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -574,7 +574,7 @@ pub fn snippet_block<'a, T: LintContext>( } /// Same as `snippet_block`, but adapts the applicability level by the rules of -/// `snippet_with_applicabiliy`. +/// `snippet_with_applicability`. pub fn snippet_block_with_applicability<'a, T: LintContext>( cx: &T, span: Span, @@ -1304,7 +1304,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { } } -// check if expr is calling method or function with #[must_use] attribyte +// check if expr is calling method or function with #[must_use] attribute pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let did = match expr.kind { ExprKind::Call(ref path, _) => if_chain! { From 2d853148d72d49956052cf1cdb5f3be18c85a9fc Mon Sep 17 00:00:00 2001 From: Bastian <bastian@cmbt.de> Date: Wed, 26 Aug 2020 16:39:30 +0200 Subject: [PATCH 502/526] Changed the location of the suggestion as well as the way the suggestion is assembled --- .../src/float_equality_without_abs.rs | 30 ++++++------- tests/ui/float_equality_without_abs.stderr | 44 ++++++++++++++----- 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/float_equality_without_abs.rs b/clippy_lints/src/float_equality_without_abs.rs index dc1c3bfc9ff..9ac5a45eb45 100644 --- a/clippy_lints/src/float_equality_without_abs.rs +++ b/clippy_lints/src/float_equality_without_abs.rs @@ -1,5 +1,6 @@ -use crate::utils::{match_qpath, paths, snippet, span_lint_and_sugg}; +use crate::utils::{match_qpath, paths, span_lint_and_then, sugg}; use if_chain::if_chain; +use rustc_ast::util::parser::AssocOp; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -84,27 +85,24 @@ impl<'tcx> LateLintPass<'tcx> for FloatEqualityWithoutAbs { if let ty::Float(_) = t_val_r.kind; then { - // get the snippet string - let lhs_string = snippet( - cx, - lhs.span, - "(...)", - ); + let sug_l = sugg::Sugg::hir(cx, &val_l, ".."); + let sug_r = sugg::Sugg::hir(cx, &val_r, ".."); // format the suggestion - let suggestion = if lhs_string.starts_with('(') { - format!("{}.abs()", lhs_string) - } else { - format!("({}).abs()", lhs_string) - }; + let suggestion = format!("{}.abs()", sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par()); // spans the lint - span_lint_and_sugg( + span_lint_and_then( cx, FLOAT_EQUALITY_WITHOUT_ABS, expr.span, "float equality check without `.abs()`", - "add `.abs()`", - suggestion, - Applicability::MaybeIncorrect, + | diag | { + diag.span_suggestion( + lhs.span, + "add `.abs()`", + suggestion, + Applicability::MaybeIncorrect, + ); + } ); } } diff --git a/tests/ui/float_equality_without_abs.stderr b/tests/ui/float_equality_without_abs.stderr index 74b9078afe8..b34c8159da0 100644 --- a/tests/ui/float_equality_without_abs.stderr +++ b/tests/ui/float_equality_without_abs.stderr @@ -2,7 +2,9 @@ error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:4:5 | LL | (a - b) < f32::EPSILON - | ^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b).abs()` + | -------^^^^^^^^^^^^^^^ + | | + | help: add `.abs()`: `(a - b).abs()` | = note: `-D clippy::float-equality-without-abs` implied by `-D warnings` @@ -10,61 +12,81 @@ error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:13:13 | LL | let _ = (a - b) < f32::EPSILON; - | ^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b).abs()` + | -------^^^^^^^^^^^^^^^ + | | + | help: add `.abs()`: `(a - b).abs()` error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:14:13 | LL | let _ = a - b < f32::EPSILON; - | ^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b).abs()` + | -----^^^^^^^^^^^^^^^ + | | + | help: add `.abs()`: `(a - b).abs()` error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:15:13 | LL | let _ = a - b.abs() < f32::EPSILON; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b.abs()).abs()` + | -----------^^^^^^^^^^^^^^^ + | | + | help: add `.abs()`: `(a - b.abs()).abs()` error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:16:13 | LL | let _ = (a as f64 - b as f64) < f64::EPSILON; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a as f64 - b as f64).abs()` + | ---------------------^^^^^^^^^^^^^^^ + | | + | help: add `.abs()`: `(a as f64 - b as f64).abs()` error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:17:13 | LL | let _ = 1.0 - 2.0 < f32::EPSILON; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(1.0 - 2.0).abs()` + | ---------^^^^^^^^^^^^^^^ + | | + | help: add `.abs()`: `(1.0 - 2.0).abs()` error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:19:13 | LL | let _ = f32::EPSILON > (a - b); - | ^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b).abs()` + | ^^^^^^^^^^^^^^^------- + | | + | help: add `.abs()`: `(a - b).abs()` error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:20:13 | LL | let _ = f32::EPSILON > a - b; - | ^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b).abs()` + | ^^^^^^^^^^^^^^^----- + | | + | help: add `.abs()`: `(a - b).abs()` error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:21:13 | LL | let _ = f32::EPSILON > a - b.abs(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a - b.abs()).abs()` + | ^^^^^^^^^^^^^^^----------- + | | + | help: add `.abs()`: `(a - b.abs()).abs()` error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:22:13 | LL | let _ = f64::EPSILON > (a as f64 - b as f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(a as f64 - b as f64).abs()` + | ^^^^^^^^^^^^^^^--------------------- + | | + | help: add `.abs()`: `(a as f64 - b as f64).abs()` error: float equality check without `.abs()` --> $DIR/float_equality_without_abs.rs:23:13 | LL | let _ = f32::EPSILON > 1.0 - 2.0; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: add `.abs()`: `(1.0 - 2.0).abs()` + | ^^^^^^^^^^^^^^^--------- + | | + | help: add `.abs()`: `(1.0 - 2.0).abs()` error: aborting due to 11 previous errors From edc05da57d4ad5ab19b5ca64e80e359e487ab2d0 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Thu, 27 Aug 2020 10:23:21 +1200 Subject: [PATCH 503/526] Fix the wrong use of `snippet_with_applicability` This includes a workaround of the issue #5822, the cause of this little mistake. --- clippy_lints/src/write.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 5f88dcb188a..e653240d049 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -297,13 +297,14 @@ impl EarlyLintPass for Write { if let (Some(fmt_str), expr) = self.check_tts(cx, mac.args.inner_tokens(), true) { if fmt_str.symbol == Symbol::intern("") { let mut applicability = Applicability::MachineApplicable; - let suggestion = expr.map_or_else( - || { - applicability = Applicability::HasPlaceholders; - Cow::Borrowed("v") - }, - |e| snippet_with_applicability(cx, e.span, "v", &mut Applicability::MachineApplicable), - ); + // FIXME: remove this `#[allow(...)]` once the issue #5822 gets fixed + #[allow(clippy::option_if_let_else)] + let suggestion = if let Some(e) = expr { + snippet_with_applicability(cx, e.span, "v", &mut applicability) + } else { + applicability = Applicability::HasPlaceholders; + Cow::Borrowed("v") + }; span_lint_and_sugg( cx, From 91024f1fdee2d2c2febfc7c76127d68d2b6e629e Mon Sep 17 00:00:00 2001 From: Jane Lusby <jlusby@yaah.dev> Date: Wed, 26 Aug 2020 16:31:49 -0700 Subject: [PATCH 504/526] Add new lint to prevent usage of unwrap in fns that return result --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 4 + clippy_lints/src/unwrap_in_result.rs | 140 +++++++++++++++++++++++++++ src/lintlist/mod.rs | 7 ++ tests/ui/unwrap_in_result.rs | 44 +++++++++ tests/ui/unwrap_in_result.stderr | 41 ++++++++ 6 files changed, 237 insertions(+) create mode 100644 clippy_lints/src/unwrap_in_result.rs create mode 100644 tests/ui/unwrap_in_result.rs create mode 100644 tests/ui/unwrap_in_result.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index a5da0f7b767..137b561028a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1778,6 +1778,7 @@ Released 2018-09-13 [`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label [`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self [`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit +[`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_in_result [`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used [`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug [`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f78de7a175f..577ce6523b4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -314,6 +314,7 @@ mod unused_io_amount; mod unused_self; mod unused_unit; mod unwrap; +mod unwrap_in_result; mod use_self; mod useless_conversion; mod vec; @@ -850,6 +851,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &unused_unit::UNUSED_UNIT, &unwrap::PANICKING_UNWRAP, &unwrap::UNNECESSARY_UNWRAP, + &unwrap_in_result::UNWRAP_IN_RESULT, &use_self::USE_SELF, &useless_conversion::USELESS_CONVERSION, &utils::internal_lints::CLIPPY_LINTS_INTERNAL, @@ -1094,6 +1096,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch); store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive); store.register_late_pass(|| box repeat_once::RepeatOnce); + store.register_late_pass(|| box unwrap_in_result::UnwrapInResult); store.register_late_pass(|| box self_assignment::SelfAssignment); store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs); @@ -1133,6 +1136,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&shadow::SHADOW_REUSE), LintId::of(&shadow::SHADOW_SAME), LintId::of(&strings::STRING_ADD), + LintId::of(&unwrap_in_result::UNWRAP_IN_RESULT), LintId::of(&verbose_file_reads::VERBOSE_FILE_READS), LintId::of(&write::PRINT_STDOUT), LintId::of(&write::USE_DEBUG), diff --git a/clippy_lints/src/unwrap_in_result.rs b/clippy_lints/src/unwrap_in_result.rs new file mode 100644 index 00000000000..1c7e62ecd3d --- /dev/null +++ b/clippy_lints/src/unwrap_in_result.rs @@ -0,0 +1,140 @@ +use crate::utils::{is_type_diagnostic_item, method_chain_args, return_ty, span_lint_and_then, walk_ptrs_ty}; +use if_chain::if_chain; +use rustc_hir as hir; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Span; + +declare_clippy_lint! { + /// **What it does:** Checks for functions of type Result that contain `expect()` or `unwrap()` + /// + /// **Why is this bad?** These functions promote recoverable errors to non-recoverable errors which may be undesirable in code bases which wish to avoid panics. + /// + /// **Known problems:** This can cause false positives in functions that handle both recoverable and non recoverable errors. + /// + /// **Example:** + /// Before: + /// ```rust + /// fn divisible_by_3(i_str: String) -> Result<(), String> { + /// let i = i_str + /// .parse::<i32>() + /// .expect("cannot divide the input by three"); + /// + /// if i % 3 != 0 { + /// Err("Number is not divisible by 3")? + /// } + /// + /// Ok(()) + /// } + /// ``` + /// + /// After: + /// ```rust + /// fn divisible_by_3(i_str: String) -> Result<(), String> { + /// let i = i_str + /// .parse::<i32>() + /// .map_err(|e| format!("cannot divide the input by three: {}", e))?; + /// + /// if i % 3 != 0 { + /// Err("Number is not divisible by 3")? + /// } + /// + /// Ok(()) + /// } + /// ``` + pub UNWRAP_IN_RESULT, + restriction, + "functions of type `Result<..>` or `Option`<...> that contain `expect()` or `unwrap()`" +} + +declare_lint_pass!(UnwrapInResult=> [UNWRAP_IN_RESULT]); + +impl<'tcx> LateLintPass<'tcx> for UnwrapInResult { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { + if_chain! { + // first check if it's a method or function + if let hir::ImplItemKind::Fn(ref _signature, _) = impl_item.kind; + // checking if its return type is `result` or `option` + if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(result_type)) + || is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(option_type)); + then { + lint_impl_body(cx, impl_item.span, impl_item); + } + } + } +} + +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::{Expr, ImplItemKind}; + +struct FindExpectUnwrap<'a, 'tcx> { + lcx: &'a LateContext<'tcx>, + typeck_results: &'tcx ty::TypeckResults<'tcx>, + result: Vec<Span>, +} + +impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + // check for `expect` + if let Some(arglists) = method_chain_args(expr, &["expect"]) { + let reciever_ty = walk_ptrs_ty(self.typeck_results.expr_ty(&arglists[0][0])); + if is_type_diagnostic_item(self.lcx, reciever_ty, sym!(option_type)) + || is_type_diagnostic_item(self.lcx, reciever_ty, sym!(result_type)) + { + self.result.push(expr.span); + } + } + + // check for `unwrap` + if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { + let reciever_ty = walk_ptrs_ty(self.typeck_results.expr_ty(&arglists[0][0])); + if is_type_diagnostic_item(self.lcx, reciever_ty, sym!(option_type)) + || is_type_diagnostic_item(self.lcx, reciever_ty, sym!(result_type)) + { + self.result.push(expr.span); + } + } + + // and check sub-expressions + intravisit::walk_expr(self, expr); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } +} + +fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) { + if_chain! { + + if let ImplItemKind::Fn(_, body_id) = impl_item.kind; + then { + let body = cx.tcx.hir().body(body_id); + let impl_item_def_id = cx.tcx.hir().local_def_id(impl_item.hir_id); + let mut fpu = FindExpectUnwrap { + lcx: cx, + typeck_results: cx.tcx.typeck(impl_item_def_id), + result: Vec::new(), + }; + fpu.visit_expr(&body.value); + + // if we've found one, lint + if !fpu.result.is_empty() { + span_lint_and_then( + cx, + UNWRAP_IN_RESULT, + impl_span, + "used unwrap or expect in a function that returns result or option", + move |diag| { + diag.help( + "unwrap and expect should not be used in a function that returns result or option" ); + diag.span_note(fpu.result, "potential non-recoverable error(s)"); + }); + } + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index eadd2621a40..687fac7baa8 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2516,6 +2516,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "unused_unit", }, + Lint { + name: "unwrap_in_result", + group: "restriction", + desc: "functions of type `Result<..>` or `Option`<...> that contain `expect()` or `unwrap()`", + deprecation: None, + module: "unwrap_in_result", + }, Lint { name: "unwrap_used", group: "restriction", diff --git a/tests/ui/unwrap_in_result.rs b/tests/ui/unwrap_in_result.rs new file mode 100644 index 00000000000..2aa842adc85 --- /dev/null +++ b/tests/ui/unwrap_in_result.rs @@ -0,0 +1,44 @@ +#![warn(clippy::unwrap_in_result)] + +struct A; + +impl A { + // should not be detected + fn good_divisible_by_3(i_str: String) -> Result<bool, String> { + // checks whether a string represents a number divisible by 3 + let i_result = i_str.parse::<i32>(); + match i_result { + Err(_e) => Err("Not a number".to_string()), + Ok(i) => { + if i % 3 == 0 { + return Ok(true); + } + Err("Number is not divisible by 3".to_string()) + }, + } + } + + // should be detected + fn bad_divisible_by_3(i_str: String) -> Result<bool, String> { + // checks whether a string represents a number divisible by 3 + let i = i_str.parse::<i32>().unwrap(); + if i % 3 == 0 { + Ok(true) + } else { + Err("Number is not divisible by 3".to_string()) + } + } + + fn example_option_expect(i_str: String) -> Option<bool> { + let i = i_str.parse::<i32>().expect("not a number"); + if i % 3 == 0 { + return Some(true); + } + None + } +} + +fn main() { + A::bad_divisible_by_3("3".to_string()); + A::good_divisible_by_3("3".to_string()); +} diff --git a/tests/ui/unwrap_in_result.stderr b/tests/ui/unwrap_in_result.stderr new file mode 100644 index 00000000000..56bc2f2d1c0 --- /dev/null +++ b/tests/ui/unwrap_in_result.stderr @@ -0,0 +1,41 @@ +error: used unwrap or expect in a function that returns result or option + --> $DIR/unwrap_in_result.rs:22:5 + | +LL | / fn bad_divisible_by_3(i_str: String) -> Result<bool, String> { +LL | | // checks whether a string represents a number divisible by 3 +LL | | let i = i_str.parse::<i32>().unwrap(); +LL | | if i % 3 == 0 { +... | +LL | | } +LL | | } + | |_____^ + | + = note: `-D clippy::unwrap-in-result` implied by `-D warnings` + = help: unwrap and expect should not be used in a function that returns result or option +note: potential non-recoverable error(s) + --> $DIR/unwrap_in_result.rs:24:17 + | +LL | let i = i_str.parse::<i32>().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used unwrap or expect in a function that returns result or option + --> $DIR/unwrap_in_result.rs:32:5 + | +LL | / fn example_option_expect(i_str: String) -> Option<bool> { +LL | | let i = i_str.parse::<i32>().expect("not a number"); +LL | | if i % 3 == 0 { +LL | | return Some(true); +LL | | } +LL | | None +LL | | } + | |_____^ + | + = help: unwrap and expect should not be used in a function that returns result or option +note: potential non-recoverable error(s) + --> $DIR/unwrap_in_result.rs:33:17 + | +LL | let i = i_str.parse::<i32>().expect("not a number"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From baf62e7a38854ff6a0039ddccb124ff329a32143 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Thu, 27 Aug 2020 14:39:09 +0200 Subject: [PATCH 505/526] Update changelog to beta 1.47 --- CHANGELOG.md | 108 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 137b561028a..34d48821023 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,113 @@ document. ## Unreleased / In Rust Nightly -[c2c07fa...master](https://github.com/rust-lang/rust-clippy/compare/c2c07fa...master) +[09bd400...master](https://github.com/rust-lang/rust-clippy/compare/09bd400...master) + +## Rust 1.47 + +Current beta, release 2020-10-08 + +[c2c07fa...09bd400](https://github.com/rust-lang/rust-clippy/compare/c2c07fa...09bd400) + +### New lints + +* [`derive_ord_xor_partial_ord`] [#5848](https://github.com/rust-lang/rust-clippy/pull/5848) +* [`trait_duplication_in_bounds`] [#5852](https://github.com/rust-lang/rust-clippy/pull/5852) +* [`map_identity`] [#5694](https://github.com/rust-lang/rust-clippy/pull/5694) +* [`unit_return_expecting_ord`] [#5737](https://github.com/rust-lang/rust-clippy/pull/5737) +* [`pattern_type_mismatch`] [#4841](https://github.com/rust-lang/rust-clippy/pull/4841) +* [`repeat_once`] [#5773](https://github.com/rust-lang/rust-clippy/pull/5773) +* [`same_item_push`] [#5825](https://github.com/rust-lang/rust-clippy/pull/5825) +* [`needless_arbitrary_self_type`] [#5869](https://github.com/rust-lang/rust-clippy/pull/5869) +* [`match_like_matches_macro`] [#5769](https://github.com/rust-lang/rust-clippy/pull/5769) +* [`stable_sort_primitive`] [#5809](https://github.com/rust-lang/rust-clippy/pull/5809) +* [`blanket_clippy_restriction_lints`] [#5750](https://github.com/rust-lang/rust-clippy/pull/5750) +* [`option_if_let_else`] [#5301](https://github.com/rust-lang/rust-clippy/pull/5301) + +### Moves and Deprecations + +* Deprecate [`regex_macro`] lint + [#5760](https://github.com/rust-lang/rust-clippy/pull/5760) +* Move [`range_minus_one`] to `pedantic` + [#5752](https://github.com/rust-lang/rust-clippy/pull/5752) + +### Enhancements + +* Improve [`needless_collect`] by catching `collect` calls followed by `iter` or `into_iter` calls + [#5837](https://github.com/rust-lang/rust-clippy/pull/5837) +* [`panic`], [`todo`], [`unimplemented`] and [`unreachable`] now detect calls with formatting + [#5811](https://github.com/rust-lang/rust-clippy/pull/5811) +* Detect more cases of [`suboptimal_flops`] and [`imprecise_flops`] + [#5443](https://github.com/rust-lang/rust-clippy/pull/5443) +* Handle asymmetrical implementations of `PartialEq` in [`cmp_owned`] + [#5701](https://github.com/rust-lang/rust-clippy/pull/5701) +* Make it possible to allow [`unsafe_derive_deserialize`] + [#5870](https://github.com/rust-lang/rust-clippy/pull/5870) +* Catch `ord.min(a).max(b)` where a < b in [`min_max`] + [#5871](https://github.com/rust-lang/rust-clippy/pull/5871) +* Make [`clone_on_copy`] suggestion machine applicable + [#5745](https://github.com/rust-lang/rust-clippy/pull/5745) +* Enable [`len_zero`] on ranges now that `is_empty` is stable on them + [#5961](https://github.com/rust-lang/rust-clippy/pull/5961) + +### False Positive Fixes + +* Avoid triggering [`or_fun_call`] with const fns that take no arguments + [#5889](https://github.com/rust-lang/rust-clippy/pull/5889) +* Fix [`redundant_closure_call`] false positive for closures that have multiple calls + [#5800](https://github.com/rust-lang/rust-clippy/pull/5800) +* Don't lint cases involving `ManuallyDrop` in [`redundant_clone`] + [#5824](https://github.com/rust-lang/rust-clippy/pull/5824) +* Treat a single expression the same as a single statement in the 2nd arm of a match in [`single_match_else`] + [#5771](https://github.com/rust-lang/rust-clippy/pull/5771) +* Don't trigger [`unnested_or_patterns`] if the feature `or_patterns` is not enabled + [#5758](https://github.com/rust-lang/rust-clippy/pull/5758) +* Avoid linting if key borrows in [`unnecessary_sort_by`] + [#5756](https://github.com/rust-lang/rust-clippy/pull/5756) +* Consider `Try` impl for `Poll` when generating suggestions in [`try_err`] + [#5857](https://github.com/rust-lang/rust-clippy/pull/5857) +* Take input lifetimes into account in `manual_async_fn` + [#5859](https://github.com/rust-lang/rust-clippy/pull/5859) +* Fix multiple false positives in [`type_repetition_in_bounds`] and add a configuration option + [#5761](https://github.com/rust-lang/rust-clippy/pull/5761) +* Limit the [`suspicious_arithmetic_impl`] lint to one binary operation + [#5820](https://github.com/rust-lang/rust-clippy/pull/5820) + +### Suggestion Fixes/Improvements + +* Improve readability of [`shadow_unrelated`] suggestion by truncating the RHS snippet + [#5788](https://github.com/rust-lang/rust-clippy/pull/5788) +* Suggest `filter_map` instead of `flat_map` when mapping to `Option` in [`map_flatten`] + [#5846](https://github.com/rust-lang/rust-clippy/pull/5846) +* Ensure suggestion is shown correctly for long method call chains in [`iter_nth_zero`] + [#5793](https://github.com/rust-lang/rust-clippy/pull/5793) +* Drop borrow operator in suggestions of [`redundant_pattern_matching`] + [#5815](https://github.com/rust-lang/rust-clippy/pull/5815) +* Add suggestion for [`iter_skip_next`] + [#5843](https://github.com/rust-lang/rust-clippy/pull/5843) +* Improve [`collapsible_if`] fix suggestion + [#5732](https://github.com/rust-lang/rust-clippy/pull/5732) + +### ICE Fixes + +* Fix ICE caused by [`needless_collect`] + [#5877](https://github.com/rust-lang/rust-clippy/pull/5877) +* Fix ICE caused by [`unnested_or_patterns`] + [#5784](https://github.com/rust-lang/rust-clippy/pull/5784) + +### Documentation Improvements + +* Fix grammar of [`await_holding_lock`] documentation + [#5748](https://github.com/rust-lang/rust-clippy/pull/5748) + +### Others + +* Make lints adhere to the rustc dev guide + [#5888](https://github.com/rust-lang/rust-clippy/pull/5888) ## Rust 1.46 -Current beta, release 2020-08-27 +Current stable, released 2020-08-27 [7ea7cd1...c2c07fa](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...c2c07fa) @@ -72,7 +174,7 @@ Current beta, release 2020-08-27 ## Rust 1.45 -Current stable, released 2020-07-16 +Released 2020-07-16 [891e1a8...7ea7cd1](https://github.com/rust-lang/rust-clippy/compare/891e1a8...7ea7cd1) From 04bff17668be1305d9efe235665a32727ff3e0b5 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Thu, 27 Aug 2020 23:37:47 +0900 Subject: [PATCH 506/526] Fix FP in `to_string_in_display` Don't emit a lint when `.to_string()` on anything that is not `self` --- clippy_lints/src/to_string_in_display.rs | 32 ++++++++++++++++++++---- tests/ui/to_string_in_display.rs | 14 +++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/to_string_in_display.rs b/clippy_lints/src/to_string_in_display.rs index 4b6a0a6a0c9..006d7a3a12d 100644 --- a/clippy_lints/src/to_string_in_display.rs +++ b/clippy_lints/src/to_string_in_display.rs @@ -1,6 +1,7 @@ -use crate::utils::{match_def_path, match_trait_method, paths, span_lint}; +use crate::utils::{match_def_path, match_trait_method, paths, qpath_res, span_lint}; use if_chain::if_chain; -use rustc_hir::{Expr, ExprKind, Item, ItemKind}; +use rustc_hir::def::Res; +use rustc_hir::{Expr, ExprKind, HirId, ImplItem, ImplItemKind, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -45,11 +46,15 @@ declare_clippy_lint! { #[derive(Default)] pub struct ToStringInDisplay { in_display_impl: bool, + self_hir_id: Option<HirId>, } impl ToStringInDisplay { pub fn new() -> Self { - Self { in_display_impl: false } + Self { + in_display_impl: false, + self_hir_id: None, + } } } @@ -65,16 +70,33 @@ impl LateLintPass<'_> for ToStringInDisplay { fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if is_display_impl(cx, item) { self.in_display_impl = false; + self.self_hir_id = None; + } + } + + fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { + if_chain! { + if self.in_display_impl; + if let ImplItemKind::Fn(.., body_id) = &impl_item.kind; + let body = cx.tcx.hir().body(*body_id); + if !body.params.is_empty(); + then { + let self_param = &body.params[0]; + self.self_hir_id = Some(self_param.pat.hir_id); + } } } fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(ref path, _, _, _) = expr.kind; + if let ExprKind::MethodCall(ref path, _, args, _) = expr.kind; if path.ident.name == sym!(to_string); if match_trait_method(cx, expr, &paths::TO_STRING); if self.in_display_impl; - + if let ExprKind::Path(ref qpath) = args[0].kind; + if let Res::Local(hir_id) = qpath_res(cx, qpath, args[0].hir_id); + if let Some(self_hir_id) = self.self_hir_id; + if hir_id == self_hir_id; then { span_lint( cx, diff --git a/tests/ui/to_string_in_display.rs b/tests/ui/to_string_in_display.rs index 3b46324704e..eb8105c6b6d 100644 --- a/tests/ui/to_string_in_display.rs +++ b/tests/ui/to_string_in_display.rs @@ -44,6 +44,20 @@ impl fmt::Display for C { } } +enum D { + E(String), + F, +} + +impl std::fmt::Display for D { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self { + Self::E(string) => write!(f, "E {}", string.to_string()), + Self::F => write!(f, "F"), + } + } +} + fn main() { let a = A; a.to_string(); From 2a3ee5fa854b49530008582900c6ea7fac120d1c Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Tue, 7 Jul 2020 22:47:32 +0200 Subject: [PATCH 507/526] Fix FP in `new_ret_no_self`: trigger in trait def instead of impl block --- clippy_lints/src/methods/mod.rs | 58 ++++++++++++-- tests/ui/new_ret_no_self.rs | 130 ++++++++++++++++++++++++++++++++ tests/ui/new_ret_no_self.stderr | 30 +++++++- 3 files changed, 212 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 1ef54d285f6..8e91cbb3cdf 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -15,6 +15,7 @@ use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::{FnRetTy, FnSig, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; @@ -28,11 +29,11 @@ use crate::consts::{constant, Constant}; use crate::utils::usage::mutated_variables; use crate::utils::{ get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro, is_copy, - is_ctor_or_promotable_const_function, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, - match_def_path, match_qpath, match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, - remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, - span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty, - walk_ptrs_ty_depth, SpanlessEq, + is_ctor_or_promotable_const_function, is_expn_of, is_self_ty, is_type_diagnostic_item, iter_input_pats, + last_path_segment, match_def_path, match_qpath, match_trait_method, match_type, match_var, method_calls, + method_chain_args, paths, remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability, + snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, + span_lint_and_then, sugg, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, }; declare_clippy_lint! { @@ -1631,6 +1632,11 @@ impl<'tcx> LateLintPass<'tcx> for Methods { } } + // if this impl block implements a trait, lint in trait definition instead + if let hir::ItemKind::Impl { of_trait: Some(_), .. } = item.kind { + return; + } + if let hir::ImplItemKind::Fn(_, _) = impl_item.kind { let ret_ty = return_ty(cx, impl_item.hir_id); @@ -1670,6 +1676,48 @@ impl<'tcx> LateLintPass<'tcx> for Methods { } } } + + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { + if_chain! { + if !in_external_macro(cx.tcx.sess, item.span); + if !item.span.from_expansion(); + if item.ident.name == sym!(new); + if let TraitItemKind::Fn(FnSig { decl, .. }, _) = &item.kind; + if let FnRetTy::Return(ret_ty) = &decl.output; + + then { + let mut visitor = HasSelfVisitor { has_self_ty: false }; + visitor.visit_ty(ret_ty); + if !visitor.has_self_ty { + span_lint( + cx, + NEW_RET_NO_SELF, + item.span, + "methods called `new` usually return `Self`", + ); + } + } + } + } +} + +struct HasSelfVisitor { + pub has_self_ty: bool, +} + +impl<'tcx> intravisit::Visitor<'tcx> for HasSelfVisitor { + type Map = Map<'tcx>; + + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { + if is_self_ty(ty) { + self.has_self_ty = true; + } else { + intravisit::walk_ty(self, ty); + } + } + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { + intravisit::NestedVisitorMap::None + } } /// Checks for the `OR_FUN_CALL` lint. diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index 2c2d1e27589..e98360ea691 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -210,3 +210,133 @@ impl<'a> WithLifetime<'a> { unimplemented!(); } } + +mod issue5435 { + struct V; + + pub trait TraitRetSelf { + // should not trigger lint + fn new() -> Self; + } + + pub trait TraitRet { + // should trigger lint as we are in trait definition + fn new() -> String; + } + pub struct StructRet; + impl TraitRet for StructRet { + // should not trigger lint as we are in the impl block + fn new() -> String { + unimplemented!(); + } + } + + pub trait TraitRet2 { + // should trigger lint + fn new(_: String) -> String; + } + + trait TupleReturnerOk { + // should not trigger lint + fn new() -> (Self, u32) + where + Self: Sized, + { + unimplemented!(); + } + } + + trait TupleReturnerOk2 { + // should not trigger lint (it doesn't matter which element in the tuple is Self) + fn new() -> (u32, Self) + where + Self: Sized, + { + unimplemented!(); + } + } + + trait TupleReturnerOk3 { + // should not trigger lint (tuple can contain multiple Self) + fn new() -> (Self, Self) + where + Self: Sized, + { + unimplemented!(); + } + } + + trait TupleReturnerBad { + // should trigger lint + fn new() -> (u32, u32) { + unimplemented!(); + } + } + + trait MutPointerReturnerOk { + // should not trigger lint + fn new() -> *mut Self + where + Self: Sized, + { + unimplemented!(); + } + } + + trait MutPointerReturnerOk2 { + // should not trigger lint + fn new() -> *const Self + where + Self: Sized, + { + unimplemented!(); + } + } + + trait MutPointerReturnerBad { + // should trigger lint + fn new() -> *mut V { + unimplemented!(); + } + } + + trait GenericReturnerOk { + // should not trigger lint + fn new() -> Option<Self> + where + Self: Sized, + { + unimplemented!(); + } + } + + trait NestedReturnerOk { + // should not trigger lint + fn new() -> (Option<Self>, u32) + where + Self: Sized, + { + unimplemented!(); + } + } + + trait NestedReturnerOk2 { + // should not trigger lint + fn new() -> ((Self, u32), u32) + where + Self: Sized, + { + unimplemented!(); + } + } + + trait NestedReturnerOk3 { + // should not trigger lint + fn new() -> Option<(Self, u32)> + where + Self: Sized, + { + unimplemented!(); + } + } +} diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index dd5a24bcbe7..8217bc6187f 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -48,5 +48,33 @@ LL | | unimplemented!(); LL | | } | |_____^ -error: aborting due to 6 previous errors +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self.rs:224:9 + | +LL | fn new() -> String; + | ^^^^^^^^^^^^^^^^^^^ + +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self.rs:236:9 + | +LL | fn new(_: String) -> String; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self.rs:271:9 + | +LL | / fn new() -> (u32, u32) { +LL | | unimplemented!(); +LL | | } + | |_________^ + +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self.rs:298:9 + | +LL | / fn new() -> *mut V { +LL | | unimplemented!(); +LL | | } + | |_________^ + +error: aborting due to 10 previous errors From 3cb75c2e5cdd4f450f2974c5e052d569674d95fd Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Tue, 25 Aug 2020 09:16:08 +0200 Subject: [PATCH 508/526] Remove expansion restriction + fix doc and tests naming --- clippy_lints/src/methods/mod.rs | 34 +++++++++++++++++++++++---------- tests/ui/new_ret_no_self.rs | 6 +++--- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 8e91cbb3cdf..2388310628f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -725,6 +725,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** + /// In an impl block: /// ```rust /// # struct Foo; /// # struct NotAFoo; @@ -737,25 +738,40 @@ declare_clippy_lint! { /// /// ```rust /// # struct Foo; - /// # struct FooError; + /// struct Bar(Foo); /// impl Foo { - /// // Good. Return type contains `Self` - /// fn new() -> Result<Foo, FooError> { - /// # Ok(Foo) + /// // Bad. The type name must contain `Self` + /// fn new() -> Bar { + /// # Bar(Foo) /// } /// } /// ``` /// /// ```rust /// # struct Foo; - /// struct Bar(Foo); + /// # struct FooError; /// impl Foo { - /// // Bad. The type name must contain `Self`. - /// fn new() -> Bar { - /// # Bar(Foo) + /// // Good. Return type contains `Self` + /// fn new() -> Result<Foo, FooError> { + /// # Ok(Foo) /// } /// } /// ``` + /// + /// Or in a trait definition: + /// ```rust + /// pub trait Trait { + /// // Bad. The type name must contain `Self` + /// fn new(); + /// } + /// ``` + /// + /// ```rust + /// pub trait Trait { + /// // Good. Return type contains `Self` + /// fn new() -> Self; + /// } + /// ``` pub NEW_RET_NO_SELF, style, "not returning type containing `Self` in a `new` method" @@ -1679,8 +1695,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if_chain! { - if !in_external_macro(cx.tcx.sess, item.span); - if !item.span.from_expansion(); if item.ident.name == sym!(new); if let TraitItemKind::Fn(FnSig { decl, .. }, _) = &item.kind; if let FnRetTy::Return(ret_ty) = &decl.output; diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index e98360ea691..e82873629a5 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -137,9 +137,9 @@ impl MutPointerReturnerOk { } } -struct MutPointerReturnerOk2; +struct ConstPointerReturnerOk2; -impl MutPointerReturnerOk2 { +impl ConstPointerReturnerOk2 { // should not trigger lint pub fn new() -> *const Self { unimplemented!(); @@ -283,7 +283,7 @@ mod issue5435 { } } - trait MutPointerReturnerOk2 { + trait ConstPointerReturnerOk2 { // should not trigger lint fn new() -> *const Self where From 504612622f2801b43dbe3e6788d2404d394376df Mon Sep 17 00:00:00 2001 From: ThibsG <Thibs@debian.com> Date: Thu, 27 Aug 2020 18:24:59 +0200 Subject: [PATCH 509/526] Merge logic of looking for `Self` type --- clippy_lints/src/methods/mod.rs | 62 +++++++++------------------------ clippy_lints/src/utils/mod.rs | 11 +++++- 2 files changed, 26 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2388310628f..63e0c183113 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -15,12 +15,11 @@ use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{FnRetTy, FnSig, TraitItem, TraitItemKind}; +use rustc_hir::{TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, Ty, TyS}; +use rustc_middle::ty::{self, TraitRef, Ty, TyS}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::{sym, SymbolStr}; @@ -28,8 +27,8 @@ use rustc_span::symbol::{sym, SymbolStr}; use crate::consts::{constant, Constant}; use crate::utils::usage::mutated_variables; use crate::utils::{ - get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro, is_copy, - is_ctor_or_promotable_const_function, is_expn_of, is_self_ty, is_type_diagnostic_item, iter_input_pats, + contains_ty, get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro, + is_copy, is_ctor_or_promotable_const_function, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath, match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, @@ -1656,16 +1655,8 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let hir::ImplItemKind::Fn(_, _) = impl_item.kind { let ret_ty = return_ty(cx, impl_item.hir_id); - let contains_self_ty = |ty: Ty<'tcx>| { - ty.walk().any(|inner| match inner.unpack() { - GenericArgKind::Type(inner_ty) => TyS::same_type(self_ty, inner_ty), - - GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, - }) - }; - // walk the return type and check for Self (this does not check associated types) - if contains_self_ty(ret_ty) { + if contains_ty(ret_ty, self_ty) { return; } @@ -1675,7 +1666,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { for &(predicate, _span) in cx.tcx.predicates_of(def_id).predicates { if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() { // walk the associated type and check for Self - if contains_self_ty(projection_predicate.ty) { + if contains_ty(projection_predicate.ty, self_ty) { return; } } @@ -1696,44 +1687,23 @@ impl<'tcx> LateLintPass<'tcx> for Methods { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if_chain! { if item.ident.name == sym!(new); - if let TraitItemKind::Fn(FnSig { decl, .. }, _) = &item.kind; - if let FnRetTy::Return(ret_ty) = &decl.output; + if let TraitItemKind::Fn(_, _) = item.kind; + let ret_ty = return_ty(cx, item.hir_id); + let self_ty = TraitRef::identity(cx.tcx, item.hir_id.owner.to_def_id()).self_ty(); + if !contains_ty(ret_ty, self_ty); then { - let mut visitor = HasSelfVisitor { has_self_ty: false }; - visitor.visit_ty(ret_ty); - if !visitor.has_self_ty { - span_lint( - cx, - NEW_RET_NO_SELF, - item.span, - "methods called `new` usually return `Self`", - ); - } + span_lint( + cx, + NEW_RET_NO_SELF, + item.span, + "methods called `new` usually return `Self`", + ); } } } } -struct HasSelfVisitor { - pub has_self_ty: bool, -} - -impl<'tcx> intravisit::Visitor<'tcx> for HasSelfVisitor { - type Map = Map<'tcx>; - - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { - if is_self_ty(ty) { - self.has_self_ty = true; - } else { - intravisit::walk_ty(self, ty); - } - } - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { - intravisit::NestedVisitorMap::None - } -} - /// Checks for the `OR_FUN_CALL` lint. #[allow(clippy::too_many_lines)] fn lint_or_fun_call<'tcx>( diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e6be5c4588f..07ec59f452a 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -42,7 +42,8 @@ use rustc_hir::{ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::map::Map; -use rustc_middle::ty::{self, layout::IntegerExt, subst::GenericArg, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; +use rustc_middle::ty::{self, layout::IntegerExt, Ty, TyCtxt, TypeFoldable}; use rustc_mir::const_eval; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::original_sp; @@ -866,6 +867,14 @@ pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> cx.tcx.erase_late_bound_regions(&ret_ty) } +/// Walk into `ty` and returns `true` if any inner type is the same as `other_ty` +pub fn contains_ty<'tcx>(ty: Ty<'tcx>, other_ty: Ty<'tcx>) -> bool { + ty.walk().any(|inner| match inner.unpack() { + GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty), + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, + }) +} + /// Returns `true` if the given type is an `unsafe` function. pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind { From e8be047c5b2d5b1522a16b4b52cc7acfa4581ca3 Mon Sep 17 00:00:00 2001 From: Thibaud <ThibsG@users.noreply.github.com> Date: Fri, 28 Aug 2020 09:31:12 +0200 Subject: [PATCH 510/526] Update clippy_lints/src/utils/mod.rs Co-authored-by: Eduardo Broto <ebroto@tutanota.com> --- clippy_lints/src/utils/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 07ec59f452a..d9598c4abbd 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -868,7 +868,7 @@ pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> } /// Walk into `ty` and returns `true` if any inner type is the same as `other_ty` -pub fn contains_ty<'tcx>(ty: Ty<'tcx>, other_ty: Ty<'tcx>) -> bool { +pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool { ty.walk().any(|inner| match inner.unpack() { GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty), GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, From ffaadae8e48699f115eafd2853c252f546a69a28 Mon Sep 17 00:00:00 2001 From: Thibaud <ThibsG@users.noreply.github.com> Date: Fri, 28 Aug 2020 09:31:29 +0200 Subject: [PATCH 511/526] Update clippy_lints/src/utils/mod.rs Co-authored-by: Eduardo Broto <ebroto@tutanota.com> --- clippy_lints/src/utils/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index d9598c4abbd..82005257115 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -867,7 +867,7 @@ pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> cx.tcx.erase_late_bound_regions(&ret_ty) } -/// Walk into `ty` and returns `true` if any inner type is the same as `other_ty` +/// Walks into `ty` and returns `true` if any inner type is the same as `other_ty` pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool { ty.walk().any(|inner| match inner.unpack() { GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty), From 73b1ee1a614aaad7dd43958280ff4a444c8b737e Mon Sep 17 00:00:00 2001 From: Thibaud <ThibsG@users.noreply.github.com> Date: Fri, 28 Aug 2020 09:33:05 +0200 Subject: [PATCH 512/526] Update clippy_lints/src/methods/mod.rs Co-authored-by: Eduardo Broto <ebroto@tutanota.com> --- clippy_lints/src/methods/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 63e0c183113..9996df69470 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1686,6 +1686,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if_chain! { + if !in_external_macro(cx.tcx.sess, item.span); if item.ident.name == sym!(new); if let TraitItemKind::Fn(_, _) = item.kind; let ret_ty = return_ty(cx, item.hir_id); From 7a66e6502dc3c7085b3f4078c01d4957d96175ed Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Sat, 29 Aug 2020 01:18:42 +0200 Subject: [PATCH 513/526] or_fn_call: ignore nullary associated const fns --- clippy_lints/src/utils/mod.rs | 2 +- tests/ui/or_fun_call.fixed | 17 +++++++++++------ tests/ui/or_fun_call.rs | 17 +++++++++++------ tests/ui/or_fun_call.stderr | 20 ++++---------------- 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 82005257115..fe2ee093157 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -899,7 +899,7 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_ return match res { def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true, // FIXME: check the constness of the arguments, see https://github.com/rust-lang/rust-clippy/pull/5682#issuecomment-638681210 - def::Res::Def(DefKind::Fn, def_id) if has_no_arguments(cx, def_id) => { + def::Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) if has_no_arguments(cx, def_id) => { const_eval::is_const_fn(cx.tcx, def_id) }, def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id), diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index 67faa8bd4a0..5fb568672d3 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -58,12 +58,6 @@ fn or_fun_call() { let without_default = Some(Foo); without_default.unwrap_or_else(Foo::new); - let mut map = HashMap::<u64, String>::new(); - map.entry(42).or_insert_with(String::new); - - let mut btree = BTreeMap::<u64, String>::new(); - btree.entry(42).or_insert_with(String::new); - let stringy = Some(String::from("")); let _ = stringy.unwrap_or_else(|| "".to_owned()); @@ -122,6 +116,17 @@ pub fn skip_const_fn_with_no_args() { Some(42) } let _ = None.or(foo()); + + // See issue #5693. + let mut map = std::collections::HashMap::new(); + map.insert(1, vec![1]); + map.entry(1).or_insert(vec![]); + + let mut map = HashMap::<u64, String>::new(); + map.entry(42).or_insert(String::new()); + + let mut btree = BTreeMap::<u64, String>::new(); + btree.entry(42).or_insert(String::new()); } fn main() {} diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 9867e2eedcf..737b0f7e55b 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -58,12 +58,6 @@ fn or_fun_call() { let without_default = Some(Foo); without_default.unwrap_or(Foo::new()); - let mut map = HashMap::<u64, String>::new(); - map.entry(42).or_insert(String::new()); - - let mut btree = BTreeMap::<u64, String>::new(); - btree.entry(42).or_insert(String::new()); - let stringy = Some(String::from("")); let _ = stringy.unwrap_or("".to_owned()); @@ -122,6 +116,17 @@ pub fn skip_const_fn_with_no_args() { Some(42) } let _ = None.or(foo()); + + // See issue #5693. + let mut map = std::collections::HashMap::new(); + map.insert(1, vec![1]); + map.entry(1).or_insert(vec![]); + + let mut map = HashMap::<u64, String>::new(); + map.entry(42).or_insert(String::new()); + + let mut btree = BTreeMap::<u64, String>::new(); + btree.entry(42).or_insert(String::new()); } fn main() {} diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index bc5978b538f..b8a436993f3 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -60,35 +60,23 @@ error: use of `unwrap_or` followed by a function call LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` -error: use of `or_insert` followed by a function call - --> $DIR/or_fun_call.rs:62:19 - | -LL | map.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` - -error: use of `or_insert` followed by a function call - --> $DIR/or_fun_call.rs:65:21 - | -LL | btree.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` - error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:68:21 + --> $DIR/or_fun_call.rs:62:21 | LL | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: use of `or` followed by a function call - --> $DIR/or_fun_call.rs:93:35 + --> $DIR/or_fun_call.rs:87:35 | LL | let _ = Some("a".to_string()).or(Some("b".to_string())); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))` error: use of `or` followed by a function call - --> $DIR/or_fun_call.rs:97:10 + --> $DIR/or_fun_call.rs:91:10 | LL | .or(Some(Bar(b, Duration::from_secs(2)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some(Bar(b, Duration::from_secs(2))))` -error: aborting due to 15 previous errors +error: aborting due to 13 previous errors From 4972989b616cbf96c015cd9fdf1f4b4464ecaace Mon Sep 17 00:00:00 2001 From: Kyle Huey <khuey@kylehuey.com> Date: Fri, 14 Aug 2020 17:30:48 -0700 Subject: [PATCH 514/526] Add a lint for an async block/closure that yields a type that is itself awaitable. This catches bugs of the form tokio::spawn(async move { let f = some_async_thing(); f // Oh no I forgot to await f so that work will never complete. }); --- CHANGELOG.md | 1 + clippy_lints/src/async_yields_async.rs | 88 +++++++++++++++++++++++ clippy_lints/src/lib.rs | 5 ++ src/lintlist/mod.rs | 7 ++ tests/ui/async_yields_async.fixed | 61 ++++++++++++++++ tests/ui/async_yields_async.rs | 61 ++++++++++++++++ tests/ui/async_yields_async.stderr | 96 ++++++++++++++++++++++++++ 7 files changed, 319 insertions(+) create mode 100644 clippy_lints/src/async_yields_async.rs create mode 100644 tests/ui/async_yields_async.fixed create mode 100644 tests/ui/async_yields_async.rs create mode 100644 tests/ui/async_yields_async.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 34d48821023..99a8b1a6293 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1512,6 +1512,7 @@ Released 2018-09-13 [`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants [`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern [`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops +[`async_yields_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#async_yields_async [`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock [`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask [`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map diff --git a/clippy_lints/src/async_yields_async.rs b/clippy_lints/src/async_yields_async.rs new file mode 100644 index 00000000000..ae347fcd3e8 --- /dev/null +++ b/clippy_lints/src/async_yields_async.rs @@ -0,0 +1,88 @@ +use crate::utils::{implements_trait, snippet, span_lint_and_then}; +use rustc_errors::Applicability; +use rustc_hir::{AsyncGeneratorKind, Body, BodyId, ExprKind, GeneratorKind, QPath}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** + /// Checks for async blocks that yield values of types that can themselves + /// be awaited. + /// + /// **Why is this bad?** + /// An await is likely missing. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// async fn foo() {} + /// + /// fn bar() { + /// let x = async { + /// foo() + /// }; + /// } + /// ``` + /// Use instead: + /// ```rust + /// async fn foo() {} + /// + /// fn bar() { + /// let x = async { + /// foo().await + /// }; + /// } + /// ``` + pub ASYNC_YIELDS_ASYNC, + correctness, + "async blocks that return a type that can be awaited" +} + +declare_lint_pass!(AsyncYieldsAsync => [ASYNC_YIELDS_ASYNC]); + +impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync { + fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { + use AsyncGeneratorKind::{Block, Closure}; + // For functions, with explicitly defined types, don't warn. + // XXXkhuey maybe we should? + if let Some(GeneratorKind::Async(Block | Closure)) = body.generator_kind { + if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() { + let body_id = BodyId { + hir_id: body.value.hir_id, + }; + let def_id = cx.tcx.hir().body_owner_def_id(body_id); + let typeck_results = cx.tcx.typeck(def_id); + let expr_ty = typeck_results.expr_ty(&body.value); + + if implements_trait(cx, expr_ty, future_trait_def_id, &[]) { + let return_expr_span = match &body.value.kind { + // XXXkhuey there has to be a better way. + ExprKind::Block(block, _) => block.expr.map(|e| e.span), + ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span), + _ => None, + }; + if let Some(return_expr_span) = return_expr_span { + span_lint_and_then( + cx, + ASYNC_YIELDS_ASYNC, + return_expr_span, + "an async construct yields a type which is itself awaitable", + |db| { + db.span_label(body.value.span, "outer async construct"); + db.span_label(return_expr_span, "awaitable value not awaited"); + db.span_suggestion( + return_expr_span, + "consider awaiting this value", + format!("{}.await", snippet(cx, return_expr_span, "..")), + Applicability::MaybeIncorrect, + ); + }, + ); + } + } + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 577ce6523b4..0eb1d331366 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -154,6 +154,7 @@ mod arithmetic; mod as_conversions; mod assertions_on_constants; mod assign_ops; +mod async_yields_async; mod atomic_ordering; mod attrs; mod await_holding_lock; @@ -483,6 +484,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &assertions_on_constants::ASSERTIONS_ON_CONSTANTS, &assign_ops::ASSIGN_OP_PATTERN, &assign_ops::MISREFACTORED_ASSIGN_OP, + &async_yields_async::ASYNC_YIELDS_ASYNC, &atomic_ordering::INVALID_ATOMIC_ORDERING, &attrs::BLANKET_CLIPPY_RESTRICTION_LINTS, &attrs::DEPRECATED_CFG_ATTR, @@ -1099,6 +1101,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box unwrap_in_result::UnwrapInResult); store.register_late_pass(|| box self_assignment::SelfAssignment); store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs); + store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1232,6 +1235,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS), LintId::of(&assign_ops::ASSIGN_OP_PATTERN), LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP), + LintId::of(&async_yields_async::ASYNC_YIELDS_ASYNC), LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING), LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), LintId::of(&attrs::DEPRECATED_CFG_ATTR), @@ -1675,6 +1679,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![ LintId::of(&approx_const::APPROX_CONSTANT), + LintId::of(&async_yields_async::ASYNC_YIELDS_ASYNC), LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING), LintId::of(&attrs::DEPRECATED_SEMVER), LintId::of(&attrs::MISMATCHED_TARGET_OS), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 687fac7baa8..dff19ef440f 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -52,6 +52,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![ deprecation: None, module: "assign_ops", }, + Lint { + name: "async_yields_async", + group: "correctness", + desc: "async blocks that return a type that can be awaited", + deprecation: None, + module: "async_yields_async", + }, Lint { name: "await_holding_lock", group: "pedantic", diff --git a/tests/ui/async_yields_async.fixed b/tests/ui/async_yields_async.fixed new file mode 100644 index 00000000000..cadc6494c76 --- /dev/null +++ b/tests/ui/async_yields_async.fixed @@ -0,0 +1,61 @@ +// run-rustfix +// edition:2018 + +#![feature(async_closure)] +#![warn(clippy::async_yields_async)] + +use core::future::Future; +use core::pin::Pin; +use core::task::{Context, Poll}; + +struct CustomFutureType; + +impl Future for CustomFutureType { + type Output = u8; + + fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<Self::Output> { + Poll::Ready(3) + } +} + +fn custom_future_type_ctor() -> CustomFutureType { + CustomFutureType +} + +#[rustfmt::skip] +fn main() { + let _f = { + 3 + }; + let _g = async { + 3 + }; + let _h = async { + async { + 3 + }.await + }; + let _i = async { + CustomFutureType.await + }; + let _i = async || { + 3 + }; + let _j = async || { + async { + 3 + }.await + }; + let _k = async || { + CustomFutureType.await + }; + let _l = async || CustomFutureType.await; + let _m = async || { + println!("I'm bored"); + // Some more stuff + + // Finally something to await + CustomFutureType.await + }; + let _n = async || custom_future_type_ctor(); +} diff --git a/tests/ui/async_yields_async.rs b/tests/ui/async_yields_async.rs new file mode 100644 index 00000000000..898fe1a9561 --- /dev/null +++ b/tests/ui/async_yields_async.rs @@ -0,0 +1,61 @@ +// run-rustfix +// edition:2018 + +#![feature(async_closure)] +#![warn(clippy::async_yields_async)] + +use core::future::Future; +use core::pin::Pin; +use core::task::{Context, Poll}; + +struct CustomFutureType; + +impl Future for CustomFutureType { + type Output = u8; + + fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<Self::Output> { + Poll::Ready(3) + } +} + +fn custom_future_type_ctor() -> CustomFutureType { + CustomFutureType +} + +#[rustfmt::skip] +fn main() { + let _f = { + 3 + }; + let _g = async { + 3 + }; + let _h = async { + async { + 3 + } + }; + let _i = async { + CustomFutureType + }; + let _i = async || { + 3 + }; + let _j = async || { + async { + 3 + } + }; + let _k = async || { + CustomFutureType + }; + let _l = async || CustomFutureType; + let _m = async || { + println!("I'm bored"); + // Some more stuff + + // Finally something to await + CustomFutureType + }; + let _n = async || custom_future_type_ctor(); +} diff --git a/tests/ui/async_yields_async.stderr b/tests/ui/async_yields_async.stderr new file mode 100644 index 00000000000..112984cdccb --- /dev/null +++ b/tests/ui/async_yields_async.stderr @@ -0,0 +1,96 @@ +error: an async construct yields a type which is itself awaitable + --> $DIR/async_yields_async.rs:34:9 + | +LL | let _h = async { + | ____________________- +LL | | async { + | |_________^ +LL | || 3 +LL | || } + | ||_________^ awaitable value not awaited +LL | | }; + | |_____- outer async construct + | + = note: `-D clippy::async-yields-async` implied by `-D warnings` +help: consider awaiting this value + | +LL | async { +LL | 3 +LL | }.await + | + +error: an async construct yields a type which is itself awaitable + --> $DIR/async_yields_async.rs:39:9 + | +LL | let _i = async { + | ____________________- +LL | | CustomFutureType + | | ^^^^^^^^^^^^^^^^ + | | | + | | awaitable value not awaited + | | help: consider awaiting this value: `CustomFutureType.await` +LL | | }; + | |_____- outer async construct + +error: an async construct yields a type which is itself awaitable + --> $DIR/async_yields_async.rs:45:9 + | +LL | let _j = async || { + | _______________________- +LL | | async { + | |_________^ +LL | || 3 +LL | || } + | ||_________^ awaitable value not awaited +LL | | }; + | |_____- outer async construct + | +help: consider awaiting this value + | +LL | async { +LL | 3 +LL | }.await + | + +error: an async construct yields a type which is itself awaitable + --> $DIR/async_yields_async.rs:50:9 + | +LL | let _k = async || { + | _______________________- +LL | | CustomFutureType + | | ^^^^^^^^^^^^^^^^ + | | | + | | awaitable value not awaited + | | help: consider awaiting this value: `CustomFutureType.await` +LL | | }; + | |_____- outer async construct + +error: an async construct yields a type which is itself awaitable + --> $DIR/async_yields_async.rs:52:23 + | +LL | let _l = async || CustomFutureType; + | ^^^^^^^^^^^^^^^^ + | | + | outer async construct + | awaitable value not awaited + | help: consider awaiting this value: `CustomFutureType.await` + +error: an async construct yields a type which is itself awaitable + --> $DIR/async_yields_async.rs:58:9 + | +LL | let _m = async || { + | _______________________- +LL | | println!("I'm bored"); +LL | | // Some more stuff +LL | | +LL | | // Finally something to await +LL | | CustomFutureType + | | ^^^^^^^^^^^^^^^^ + | | | + | | awaitable value not awaited + | | help: consider awaiting this value: `CustomFutureType.await` +LL | | }; + | |_____- outer async construct + +error: aborting due to 6 previous errors + From c1d2b9376a6bb4fc06f845e12b9c2a93079bb2ee Mon Sep 17 00:00:00 2001 From: Kyle Huey <khuey@kylehuey.com> Date: Sat, 22 Aug 2020 21:36:39 -0700 Subject: [PATCH 515/526] Add a test for an async function. --- tests/ui/async_yields_async.fixed | 7 +++++++ tests/ui/async_yields_async.rs | 7 +++++++ tests/ui/async_yields_async.stderr | 12 ++++++------ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/ui/async_yields_async.fixed b/tests/ui/async_yields_async.fixed index cadc6494c76..9b1a7ac3ba9 100644 --- a/tests/ui/async_yields_async.fixed +++ b/tests/ui/async_yields_async.fixed @@ -22,6 +22,12 @@ fn custom_future_type_ctor() -> CustomFutureType { CustomFutureType } +async fn f() -> CustomFutureType { + // Don't warn for functions since you have to explicitly declare their + // return types. + CustomFutureType +} + #[rustfmt::skip] fn main() { let _f = { @@ -58,4 +64,5 @@ fn main() { CustomFutureType.await }; let _n = async || custom_future_type_ctor(); + let _o = async || f(); } diff --git a/tests/ui/async_yields_async.rs b/tests/ui/async_yields_async.rs index 898fe1a9561..731c094edb4 100644 --- a/tests/ui/async_yields_async.rs +++ b/tests/ui/async_yields_async.rs @@ -22,6 +22,12 @@ fn custom_future_type_ctor() -> CustomFutureType { CustomFutureType } +async fn f() -> CustomFutureType { + // Don't warn for functions since you have to explicitly declare their + // return types. + CustomFutureType +} + #[rustfmt::skip] fn main() { let _f = { @@ -58,4 +64,5 @@ fn main() { CustomFutureType }; let _n = async || custom_future_type_ctor(); + let _o = async || f(); } diff --git a/tests/ui/async_yields_async.stderr b/tests/ui/async_yields_async.stderr index 112984cdccb..17d0c375106 100644 --- a/tests/ui/async_yields_async.stderr +++ b/tests/ui/async_yields_async.stderr @@ -1,5 +1,5 @@ error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:34:9 + --> $DIR/async_yields_async.rs:40:9 | LL | let _h = async { | ____________________- @@ -20,7 +20,7 @@ LL | }.await | error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:39:9 + --> $DIR/async_yields_async.rs:45:9 | LL | let _i = async { | ____________________- @@ -33,7 +33,7 @@ LL | | }; | |_____- outer async construct error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:45:9 + --> $DIR/async_yields_async.rs:51:9 | LL | let _j = async || { | _______________________- @@ -53,7 +53,7 @@ LL | }.await | error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:50:9 + --> $DIR/async_yields_async.rs:56:9 | LL | let _k = async || { | _______________________- @@ -66,7 +66,7 @@ LL | | }; | |_____- outer async construct error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:52:23 + --> $DIR/async_yields_async.rs:58:23 | LL | let _l = async || CustomFutureType; | ^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | let _l = async || CustomFutureType; | help: consider awaiting this value: `CustomFutureType.await` error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:58:9 + --> $DIR/async_yields_async.rs:64:9 | LL | let _m = async || { | _______________________- From 04912ca115ff153a97d80b604435b10dcb155dd0 Mon Sep 17 00:00:00 2001 From: Kyle Huey <khuey@kylehuey.com> Date: Sat, 22 Aug 2020 21:40:01 -0700 Subject: [PATCH 516/526] Formatting changes requested by ThibsG. --- clippy_lints/src/async_yields_async.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/async_yields_async.rs b/clippy_lints/src/async_yields_async.rs index ae347fcd3e8..88d9d3b5a26 100644 --- a/clippy_lints/src/async_yields_async.rs +++ b/clippy_lints/src/async_yields_async.rs @@ -5,12 +5,10 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { - /// **What it does:** - /// Checks for async blocks that yield values of types that can themselves - /// be awaited. + /// **What it does:** Checks for async blocks that yield values of types + /// that can themselves be awaited. /// - /// **Why is this bad?** - /// An await is likely missing. + /// **Why is this bad?** An await is likely missing. /// /// **Known problems:** None. /// From 17b2ba5ded12f59dba63ece659b5cd714b763800 Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Sun, 30 Aug 2020 11:24:15 -0700 Subject: [PATCH 517/526] Syntax-highlight `single_char_push_str` lint --- clippy_lints/src/methods/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 9996df69470..7c4a78cbdcd 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1324,20 +1324,20 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Warns when using push_str with a single-character string literal, - /// and push with a char would work fine. + /// **What it does:** Warns when using `push_str` with a single-character string literal, + /// and `push` with a `char` would work fine. /// - /// **Why is this bad?** It's less clear that we are pushing a single character + /// **Why is this bad?** It's less clear that we are pushing a single character. /// /// **Known problems:** None /// /// **Example:** - /// ``` + /// ```rust /// let mut string = String::new(); /// string.push_str("R"); /// ``` /// Could be written as - /// ``` + /// ```rust /// let mut string = String::new(); /// string.push('R'); /// ``` From 001f9e45f24c5617d816e7d9dfbca4dc1a694dd9 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata <f.seasons017@gmail.com> Date: Tue, 1 Sep 2020 00:05:53 +0900 Subject: [PATCH 518/526] Fix the wrong suggestion when using macro in `collapsible_if` --- clippy_lints/src/utils/sugg.rs | 6 +++++- tests/ui/collapsible_if.fixed | 3 +++ tests/ui/collapsible_if.rs | 5 +++++ tests/ui/collapsible_if.stderr | 10 +++++++++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 2955f8d8e59..811fde388d1 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -132,7 +132,11 @@ impl<'a> Sugg<'a> { pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self { use rustc_ast::ast::RangeLimits; - let snippet = snippet(cx, expr.span, default); + let snippet = if expr.span.from_expansion() { + snippet_with_macro_callsite(cx, expr.span, default) + } else { + snippet(cx, expr.span, default) + }; match expr.kind { ast::ExprKind::AddrOf(..) diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index 561283fc8e7..efd4187947b 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -135,4 +135,7 @@ fn main() { if truth() {} } } + + // Fix #5962 + if matches!(true, true) && matches!(true, true) {} } diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index dc9d9b451c0..657f32d38a3 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -149,4 +149,9 @@ fn main() { if truth() {} } } + + // Fix #5962 + if matches!(true, true) { + if matches!(true, true) {} + } } diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index f56dd65b9dd..acd1ec3f2ca 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -118,5 +118,13 @@ LL | println!("Hello world!"); LL | } | -error: aborting due to 7 previous errors +error: this `if` statement can be collapsed + --> $DIR/collapsible_if.rs:154:5 + | +LL | / if matches!(true, true) { +LL | | if matches!(true, true) {} +LL | | } + | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}` + +error: aborting due to 8 previous errors From 8b0aa6a00b19b8e47a72157ec8e8f9e9060cb2fb Mon Sep 17 00:00:00 2001 From: Taiki Endo <te316e89@gmail.com> Date: Tue, 1 Sep 2020 00:31:53 +0900 Subject: [PATCH 519/526] default_trait_access: Fix wrong suggestion --- clippy_lints/src/default_trait_access.rs | 4 +- tests/ui/default_trait_access.fixed | 106 +++++++++++++++++++++++ tests/ui/default_trait_access.rs | 5 +- tests/ui/default_trait_access.stderr | 26 +++--- 4 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 tests/ui/default_trait_access.fixed diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 067ea903bdd..0b0a1307876 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -55,8 +55,8 @@ impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess { // TODO: Work out a way to put "whatever the imported way of referencing // this type in this file" rather than a fully-qualified type. let expr_ty = cx.typeck_results().expr_ty(expr); - if let ty::Adt(..) = expr_ty.kind { - let replacement = format!("{}::default()", expr_ty); + if let ty::Adt(def, ..) = expr_ty.kind { + let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did)); span_lint_and_sugg( cx, DEFAULT_TRAIT_ACCESS, diff --git a/tests/ui/default_trait_access.fixed b/tests/ui/default_trait_access.fixed new file mode 100644 index 00000000000..d05567a3f82 --- /dev/null +++ b/tests/ui/default_trait_access.fixed @@ -0,0 +1,106 @@ +// run-rustfix + +#![allow(unused_imports)] +#![deny(clippy::default_trait_access)] + +use std::default; +use std::default::Default as D2; +use std::string; + +fn main() { + let s1: String = std::string::String::default(); + + let s2 = String::default(); + + let s3: String = std::string::String::default(); + + let s4: String = std::string::String::default(); + + let s5 = string::String::default(); + + let s6: String = std::string::String::default(); + + let s7 = std::string::String::default(); + + let s8: String = DefaultFactory::make_t_badly(); + + let s9: String = DefaultFactory::make_t_nicely(); + + let s10 = DerivedDefault::default(); + + let s11: GenericDerivedDefault<String> = GenericDerivedDefault::default(); + + let s12 = GenericDerivedDefault::<String>::default(); + + let s13 = TupleDerivedDefault::default(); + + let s14: TupleDerivedDefault = TupleDerivedDefault::default(); + + let s15: ArrayDerivedDefault = ArrayDerivedDefault::default(); + + let s16 = ArrayDerivedDefault::default(); + + let s17: TupleStructDerivedDefault = TupleStructDerivedDefault::default(); + + let s18 = TupleStructDerivedDefault::default(); + + let s19 = <DerivedDefault as Default>::default(); + + println!( + "[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}], [{:?}]", + s1, + s2, + s3, + s4, + s5, + s6, + s7, + s8, + s9, + s10, + s11, + s12, + s13, + s14, + s15, + s16, + s17, + s18, + s19, + ); +} + +struct DefaultFactory; + +impl DefaultFactory { + pub fn make_t_badly<T: Default>() -> T { + Default::default() + } + + pub fn make_t_nicely<T: Default>() -> T { + T::default() + } +} + +#[derive(Debug, Default)] +struct DerivedDefault { + pub s: String, +} + +#[derive(Debug, Default)] +struct GenericDerivedDefault<T: Default + std::fmt::Debug> { + pub s: T, +} + +#[derive(Debug, Default)] +struct TupleDerivedDefault { + pub s: (String, String), +} + +#[derive(Debug, Default)] +struct ArrayDerivedDefault { + pub s: [String; 10], +} + +#[derive(Debug, Default)] +struct TupleStructDerivedDefault(String); diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index 2f1490a7036..447e70c0bbb 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -1,4 +1,7 @@ -#![warn(clippy::default_trait_access)] +// run-rustfix + +#![allow(unused_imports)] +#![deny(clippy::default_trait_access)] use std::default; use std::default::Default as D2; diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index 26b2057548b..df8a5b94ddc 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -1,49 +1,53 @@ error: calling `std::string::String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:8:22 + --> $DIR/default_trait_access.rs:11:22 | LL | let s1: String = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` | - = note: `-D clippy::default-trait-access` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/default_trait_access.rs:4:9 + | +LL | #![deny(clippy::default_trait_access)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `std::string::String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:12:22 + --> $DIR/default_trait_access.rs:15:22 | LL | let s3: String = D2::default(); | ^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: calling `std::string::String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:14:22 + --> $DIR/default_trait_access.rs:17:22 | LL | let s4: String = std::default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: calling `std::string::String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:18:22 + --> $DIR/default_trait_access.rs:21:22 | LL | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` -error: calling `GenericDerivedDefault<std::string::String>::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:28:46 +error: calling `GenericDerivedDefault::default()` is more clear than this expression + --> $DIR/default_trait_access.rs:31:46 | LL | let s11: GenericDerivedDefault<String> = Default::default(); - | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault<std::string::String>::default()` + | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` error: calling `TupleDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:34:36 + --> $DIR/default_trait_access.rs:37:36 | LL | let s14: TupleDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` error: calling `ArrayDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:36:36 + --> $DIR/default_trait_access.rs:39:36 | LL | let s15: ArrayDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` error: calling `TupleStructDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:40:42 + --> $DIR/default_trait_access.rs:43:42 | LL | let s17: TupleStructDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` From afeb917fca7eaa5b44acd29a60f687024c0ebeac Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Tue, 1 Sep 2020 11:21:48 +1200 Subject: [PATCH 520/526] Fix a fp in `transmute_ptr_to_ptr` Avoid firing the lint when `transmute` in const contexts as dereferencing raw pointers in consts is unstable. cc #5959 --- clippy_lints/src/transmute.rs | 6 ++++-- tests/ui/transmute_ptr_to_ptr.rs | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 50d9c93f9d4..789d124eae2 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -331,8 +331,9 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::TRANSMUTE); then { - // Avoid suggesting from/to bits in const contexts. + // Avoid suggesting from/to bits and dereferencing raw pointers in const contexts. // See https://github.com/rust-lang/rust/issues/73736 for progress on making them `const fn`. + // And see https://github.com/rust-lang/rust/issues/51911 for dereferencing raw pointers. let const_context = in_constant(cx, e.hir_id); let from_ty = cx.typeck_results().expr_ty(&args[0]); @@ -486,7 +487,8 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { Applicability::Unspecified, ); } else { - if cx.tcx.erase_regions(&from_ty) != cx.tcx.erase_regions(&to_ty) { + if (cx.tcx.erase_regions(&from_ty) != cx.tcx.erase_regions(&to_ty)) + && !const_context { span_lint_and_then( cx, TRANSMUTE_PTR_TO_PTR, diff --git a/tests/ui/transmute_ptr_to_ptr.rs b/tests/ui/transmute_ptr_to_ptr.rs index 0d8a322f2b2..26b03bdc740 100644 --- a/tests/ui/transmute_ptr_to_ptr.rs +++ b/tests/ui/transmute_ptr_to_ptr.rs @@ -51,4 +51,12 @@ fn transmute_ptr_to_ptr() { let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) }; } +// dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959) +const _: &() = { + struct ZST; + let zst = &ZST; + + unsafe { std::mem::transmute::<&'static ZST, &'static ()>(zst) } +}; + fn main() {} From 2e4b4cebbbb37efa5dc69dd2616f3b7a288b92aa Mon Sep 17 00:00:00 2001 From: Taiki Endo <te316e89@gmail.com> Date: Tue, 1 Sep 2020 12:09:32 +0900 Subject: [PATCH 521/526] useless_attribute: Permit wildcard_imports and enum_glob_use --- clippy_lints/src/attrs.rs | 38 ++++++++++++++++++------------- tests/ui/useless_attribute.fixed | 8 +++++++ tests/ui/useless_attribute.rs | 8 +++++++ tests/ui/useless_attribute.stderr | 2 +- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index cfcc1b3c5f3..c8f153e7201 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -71,8 +71,9 @@ declare_clippy_lint! { /// **What it does:** Checks for `extern crate` and `use` items annotated with /// lint attributes. /// - /// This lint permits `#[allow(unused_imports)]`, `#[allow(deprecated)]` and - /// `#[allow(unreachable_pub)]` on `use` items and `#[allow(unused_imports)]` on + /// This lint permits `#[allow(unused_imports)]`, `#[allow(deprecated)]`, + /// `#[allow(unreachable_pub)]`, `#[allow(clippy::wildcard_imports)]` and + /// `#[allow(clippy::enum_glob_use)]` on `use` items and `#[allow(unused_imports)]` on /// `extern crate` items with a `#[macro_use]` attribute. /// /// **Why is this bad?** Lint attributes have no effect on crate imports. Most @@ -318,7 +319,8 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { if let Some(ident) = attr.ident() { match &*ident.as_str() { "allow" | "warn" | "deny" | "forbid" => { - // permit `unused_imports`, `deprecated` and `unreachable_pub` for `use` items + // permit `unused_imports`, `deprecated`, `unreachable_pub`, + // `clippy::wildcard_imports`, and `clippy::enum_glob_use` for `use` items // and `unused_imports` for `extern crate` items with `macro_use` for lint in lint_list { match item.kind { @@ -327,6 +329,9 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { || is_word(lint, sym!(deprecated)) || is_word(lint, sym!(unreachable_pub)) || is_word(lint, sym!(unused)) + || extract_clippy_lint(lint) + .map_or(false, |s| s == "wildcard_imports") + || extract_clippy_lint(lint).map_or(false, |s| s == "enum_glob_use") { return; } @@ -387,24 +392,25 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { } } -fn check_clippy_lint_names(cx: &LateContext<'_>, ident: &str, items: &[NestedMetaItem]) { - fn extract_name(lint: &NestedMetaItem) -> Option<SymbolStr> { - if_chain! { - if let Some(meta_item) = lint.meta_item(); - if meta_item.path.segments.len() > 1; - if let tool_name = meta_item.path.segments[0].ident; - if tool_name.as_str() == "clippy"; - let lint_name = meta_item.path.segments.last().unwrap().ident.name; - then { - return Some(lint_name.as_str()); - } +/// Returns the lint name if it is clippy lint. +fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<SymbolStr> { + if_chain! { + if let Some(meta_item) = lint.meta_item(); + if meta_item.path.segments.len() > 1; + if let tool_name = meta_item.path.segments[0].ident; + if tool_name.as_str() == "clippy"; + let lint_name = meta_item.path.segments.last().unwrap().ident.name; + then { + return Some(lint_name.as_str()); } - None } + None +} +fn check_clippy_lint_names(cx: &LateContext<'_>, ident: &str, items: &[NestedMetaItem]) { let lint_store = cx.lints(); for lint in items { - if let Some(lint_name) = extract_name(lint) { + if let Some(lint_name) = extract_clippy_lint(lint) { if let CheckLintNameResult::Tool(Err((None, _))) = lint_store.check_lint_name(&lint_name, Some(sym!(clippy))) { diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index b222e2f7976..a5fcde768f1 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -49,6 +49,14 @@ mod a { pub use self::b::C; } +// don't lint on clippy::wildcard_imports for `use` items +#[allow(clippy::wildcard_imports)] +pub use std::io::prelude::*; + +// don't lint on clippy::enum_glob_use for `use` items +#[allow(clippy::enum_glob_use)] +pub use std::cmp::Ordering::*; + fn test_indented_attr() { #![allow(clippy::almost_swapped)] use std::collections::HashSet; diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 3422eace4ab..0396d39e3d5 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -49,6 +49,14 @@ mod a { pub use self::b::C; } +// don't lint on clippy::wildcard_imports for `use` items +#[allow(clippy::wildcard_imports)] +pub use std::io::prelude::*; + +// don't lint on clippy::enum_glob_use for `use` items +#[allow(clippy::enum_glob_use)] +pub use std::cmp::Ordering::*; + fn test_indented_attr() { #[allow(clippy::almost_swapped)] use std::collections::HashSet; diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 57ba976730c..d0194e4bbbe 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -13,7 +13,7 @@ LL | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)` error: useless lint attribute - --> $DIR/useless_attribute.rs:53:5 + --> $DIR/useless_attribute.rs:61:5 | LL | #[allow(clippy::almost_swapped)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(clippy::almost_swapped)]` From b30422114e6bb7235398f21fe13ffa09429b7d0f Mon Sep 17 00:00:00 2001 From: Koxiaet <38139193+Koxiaet@users.noreply.github.com> Date: Tue, 1 Sep 2020 14:05:19 +0100 Subject: [PATCH 522/526] Allow GraphQL in doc without backticks --- clippy_lints/src/utils/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 292dbd7ad6b..9c5a12ea9c8 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -122,7 +122,7 @@ define_Conf! { "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", - "OAuth", + "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "TensorFlow", From a5754a1fad6eeb765bc825dcc657134985576787 Mon Sep 17 00:00:00 2001 From: Eduardo Broto <ebroto@tutanota.com> Date: Wed, 2 Sep 2020 08:57:00 +0200 Subject: [PATCH 523/526] Run cargo dev fmt --- clippy_lints/src/utils/ast_utils.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/ast_utils.rs b/clippy_lints/src/utils/ast_utils.rs index 3c3f8b26e3a..fa8dd210eba 100644 --- a/clippy_lints/src/utils/ast_utils.rs +++ b/clippy_lints/src/utils/ast_utils.rs @@ -191,7 +191,9 @@ pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool { (Item(l), Item(r)) => eq_item(l, r, eq_item_kind), (Expr(l), Expr(r)) | (Semi(l), Semi(r)) => eq_expr(l, r), (Empty, Empty) => true, - (MacCall(l), MacCall(r)) => l.style == r.style && eq_mac_call(&l.mac, &r.mac) && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)), + (MacCall(l), MacCall(r)) => { + l.style == r.style && eq_mac_call(&l.mac, &r.mac) && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) + }, _ => false, } } From 22c994061359aa9e0e08e44cd698dbfc6553834c Mon Sep 17 00:00:00 2001 From: Koxiaet <38139193+Koxiaet@users.noreply.github.com> Date: Wed, 2 Sep 2020 12:51:44 +0100 Subject: [PATCH 524/526] Add tests for allowed non-backticked identifiers in doc --- tests/ui/doc.rs | 13 +++++++++--- tests/ui/doc.stderr | 50 +++++++++++++++++++++++++-------------------- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 77620c857e6..68c5d32846f 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -49,6 +49,16 @@ fn test_emphasis() { fn test_units() { } +/// This tests allowed identifiers. +/// DirectX +/// ECMAScript +/// OAuth GraphQL +/// TeX LaTeX BibTeX BibLaTeX +/// CamelCase (see also #2395) +/// be_sure_we_got_to_the_end_of_it +fn test_allowed() { +} + /// This test has [a link_with_underscores][chunked-example] inside it. See #823. /// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues) /// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link]. @@ -168,9 +178,6 @@ fn issue_1920() {} /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels fn issue_1832() {} -/// Ok: CamelCase (It should not be surrounded by backticks) -fn issue_2395() {} - /// An iterator over mycrate::Collection's values. /// It should not lint a `'static` lifetime in ticks. fn issue_2210() {} diff --git a/tests/ui/doc.stderr b/tests/ui/doc.stderr index ae9bb394cb9..23fca43590b 100644 --- a/tests/ui/doc.stderr +++ b/tests/ui/doc.stderr @@ -54,131 +54,137 @@ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the doc LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation + --> $DIR/doc.rs:58:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: you should put `link_with_underscores` between ticks in the documentation - --> $DIR/doc.rs:52:22 + --> $DIR/doc.rs:62:22 | LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. | ^^^^^^^^^^^^^^^^^^^^^ error: you should put `inline_link2` between ticks in the documentation - --> $DIR/doc.rs:55:21 + --> $DIR/doc.rs:65:21 | LL | /// It can also be [inline_link2]. | ^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:65:5 + --> $DIR/doc.rs:75:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:73:8 + --> $DIR/doc.rs:83:8 | LL | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:76:7 + --> $DIR/doc.rs:86:7 | LL | /// # CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:78:22 + --> $DIR/doc.rs:88:22 | LL | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:79:5 + --> $DIR/doc.rs:89:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:86:5 + --> $DIR/doc.rs:96:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:99:5 + --> $DIR/doc.rs:109:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:110:43 + --> $DIR/doc.rs:120:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:115:5 + --> $DIR/doc.rs:125:5 | LL | And BarQuz too. | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:116:1 + --> $DIR/doc.rs:126:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:121:43 + --> $DIR/doc.rs:131:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:126:5 + --> $DIR/doc.rs:136:5 | LL | And BarQuz too. | ^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:127:1 + --> $DIR/doc.rs:137:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:138:5 + --> $DIR/doc.rs:148:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:165:13 + --> $DIR/doc.rs:175:13 | LL | /// Not ok: http://www.unicode.org | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:166:13 + --> $DIR/doc.rs:176:13 | LL | /// Not ok: https://www.unicode.org | ^^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:167:13 + --> $DIR/doc.rs:177:13 | LL | /// Not ok: http://www.unicode.org/ | ^^^^^^^^^^^^^^^^^^^^^^ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:168:13 + --> $DIR/doc.rs:178:13 | LL | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you should put `mycrate::Collection` between ticks in the documentation - --> $DIR/doc.rs:174:22 + --> $DIR/doc.rs:181:22 | LL | /// An iterator over mycrate::Collection's values. | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 30 previous errors +error: aborting due to 31 previous errors From 93ce686b5df94f52a040a05c9434b4341efffec5 Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Thu, 3 Sep 2020 04:58:14 +0200 Subject: [PATCH 525/526] Update ui stderr with improved rustc output Related rust pull request: rust-lang/rust#76160 --- tests/ui/issue-3145.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/issue-3145.stderr b/tests/ui/issue-3145.stderr index cb0d95f5e26..8f2922b022a 100644 --- a/tests/ui/issue-3145.stderr +++ b/tests/ui/issue-3145.stderr @@ -1,4 +1,4 @@ -error: expected token: `,` +error: expected `,`, found `a` --> $DIR/issue-3145.rs:2:19 | LL | println!("{}" a); //~ERROR expected token: `,` From cf1cc7c449e881f0ac5d8474209222bc269df250 Mon Sep 17 00:00:00 2001 From: Michael Wright <mikerite@lavabit.com> Date: Fri, 4 Sep 2020 05:15:31 +0200 Subject: [PATCH 526/526] Simplify `clippy::default_trait_access` Remove repeated matching on the same QPath. --- clippy_lints/src/default_trait_access.rs | 46 +++++++++--------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 0b0a1307876..320a2a257bd 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -38,37 +38,23 @@ impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess { if let ExprKind::Path(ref qpath) = path.kind; if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); + // Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type. + if let QPath::Resolved(None, _path) = qpath; then { - match qpath { - QPath::Resolved(..) => { - if_chain! { - // Detect and ignore <Foo as Default>::default() because these calls do - // explicitly name the type. - if let ExprKind::Call(ref method, ref _args) = expr.kind; - if let ExprKind::Path(ref p) = method.kind; - if let QPath::Resolved(Some(_ty), _path) = p; - then { - return; - } - } - - // TODO: Work out a way to put "whatever the imported way of referencing - // this type in this file" rather than a fully-qualified type. - let expr_ty = cx.typeck_results().expr_ty(expr); - if let ty::Adt(def, ..) = expr_ty.kind { - let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did)); - span_lint_and_sugg( - cx, - DEFAULT_TRAIT_ACCESS, - expr.span, - &format!("calling `{}` is more clear than this expression", replacement), - "try", - replacement, - Applicability::Unspecified, // First resolve the TODO above - ); - } - }, - QPath::TypeRelative(..) | QPath::LangItem(..) => {}, + let expr_ty = cx.typeck_results().expr_ty(expr); + if let ty::Adt(def, ..) = expr_ty.kind { + // TODO: Work out a way to put "whatever the imported way of referencing + // this type in this file" rather than a fully-qualified type. + let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did)); + span_lint_and_sugg( + cx, + DEFAULT_TRAIT_ACCESS, + expr.span, + &format!("calling `{}` is more clear than this expression", replacement), + "try", + replacement, + Applicability::Unspecified, // First resolve the TODO above + ); } } }