Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to look up a method within the compiler given the type and a name?

Tags:

lint

rust

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?

like image 416
llogiq Avatar asked Jun 01 '15 09:06

llogiq


1 Answers

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 DefIds 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...

like image 120
llogiq Avatar answered Oct 19 '22 12:10

llogiq