-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace match_def_path
and friends with is_item
#7647
Conversation
r? @giraffate (rust-highfive has picked a reviewer for you, use r? to override) |
3fc960d
to
d4cc838
Compare
This is a really big refactor and bitrotty. So I don't want to put all of the burden of reviewing this on @giraffate. So first @rust-lang/clippy what are your thoughts on this? And then, if you have time, please pick a part of the PR and help reviewing it. |
I'll split this up into two PRs. One with just the switchover to |
* `is_qpath_def_path` * `is_expr_path_def_path` * `is_expr_diagnostic_item` * `match_any_def_paths` * `match_any_diagnostic_items` * `match_def_path` * `is_type_diagnostic_item` * `is_type_lang_item` * `match_type`
2f5b2ed
to
6b64159
Compare
* Check for `is_item` instead * Check consts and statics from external crates * Check for lang items * Check for inherent functions which have the same name as a field
Pulled out the refactorings. Only thing left is the switch to |
We definitely need to simplify our approach to item lookups. I've also toyed with creating utils like this. I'm a little unsure that this is the right direction though. Lately I've been thinking that we should simply move towards diagnostic items. In particular, I would really like to have a diagnostic item "reverse lookup" added to rustc: match cx.tcx.get_diagnostic_name(def_id)? {
sym::vec_type => .. If we do go with this approach, I would prefer that |
That would definitely work better when checking for multiple diagnostic items. There's still a need to simplify getting the if_chain! {
if let ExprKind::Call(fn_expr, args) = e.kind;
if let ExprKind::Path(ref p) = fn_expr.kind;
lf let Some(def_id) = cx.qpath_res(p, fn_expr.hir_id).opt_def_id();
if cx.tcx.is_diagnostic_item(_, def_id);
then {
// do stuff with args
}
} Lang items can also use a simplified check as well.
The name could be better (it's just wrong). There are quite a few cases where knowing which one matched is necessary though. Edit: |
☔ The latest upstream changes (presumably #7663) made this pull request unmergeable. Please resolve the merge conflicts. |
Here is a util idea I have fn is_path_to_item(cx, impl MaybePath, impl ItemRef);
This could be complimented with
You could split into multiple invocations of |
That still leaves My issue with splitting the functions is justifying why they're two separate functions. As in from the perspective of the person calling the function, what problem are you solving by having two functions as opposed to one. I can kind of do that for expressions and patterns just by being clear that they only work on paths rather than, for example, method calls (it would make the function useless as it can't disambiguate between a path to a method vs. a call to a method, but I could see someone possibly using it to check a method call node without really thinking). At this point the cost is the same either way. Either you remember that paths use a different function (for If we do go with splitting the functions, please don't have different argument orders. Either one works, but differing orders are just pointless friction. |
True. I think I'm torn on
Agreed. I would apply the "yoda condition" rule which would put |
There is a line here. Checking for a ufcs call to if let ExprKind::Call(fn, _) = e.kind {
is_item(cx, fn, &OPTION_UNWRAP)
} else {
false
} If we allow method calls this could match either I'd be in favour of a good abstraction around method and function calls. There is |
You make a compelling case for excluding I think |
I can't really think of a single name that gets across subtleties like that. Just some other things to consider:
|
Discussed this in the Clippy meeting today. We agreed on the following.
Even if we don't adopt |
I'll pull out the fixes for the internal lint into a different PR since those will be needed anyways. Should I open an issue summarizing things and possible steps forward?
I don't think this is possible for external crates (currently we use
Is that replacing |
Go for it! For reference we have #5393 for migrating to diagnostic items and I just opened #7784 for
True, there will be some exceptions. We can just implement those cases more "naively" instead of having utils. And/or we can separate path utils into a separate module to declutter.
In addition - for cases where multiple queries can be replaced with one query. |
…ogiq Fix and improve `match_type_on_diagnostic_item` This extracts the fix for the lint out of #7647. There's still a couple of other functions to check, but at least this will get lint working again. The two added util functions (`is_diagnostic_item` and `is_lang_item`) are needed to handle `DefId` for unit and tuple struct/variant constructors. The `rustc_diagnostic_item` and `lang` attributes are attached to the struct/variant `DefId`, but most of the time they are used through their constructors which have a different `DefId`. The two utility functions will check if the `DefId` is for a constructor and switch to the associated struct/variant `DefId`. There does seem to be a bug on rustc's side where constructor `DefId`s from external crates seem to be returning `DefKind::Variant` instead of `DefKind::Ctor()`. There's a workaround put in right. changelog: None
This is a pair of new util functions
is_item
andis_any_item
. These will take anything that can be turned into aDefId
(currentlyDefId
,Res
,(QPath,HirId)
,Expr
,Pat
, andTy
) and anything that can refer to a specific item (currently a def path, diagnostic item and lang item). This replaces the handful of functions we currently have to do certain combinations of these.The following functions are then removed:
is_qpath_def_path
is_expr_path_def_path
is_expr_diagnostic_item
match_any_def_paths
match_any_diagnostic_items
match_def_path
is_type_diagnostic_item
is_type_lang_item
match_type
The internal lint
match_type_on_diagnostic_item
has been changed to work on the new function. It will also check consts and statics from external crates and check for lang items.changelog: none