-
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
False positive for inherent_to_string_shadow_display? #4396
Comments
You should just write impl fmt::Display for Ulid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
let mut string = String::with_capacity(26);
crockford::append_crockford_u64_tuple(self.value, &mut string);
write!(f, "{}", string)
}
} and remove the This will give you a Or does something prevent an implementation like this? |
I thought the way I'm doing it would be slightly more efficient, i.e. only one |
I doubt that. One great thing about Rust are Zero Cost Abstractions; the way it's implemented by the compiler should be at least as fast as your implementation.
I expect that the default implementation of Just tested it with godbolt: https://rust.godbolt.org/z/0Ynb4g The version with just the So yeah: Just trust the Rust compiler, he/she/it just wants what's best for you ❤️ 😄 |
@flip1995 There are some benchmarks in my repository. With my current manual implementation: generate_ulid_string time: [197.75 ns 199.60 ns 201.66 ns]
Found 8 outliers among 100 measurements (8.00%)
8 (8.00%) high mild Using the default implementation of generate_ulid_string time: [338.23 ns 340.84 ns 343.38 ns]
change: [+68.709% +70.540% +72.419%] (p = 0.00 < 0.05)
Performance has regressed.
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high mild |
Do you run these benchmarks in |
I simply executed Reverting the changes causes the performance to increase accordingly: generate_ulid_string time: [193.82 ns 194.85 ns 195.95 ns]
change: [-42.510% -41.993% -41.431%] (p = 0.00 < 0.05)
Performance has improved.
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high mild Taking a look at the inherent_to_string_shadow_display description, it seems that the intent of this rule is mostly about preventing different output from But in my example this problematic behavior is impossible because I have no idea how prevalent this other-way-around pattern is but I think that it should not trigger the rule if it is detected. The description of the rule also says "The less versatile inherent method will then shadow the implementation introduced by @flip1995 I think I can't reopen the issue. I could only create a new one referencing this one. |
Fair enough. Could you test what happens if you implement the
Oh I thought the author can always do this. In that case I do it for you. |
Trying to implement ToString directly leads to this error: error[E0119]: conflicting implementations of trait `std::string::ToString` for type `Ulid`:
--> src/lib.rs:555:1
|
555 | impl ToString for Ulid {
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `alloc`:
- impl<T> std::string::ToString for T
where T: std::fmt::Display, T: ?Sized; The documentation of |
Hm, I kind of expected something like this. So yeah, a check, if the I'll add the |
The problem is the shadowing. Calling I can think of two possible solutions.
You could also do both. |
Here are some more benchmarks: generate_ulid_string time: [208.62 ns 209.90 ns 211.33 ns]
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high severe
generate_ulid_string_formatter
time: [364.51 ns 369.58 ns 375.72 ns]
Found 13 outliers among 100 measurements (13.00%)
7 (7.00%) high mild
6 (6.00%) high severe
generate_ulid_string_tostring_trait
time: [367.32 ns 370.45 ns 373.84 ns]
Found 11 outliers among 100 measurements (11.00%)
1 (1.00%) high mild
10 (10.00%) high severe
As you can see, the performance differences are minuscule but exist. Given that a user would always get optimal I don't think that sacrificing usability/expected behavior by not implementing Because of that, I'll keep the But I'm also still convinced that not warning if the shadowing |
Now I see, why your If we allow a shadowing |
Yep, that's exactly the point I tried to make. :) My current implementation looks like this, though: impl fmt::Display for Ulid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.write_str(&self.to_string())
}
} It may actually be worthwhile to write another clippy rule detecting a pattern like I wanted to do that from the start but forgot to revisit the code once it worked... |
The documentation states that these two functions are equivalent. But if the |
I wonder if this could/should be fixed at the |
I think this lint is wrong. There is a good reason for shadowing It's possible to deal with this issue to some extent by not implementing I understand that incompatible implementations are a problem, however I don't think it's easy to determine whether implementations are incompatible. I think this lint shouldn't be enabled by default until specialization gets introduced on stable. |
I think I found a false positive or at least questionable case of
inherent_to_string_shadow_display
rule triggering.The place this rule is (or rather "was", since I disabled it) triggered:
https://github.com/huxi/rusty_ulid/blob/72ac82736311981d12c339b78756049f48406179/src/lib.rs#L557
The place where the method in question is used to actually implement
Display
:https://github.com/huxi/rusty_ulid/blob/72ac82736311981d12c339b78756049f48406179/src/lib.rs#L571
This boils down to a situation where a type has an efficient implementation of
fn to_string(&self) -> String
that is used to implementfn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error>
offmt::Display
.I think this case (method is used to implement trait) shouldn't trigger the rule.
The text was updated successfully, but these errors were encountered: