Skip to content

Commit 8cb2ec8

Browse files
committed
Support generic type
1 parent 16e53c9 commit 8cb2ec8

File tree

9 files changed

+43
-17
lines changed

9 files changed

+43
-17
lines changed

clippy_lints/src/assign_ops.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
152152
let hir::Item_::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node,
153153
trait_ref.path.def.def_id() == trait_id
154154
], { return; }}
155-
implements_trait($cx, $ty, trait_id, vec![$rty])
155+
implements_trait($cx, $ty, trait_id, &[$rty], None)
156156
},)*
157157
_ => false,
158158
}

clippy_lints/src/methods.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir:
724724
return false;
725725
};
726726

727-
if implements_trait(cx, arg_ty, default_trait_id, Vec::new()) {
727+
if implements_trait(cx, arg_ty, default_trait_id, &[], None) {
728728
span_lint_and_then(cx,
729729
OR_FUN_CALL,
730730
span,
@@ -1268,7 +1268,7 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> {
12681268
/// This checks whether a given type is known to implement Debug.
12691269
fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool {
12701270
match cx.tcx.lang_items.debug_trait() {
1271-
Some(debug) => implements_trait(cx, ty, debug, Vec::new()),
1271+
Some(debug) => implements_trait(cx, ty, debug, &[], None),
12721272
None => false,
12731273
}
12741274
}

clippy_lints/src/misc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S
420420
None => return,
421421
};
422422

423-
if !implements_trait(cx, arg_ty, partial_eq_trait_id, vec![other_ty]) {
423+
if !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty], None) {
424424
return;
425425
}
426426

clippy_lints/src/new_without_default.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
115115
self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
116116
same_tys(cx, self_ty, return_ty(cx, id), id),
117117
let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT),
118-
!implements_trait(cx, self_ty, default_trait_id, Vec::new())
118+
!implements_trait(cx, self_ty, default_trait_id, &[], None)
119119
], {
120120
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
121121
span_lint_and_then(cx,
@@ -156,7 +156,7 @@ fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_
156156
ty::TyAdt(adt_def, substs) if adt_def.is_struct() => {
157157
for field in adt_def.all_fields() {
158158
let f_ty = field.ty(cx.tcx, substs);
159-
if !implements_trait(cx, f_ty, default_trait_id, Vec::new()) {
159+
if !implements_trait(cx, f_ty, default_trait_id, &[], None) {
160160
return None;
161161
}
162162
}

clippy_lints/src/should_assert_eq.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use rustc::lint::*;
22
use rustc::hir::*;
3-
use utils::{paths, is_direct_expn_of, get_trait_def_id, implements_trait, span_lint};
3+
use utils::{is_direct_expn_of, implements_trait, span_lint};
44

55
/// **What it does:** Checks for `assert!(x == y)` which can be written better
66
/// as `assert_eq!(x, y)` if `x` and `y` implement `Debug` trait.
77
///
88
/// **Why is this bad?** `assert_eq` provides better assertion failure reporting.
99
///
10-
/// **Known problems:** None.
10+
/// **Known problems:** Hopefully none.
1111
///
1212
/// **Example:**
1313
/// ```rust
@@ -45,13 +45,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ShouldAssertEq {
4545
return;
4646
}
4747

48-
let debug_trait = get_trait_def_id(cx, &paths::DEBUG_TRAIT)
49-
.expect("cannot find Debug trait");
48+
let debug_trait = if let Some(t) = cx.tcx.lang_items.debug_trait() {
49+
t
50+
} else {
51+
return;
52+
};
5053

5154
let ty1 = cx.tables.expr_ty(expr1);
5255
let ty2 = cx.tables.expr_ty(expr2);
53-
if implements_trait(cx, ty1, debug_trait, vec![]) &&
54-
implements_trait(cx, ty2, debug_trait, vec![]) {
56+
57+
let parent = cx.tcx.hir.get_parent(e.id);
58+
59+
if implements_trait(cx, ty1, debug_trait, &[], Some(parent)) &&
60+
implements_trait(cx, ty2, debug_trait, &[], Some(parent)) {
5561
span_lint(cx, SHOULD_ASSERT_EQ, e.span, "use `assert_eq` for better reporting");
5662
}
5763
}}

clippy_lints/src/utils/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,13 +317,19 @@ pub fn implements_trait<'a, 'tcx>(
317317
cx: &LateContext<'a, 'tcx>,
318318
ty: ty::Ty<'tcx>,
319319
trait_id: DefId,
320-
ty_params: Vec<ty::Ty<'tcx>>
320+
ty_params: &[ty::Ty<'tcx>],
321+
parent_node_id: Option<NodeId>
321322
) -> bool {
322323
cx.tcx.populate_implementations_for_trait_if_necessary(trait_id);
323324

324325
let ty = cx.tcx.erase_regions(&ty);
325-
cx.tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
326-
let obligation = cx.tcx.predicate_for_trait_def(traits::ObligationCause::dummy(), trait_id, 0, ty, &ty_params);
326+
let mut b = if let Some(id) = parent_node_id {
327+
cx.tcx.infer_ctxt(BodyId { node_id: id }, Reveal::All)
328+
} else {
329+
cx.tcx.infer_ctxt((), Reveal::All)
330+
};
331+
b.enter(|infcx| {
332+
let obligation = cx.tcx.predicate_for_trait_def(traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params);
327333

328334
traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation)
329335
})

clippy_lints/src/utils/paths.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ pub const CMP_MIN: [&'static str; 3] = ["core", "cmp", "min"];
1515
pub const COW: [&'static str; 3] = ["collections", "borrow", "Cow"];
1616
pub const CSTRING_NEW: [&'static str; 5] = ["std", "ffi", "c_str", "CString", "new"];
1717
pub const DEBUG_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Debug", "fmt"];
18-
pub const DEBUG_TRAIT: [&'static str; 3] = ["core", "fmt", "Debug"];
1918
pub const DEFAULT_TRAIT: [&'static str; 3] = ["core", "default", "Default"];
2019
pub const DISPLAY_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Display", "fmt"];
2120
pub const DROP: [&'static str; 3] = ["core", "mem", "drop"];

tests/ui/should_assert_eq.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,11 @@ fn main() {
1313
assert!(1 == 2);
1414
assert!(Debug(1) == Debug(2));
1515
assert!(NonDebug(1) == NonDebug(1)); // ok
16+
17+
test_generic(1, 2, 3, 4);
18+
}
19+
20+
fn test_generic<T: std::fmt::Debug + Eq, U: Eq>(x: T, y: T, z: U, w: U) {
21+
assert!(x == y);
22+
assert!(z == w); // ok
1623
}

tests/ui/should_assert_eq.stderr

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,13 @@ error: use `assert_eq` for better reporting
1919
|
2020
= note: this error originates in a macro outside of the current crate
2121

22-
error: aborting due to 2 previous errors
22+
error: use `assert_eq` for better reporting
23+
--> $DIR/should_assert_eq.rs:21:5
24+
|
25+
21 | assert!(x == y);
26+
| ^^^^^^^^^^^^^^^^
27+
|
28+
= note: this error originates in a macro outside of the current crate
29+
30+
error: aborting due to 3 previous errors
2331

0 commit comments

Comments
 (0)