-
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
WIP: use_self checking lifetimes & generics #1997
WIP: use_self checking lifetimes & generics #1997
Conversation
These are gonna fail right now as I haven't actually implemented the fix yet.
I'm a little stuck here--I started out by comparing the lifetimes and generics that are present in the item's path, but then I realized that they won't be in the path if they're inferred. It seems like this information should probably be cached somewhere in |
What's the exact issue with the current implementation? Can you give an example where the lint fails? |
Yup--I'm trying to fix the false positive given in #1993 caused by not verifying that the type parameters match self before warning (playground link), and also the fact that it currently bails if the type has any lifetimes. |
Right, but you fixed some of these. I meant what failures are left after your changes? |
Ah my bad misunderstood/didn't recognize your username. I've only changed the lifetimes side of things, I realized the inference issue when I started trying to work out how to do generics but it also affects lifetimes: mod lifetimes {
struct Foo<'a>{foo_str: &'a str}
impl<'a> Foo<'a> {
// Correctly gives no warnings here
fn differnt_lifetimes() -> Foo<'static> {
Foo { foo_str: "foo"}
}
// Correctly warns on both the declared return type and the struct literal
fn explicit_lifetimes(&self) -> Foo<'a> {
Foo::<'a> { foo_str: self.foo_str }
}
// Correctly warns on the declared return type, but not the literal even though it
// should because I don't know how to get the inferred lifetimes
fn inferred_lifetimes(&self) -> Foo<'a> {
Foo { foo_str: self.foo_str }
}
}
} So basically to fix this I just need to figure out how to get the list of lifetimes and generics after type inference, but I'm not sure how to do that. |
Hmm... I think that's pretty hard to do in a general way. But we can special case struct constructors, by implementing |
Makes sense, I'll try that out. |
Sorry for the delay on this, been busy with other things--how do I actually obtain the type of the I'm testing against the same code as before, for the struct literal in the Expr_::ExprStruct(Resolved(None, path(Foo<'a>)), [...], None) But when I visit struct literal in the Expr_::ExprStruct(Resolved(None, path(Foo)), [...], None) |
That's expected. You can use |
Ah okay, checked that out it does in fact give us the inferred parameters! Here's what I have so far. It will print out the type for every struct literal that doesn't have fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let Expr_::ExprStruct(ref path, _, _) = expr.node {
let segment = match *path {
QPath::Resolved(_, ref path) => path.segments
.last()
.expect(SEGMENTS_MSG),
QPath::TypeRelative(_, ref segment) => segment,
};
if segment.name != SelfType.name() {
let ty = cx.tables.expr_ty(expr);
println!("{:?}: {:?}", path, ty);
}
}
} The next step is to determine if the type I've obtained here is actually equivalent to Previously was this was accomplished by triggering a separate visitor when the late lint pass entered an impl block, and saving the self type as a field on that visitor. (Side note: I think this isn't exactly correct--you can nest structs and impls inside functions, so really the visitor needs to implement the I'm not sure that this strategy works anymore anyway though. It seems that I actually need the instance of Given this I'm not sure how to obtain the type of |
You can implement visit_expr on the visitor instead of check_expr on the lintcontext. I'd ignore nested functions for now. The none issue can be worked around by implementing visit_body. Look for other visit_body impla in clippy to see what you need to change in your visitor to make it work. |
ping @MasonRemaley |
Whoops, I've been busy and this fell off my radar--I'll mess with this some more this weekend and see if I can get something working. |
Okay, haven't pushed yet as I have to clean up a few things but I've made some progress. I reimplemented the snippet from above as
Now I need to figure out how to compare these two things so I can print the lint message if they match up, or if that doesn't make sense I need to figure out how to get Maybe a more general question, but are there docs/blog posts/such I could read anywhere that explain what some of these different structures in rustc are? Right now my strategy for figuring out if I can get one thing given another is to click through as many levels of the generated docs as I can, |
So the The
I don't think so. You need context for that conversion (e.g. the entirety of the I don't fully understand the situation, can you push the code so I can have a look?
Unfortunately the most you get are the module docs in which the types, that you want to know stuff about, reside. |
…o use-self-lifetimes-generics I accepted --theirs on all the files I touched because I started over on these changes now that I have a better idea of how things worked on a branch off of the current master anyway. So basically gonna do this merge and have it revert everything, then reapply those commits to this branch. Will probably come back to the history and grab the test cases from it later.
Ah thanks for the explanation about I just pushed my work in progress. If you run it as is the (Uh also sorry for the weird commit history..I just reverted the changes from earlier before doing this because it was easier than dealing with the merge conflicts while I work out this detail, plan was to put them back in before committing because I didn't realize I was gonna get stuck here.) |
@MasonRemaley Any news on this? |
Ping from triage @MasonRemaley: It looks like this PR hasn't received any updates in a while, so I'm closing it per our new guidelines. Thank you for your contributions and please feel free to re-open in the future. |
I think this would have solved #3859, i'm hitting it a lot, forcing me to disable the |
Work in progress. Fixing a false positive in the
use_self
lint caused by type parameters not being checked, and also allowing the lint to check types with lifetimes.fixes #1993