Skip to content

Commit c5a82cf

Browse files
author
Bryant Mairs
committed
Expand traits implemented by structs within libc
1 parent 90a6f4e commit c5a82cf

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

text/0000-libc-struct-traits.md

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
- Feature Name: (libc_struct_traits)
2+
- Start Date: (2017-12-05)
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
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+
The feature flag `derive_all` is added to the `libc` library that when enabled adds `Debug`, `Eq`, `Hash`, and `PartialEq` traits for all structs. It will default to off.
32+
33+
# Reference-level explanation
34+
[reference-level-explanation]: #reference-level-explanation
35+
36+
The `Debug`, `Eq`, `Hash`, and `PartialEq` traits will be added as automatic derives within the `s!` macro in `src/macros.rs` if the `derive_all` 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` and `PartialEq` - 46
42+
* `Hash` - 17
43+
44+
# Drawbacks
45+
[drawbacks]: #drawbacks
46+
47+
The addition of this behind a feature flag does not have a significant effect on build times, but the burden of adding these implementations for new types that
48+
require manual implementations will be high, possibly hindering new contributors.
49+
50+
# Rationale and alternatives
51+
[alternatives]: #alternatives
52+
53+
Adding these trait implementations behind a singular feature flag has the best compination of utility and ergonomics out of the possible alternatives listed below:
54+
55+
## Always enabled
56+
57+
This was regarded as unsuitable because it doubles to triples compilation time. Compilation times of `libc` was tested at commit `bbda50d20937e570df5ec857eea0e2a098e76b2d`
58+
with modifications to add derives for the traits discussed here. Some types failed to have these traits derived because of specific fields, so these were removed from the
59+
struct declaration. The table below shows the results:
60+
61+
| Build arguments | Time |
62+
|--------------------------------------------------------------------------------------------|-------|
63+
| `cargo clean && cargo build --no-default-features` | 0.84s |
64+
| `cargo clean && cargo build --no-default-features --features derive_all` | 2.17s |
65+
| `cargo clean && cargo build --no-default-features --release` | 0.64s |
66+
| `cargo clean && cargo build --no-default-features --release --features derive_all` | 1.80s |
67+
| `cargo clean && cargo build --no-default-features --features use_std` | 1.14s |
68+
| `cargo clean && cargo build --no-default-features --features use_std,derive_all` | 2.34s |
69+
| `cargo clean && cargo build --no-default-features --release --features use_std` | 0.66s |
70+
| `cargo clean && cargo build --no-default-features --release --features use_std,derive_all` | 1.94s |
71+
72+
## Default-on feature flag
73+
74+
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
75+
feature flag, but it's more likely the library authors will expose it as a flag as well.
76+
77+
## Independent feature flags
78+
79+
It wasn't tested how much compilation times increased per-trait, but further mitigation of slow compilation times could done by exposing all traits mentioned here
80+
behind individual feature flags. By doing this it becomes harder for downstream crates to pass-through these feature flags, so it's likely not a worthwhile tradeoff.
81+
82+
# Unresolved questions
83+
[unresolved]: #unresolved-questions
84+
85+
Is `derive_all` a suitable name for this feature flag?

0 commit comments

Comments
 (0)