I have a lint that warns on x.len() == 0
, suggesting to use x.is_empty()
instead. However, I wanted to get rid of the false positives if x
has no is_empty(self: &Self)
method.
Thus began the quest to look up methods from within rustc.
First step, get the x
: I matched the node
of an Expr
to ExprMethodCall(ref method, _, ref args)
(and made sure that args.len() == 1
and method.node.as_str() == "len"
) and just used &*args[0]
, which I will call expr
from now on.
Next step, get the type of x
: This can easily be done using rustc::middle::ty::expr_ty(cx.tcx, expr)
. Note that this is a rustc::middle::ty::Ty
(and not a syntax::ast::Ty
, which led to some confusion).
To look up the methods, the ctxt.impl_items
and ctxt.trait_item_def_ids
looked promising, so I get the DefId
for my type with rustc::middle::ty::ty::ty_to_def_id(ty)
and try to get the ids. However, this approach has a few problems:
For
let x = [1, 2];
x.len() == 2 // <- lookee here
I simply have no DefId. That is ok though, because we have a ty_vec
in that case, and std::vec::Vec
is known to have both len()
and is_empty()
.
The good message is that the ctxt.trait_item_def_ids
has a suitable entry for a trait with a is_empty
method. Alas, for the following example:
struct One;
impl One { fn is_empty(self: &Self) -> bool { false } }
I got no TraitOrItemId
for any impl item, which is a bit unfortunate. Can someone privy to rustc help me find my impl items?
I got it! The problem was that I trying to get a DefId for the type, not for the impl
. Going through cx.tcx.inherent_impls.get(id)
gave me a vec of DefId
s for inherent impls, which I could then query via the impl_items
lookup I already implemented.
Look in rust-clippy/src/len_zero.rs for an example implementation. Edit: Note that the implementation is O(N) where N is the number of methods of the type (either direct impl
or by traits) – perhaps rustc will someday allow a faster lookup...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With