Skip to content

Commit 4140615

Browse files
authored
Merge pull request #2235 from Susurrus/libc_derives
RFC: Implement Debug, Eq, PartialEq, and Hash for libc structs
2 parents d5d551c + 511630e commit 4140615

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

text/2235-libc-struct-traits.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
- Feature Name: `libc_struct_traits`
2+
- Start Date: 2017-12-05
3+
- RFC PR: [rust-lang/rfcs#2235](https://github.com/rust-lang/rfcs/pull/2235)
4+
- Rust Issue: [rust-lang/rust#57715](https://github.com/rust-lang/rust/issues/57715)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Expand the traits implemented by structs `libc` crate to include `Debug`, `Eq`, `Hash`, and `PartialEq`.
10+
11+
# Motivation
12+
[motivation]: #motivation
13+
14+
This will allow downstream crates to easily support similar operations with any types they
15+
provide that contain `libc` structs. Additionally [The Rust API Guidelines](https://rust-lang-nursery.github.io/api-guidelines/checklist.html) specify that it is
16+
considered useful to expose as many traits as possible from the standard library. In order to facilitate the
17+
following of these guidelines, official Rust libraries should lead by example.
18+
19+
For many of these traits, it is trivial for downstream crates to implement them for these types by using
20+
newtype wrappers. As a specific example, the `nix` crate offers the `TimeSpec` wrapper type around the `timespec` struct. This
21+
wrapper could easily implement `Eq` through comparing both fields in the struct.
22+
23+
Unfortunately there are a great many structs that are large and vary widely between platforms. Some of these in use by `nix`
24+
are `dqblk`, `utsname`, and `statvfs`. These structs have fields and field types that vary across platforms. As `nix` aims to
25+
support as many platforms as `libc` does, this variation makes implementing these traits manually on wrapper types time consuming and
26+
error prone.
27+
28+
# Guide-level explanation
29+
[guide-level-explanation]: #guide-level-explanation
30+
31+
Add an `extra_traits` feature to the `libc` library that enables `Debug`, `Eq`, `Hash`, and `PartialEq` implementations for all structs.
32+
33+
# Reference-level explanation
34+
[reference-level-explanation]: #reference-level-explanation
35+
36+
The `Debug`, `Eq`/`PartialEq`, and `Hash` traits will be added as automatic derives within the `s!` macro in `src/macros.rs` if the corresponding feature
37+
flag is enabled. This won't work for some types because auto-derive doesn't work for arrays larger than 32 elements, so for these they'll be implemented manually. For `libc`
38+
as of `bbda50d20937e570df5ec857eea0e2a098e76b2d` on `x86_64-unknown-linux-gnu` these many structs will need manual implementations:
39+
40+
* `Debug` - 17
41+
* `Eq`/`PartialEq` - 46
42+
* `Hash` - 17
43+
44+
# Drawbacks
45+
[drawbacks]: #drawbacks
46+
47+
While most structs will be able to derive these implementations automatically, some will not (for example arrays larger than 32 elements). This will make it harder to add
48+
some structs to `libc`.
49+
50+
This extra trait will increase the testing requirements for `libc`.
51+
52+
# Rationale and alternatives
53+
[alternatives]: #alternatives
54+
55+
Adding these trait implementations behind a singular feature flag has the best compination of utility and ergonomics out of the possible alternatives listed below:
56+
57+
## Always enabled with no feature flags
58+
59+
This was regarded as unsuitable because it increases compilation times by 100-200%. Compilation times of `libc` was tested at commit `bbda50d20937e570df5ec857eea0e2a098e76b2d`
60+
with modifications to add derives for the traits discussed here under the `extra_traits` feature (with no other features). Some types failed to have these traits
61+
derived because of specific fields, so these were removed from the struct declaration. The table below shows the compilation times:
62+
63+
| Build arguments | Time |
64+
|----------------------------------------------------------------------------------------------|-------|
65+
| `cargo clean && cargo build --no-default-features` | 0.84s |
66+
| `cargo clean && cargo build --no-default-features --features extra_traits` | 2.17s |
67+
| `cargo clean && cargo build --no-default-features --release` | 0.64s |
68+
| `cargo clean && cargo build --no-default-features --release --features extra_traits` | 1.80s |
69+
| `cargo clean && cargo build --no-default-features --features use_std` | 1.14s |
70+
| `cargo clean && cargo build --no-default-features --features use_std,extra_traits` | 2.34s |
71+
| `cargo clean && cargo build --no-default-features --release --features use_std` | 0.66s |
72+
| `cargo clean && cargo build --no-default-features --release --features use_std,extra_traits` | 1.94s |
73+
74+
## Default-on feature
75+
76+
For crates that are more than one level above `libc` in the dependency chain it will be impossible for them to opt out. This could also happen with a default-off
77+
feature flag, but it's more likely the library authors will expose it as a flag as well.
78+
79+
## Multiple feature flags
80+
81+
Instead of having a single `extra_traits` feature, have it and feature flags for each trait individually like:
82+
83+
* `trait_debug` - Enables `Debug` for all structs
84+
* `trait_eg` - Enables `Eq` and `PartialEq` for all structs
85+
* `trait_hash` - Enables `Hash` for all structs
86+
* `extra_traits` - Enables all of the above through dependent features
87+
88+
This change should reduce compilation times when not all traits are desired. The downsides are that it complicates CI. It can be added in a backwards-compatible
89+
manner later should compilation times or consumer demand changes.
90+
91+
# Unresolved questions
92+
[unresolved]: #unresolved-questions

0 commit comments

Comments
 (0)