如何在给定类型和名称的情况下在编译器中查找方法?

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

我有一个在 x.len() == 0 上发出警告的 lint,建议改用 x.is_empty()。但是,如果 x 没有 is_empty(self: &Self) 方法,我想消除误报。

因此开始了从 rustc 中查找方法的探索。

第一步,获取 x:我将 Exprnode 匹配到 ExprMethodCall(ref method, _, ref args)(并确保 args.len() == 1method.node.as_str() == "len") 并且刚刚使用了 &*args[0],从现在开始我将其称为 expr

下一步,获取 x 的类型:这可以使用 rustc::middle::ty::expr_ty(cx.tcx, expr) 轻松完成。请注意,这是 rustc::middle::ty::Ty(而不是 syntax::ast::Ty,这导致了一些混淆)。

为了查找方法,ctxt.impl_itemsctxt.trait_item_def_ids 看起来很有希望,所以我用 rustc::middle::ty::ty::ty_to_def_id(ty) 得到了我的类型的 DefId 并尝试获取 ID .但是,这种方法有一些问题:

为了

let x = [1, 2];
x.len() == 2 // <- lookee here

我根本没有DefId。不过没关系,因为在那种情况下我们有一个 ty_vec,并且已知 std::vec::Vec 同时具有 len()is_empty()

好消息是 ctxt.trait_item_def_ids 具有 适合具有 is_empty 方法的特征的条目。 las,对于以下示例:

struct One;
impl One { fn is_empty(self: &Self) -> bool { false } }

我没有得到任何 impl 项目的 TraitOrItemId,这有点不幸。有人知道 rustc 可以帮我找到我的 impl 项目吗?

我明白了!问题是我试图获取 type 的 DefId,而不是 impl。通过 cx.tcx.inherent_impls.get(id) 给了我一个 DefIds 的内在暗示,然后我可以通过我已经实现的 impl_items 查找进行查询。

rust-clippy/src/len_zero.rs 中查找示例实现。编辑:请注意,实现是 O(N),其中 N 是该类型方法的数量(直接 impl 或by traits) – 也许 rustc 有一天会允许更快的查找...