-
Couldn't load subscription status.
- Fork 1.8k
Use MIR body to identify more "default equivalent" calls for derivable_impls
#13988
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
Use MIR body to identify more "default equivalent" calls for derivable_impls
#13988
Conversation
derivable_impls
01edde1 to
6fa2199
Compare
|
Very interesting. In particular, your change also affects |
6fa2199 to
e932dd3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the long delay. Just one question, otherwise this looks good.
| if let rustc_ty::InstanceKind::Item(def) = instance.def | ||
| && !cx.tcx.is_mir_available(def) | ||
| { | ||
| // Avoid ICE while running rustdoc for not providing `optimized_mir` query. | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know there are cases where the MIR isn't available, but what does rustdoc have to do with clippy here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that this might have been a comment from when I implemented this in rustc itself, which triggered an ICE when invoked by rustdoc. The check I think is still good to keep, but maybe not the comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use impossible_predicates in other places to cover when optimized_mir fails, but is_mir_available seems like it's the better thing to use.
When looking for `Default` impls that could be derived, we look at the
body of their `fn default()` and if it is an fn call or literal we check
if they are equivalent to what `#[derive(Default)]` would have used.
Now, when checking those fn calls in the `fn default()` body, we also
compare against the corresponding type's `Default::default` body to see
if our call is equivalent to that one.
For example, given
```rust
struct S;
impl S {
fn new() -> S { S }
}
impl Default for S {
fn default() -> S { S::new() }
}
```
`<S as Default>::default()` and `S::new()` are considered equivalent.
Given that, if the user also writes
```rust
struct R {
s: S,
}
impl Default for R {
fn default() -> R {
R { s: S::new() }
}
}
```
the `derivable_impls` lint will now trigger.
e932dd3 to
39d73d5
Compare
When looking for
Defaultimpls that could be derived, we look at the body of theirfn default()and if it is an fn call or literal we check if they are equivalent to what#[derive(Default)]would have used.Now, when checking those fn calls in the
fn default()body, we also compare against the corresponding type'sDefault::defaultbody to see if our call is equivalent to that one.For example, given
<S as Default>::default()andS::new()are considered equivalent. Given that, if the user also writesthe
derivable_implslint will now trigger.changelog: [
derivable_impls]: detect when aDefaultimpl is using the same fn call that that type'sDefault::defaultcallschangelog: [
mem_replace_with_default]: detect whenstd::mem::replaceis being called with the same fn that that type'sDefault::defaultcalls, without the need of a manually maintained list