let hir::Item_::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node,
trait_ref.path.def.def_id() == trait_id
], { return; }}
- implements_trait($cx, $ty, trait_id, vec![$rty])
+ implements_trait($cx, $ty, trait_id, &[$rty], None)
},)*
_ => false,
}
return false;
};
- if implements_trait(cx, arg_ty, default_trait_id, Vec::new()) {
+ if implements_trait(cx, arg_ty, default_trait_id, &[], None) {
span_lint_and_then(cx,
OR_FUN_CALL,
span,
/// This checks whether a given type is known to implement Debug.
fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool {
match cx.tcx.lang_items.debug_trait() {
- Some(debug) => implements_trait(cx, ty, debug, Vec::new()),
+ Some(debug) => implements_trait(cx, ty, debug, &[], None),
None => false,
}
}
None => return,
};
- if !implements_trait(cx, arg_ty, partial_eq_trait_id, vec![other_ty]) {
+ if !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty], None) {
return;
}
self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
same_tys(cx, self_ty, return_ty(cx, id), id),
let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT),
- !implements_trait(cx, self_ty, default_trait_id, Vec::new())
+ !implements_trait(cx, self_ty, default_trait_id, &[], None)
], {
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
span_lint_and_then(cx,
ty::TyAdt(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, Vec::new()) {
+ if !implements_trait(cx, f_ty, default_trait_id, &[], None) {
return None;
}
}
use rustc::lint::*;
use rustc::hir::*;
-use utils::{paths, is_direct_expn_of, get_trait_def_id, implements_trait, span_lint};
+use utils::{is_direct_expn_of, implements_trait, span_lint};
/// **What it does:** Checks for `assert!(x == y)` which can be written better
/// as `assert_eq!(x, y)` if `x` and `y` implement `Debug` trait.
///
/// **Why is this bad?** `assert_eq` provides better assertion failure reporting.
///
-/// **Known problems:** None.
+/// **Known problems:** Hopefully none.
///
/// **Example:**
/// ```rust
return;
}
- let debug_trait = get_trait_def_id(cx, &paths::DEBUG_TRAIT)
- .expect("cannot find Debug trait");
+ let debug_trait = if let Some(t) = cx.tcx.lang_items.debug_trait() {
+ t
+ } else {
+ return;
+ };
let ty1 = cx.tables.expr_ty(expr1);
let ty2 = cx.tables.expr_ty(expr2);
- if implements_trait(cx, ty1, debug_trait, vec![]) &&
- implements_trait(cx, ty2, debug_trait, vec![]) {
+
+ let parent = cx.tcx.hir.get_parent(e.id);
+
+ if implements_trait(cx, ty1, debug_trait, &[], Some(parent)) &&
+ implements_trait(cx, ty2, debug_trait, &[], Some(parent)) {
span_lint(cx, SHOULD_ASSERT_EQ, e.span, "use `assert_eq` for better reporting");
}
}}
cx: &LateContext<'a, 'tcx>,
ty: ty::Ty<'tcx>,
trait_id: DefId,
- ty_params: Vec<ty::Ty<'tcx>>
+ ty_params: &[ty::Ty<'tcx>],
+ parent_node_id: Option<NodeId>
) -> bool {
cx.tcx.populate_implementations_for_trait_if_necessary(trait_id);
let ty = cx.tcx.erase_regions(&ty);
- cx.tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
- let obligation = cx.tcx.predicate_for_trait_def(traits::ObligationCause::dummy(), trait_id, 0, ty, &ty_params);
+ let mut b = if let Some(id) = parent_node_id {
+ cx.tcx.infer_ctxt(BodyId { node_id: id }, Reveal::All)
+ } else {
+ cx.tcx.infer_ctxt((), Reveal::All)
+ };
+ b.enter(|infcx| {
+ let obligation = cx.tcx.predicate_for_trait_def(traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params);
traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation)
})
pub const COW: [&'static str; 3] = ["collections", "borrow", "Cow"];
pub const CSTRING_NEW: [&'static str; 5] = ["std", "ffi", "c_str", "CString", "new"];
pub const DEBUG_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Debug", "fmt"];
-pub const DEBUG_TRAIT: [&'static str; 3] = ["core", "fmt", "Debug"];
pub const DEFAULT_TRAIT: [&'static str; 3] = ["core", "default", "Default"];
pub const DISPLAY_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Display", "fmt"];
pub const DROP: [&'static str; 3] = ["core", "mem", "drop"];
assert!(1 == 2);
assert!(Debug(1) == Debug(2));
assert!(NonDebug(1) == NonDebug(1)); // ok
+
+ test_generic(1, 2, 3, 4);
+}
+
+fn test_generic<T: std::fmt::Debug + Eq, U: Eq>(x: T, y: T, z: U, w: U) {
+ assert!(x == y);
+ assert!(z == w); // ok
}
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 2 previous errors
+error: use `assert_eq` for better reporting
+ --> $DIR/should_assert_eq.rs:21:5
+ |
+21 | assert!(x == y);
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in a macro outside of the current crate
+
+error: aborting due to 3 previous errors