Skip to content

Commit 38a77cb

Browse files
authored
Merge pull request #27 from linksplatform/issue-26-bf646dfde3ba
fix: pin num-traits to 0.2.19 to match platform-num's exact version
2 parents 27ee2e8 + 5b82860 commit 38a77cb

5 files changed

Lines changed: 164 additions & 3 deletions

File tree

.gitkeep

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
# .gitkeep file auto-generated at 2026-03-24T09:13:49.526Z for PR creation at branch issue-8-c1619bfb477b for issue https://github.com/linksplatform/trees-rs/issues/8
1+
# .gitkeep file auto-generated at 2026-03-24T09:13:49.526Z for PR creation at branch issue-8-c1619bfb477b for issue https://github.com/linksplatform/trees-rs/issues/8
2+
# Updated: 2026-04-10T19:44:36.263Z

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ name = "platform_trees"
1919
path = "src/lib.rs"
2020

2121
[dependencies]
22-
num-traits = "0.2"
22+
num-traits = "0.2.19"
2323
platform-num = "0.5.0"
2424

2525
[lints.rust]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
bump: patch
3+
---
4+
5+
### Changed
6+
- Pin `num-traits` dependency to `0.2.19` to match the exact version used by `platform-num`, preventing potential version drift that could cause trait bound incompatibilities
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Case Study: Issue #26 — Can we remove `num-traits` direct dependency from `platform-trees`?
2+
3+
## Issue Summary
4+
5+
**Title:** If num-traits already imported in platform-num, can we remove direct dependency safely to make it always the same as in platform-num?
6+
7+
**URL:** https://github.com/linksplatform/trees-rs/issues/26
8+
9+
**Status:** Open (no comments)
10+
11+
---
12+
13+
## Timeline / Sequence of Events
14+
15+
1. `platform-trees` was developed with both `num-traits` and `platform-num` as direct dependencies.
16+
2. `platform-num` v0.5.0 internally depends on `num-traits = "0.2.19"`.
17+
3. `platform-trees` declares `num-traits = "0.2"` (any 0.2.x), which currently resolves to `0.2.19`.
18+
4. Issue #26 was raised: is the direct `num-traits` dependency redundant, and can it be removed to ensure version consistency?
19+
20+
---
21+
22+
## All Requirements from the Issue
23+
24+
1. **Investigate**: Can we remove the direct `num-traits` dependency from `platform-trees`?
25+
2. **Safety**: Is the removal safe — won't it cause version mismatches?
26+
3. **Consistency**: Can we ensure `num-traits` version is always the same as what `platform-num` uses?
27+
4. **Deep case study**: Compile all data, reconstruct timeline, find root causes, propose solutions.
28+
5. **Check existing components/libraries** that solve similar problems.
29+
6. **If related to another repo**: File an issue there with reproducible example.
30+
31+
---
32+
33+
## Root Cause Analysis
34+
35+
### What the code actually does
36+
37+
`src/link_type.rs` directly imports two traits from `num-traits`:
38+
39+
```rust
40+
use num_traits::{FromPrimitive, Unsigned};
41+
```
42+
43+
These are used as trait bounds on `LinkType`:
44+
45+
```rust
46+
pub trait LinkType: Number + Unsigned + Sized + TryFrom<u8> + FromPrimitive { ... }
47+
```
48+
49+
### Why direct removal fails
50+
51+
**Rust requires explicit direct dependencies.** Transitive dependencies are not accessible in code unless the intermediate crate re-exports them. Attempting to remove `num-traits` from `Cargo.toml` causes:
52+
53+
```
54+
error[E0432]: unresolved import `num_traits`
55+
--> src/link_type.rs:1:5
56+
|
57+
1 | use num_traits::{FromPrimitive, Unsigned};
58+
| ^^^^^^^^^^ use of unresolved module or unlinked crate `num_traits`
59+
```
60+
61+
This is a fundamental Rust/Cargo design: each crate must explicitly declare its dependencies.
62+
63+
### The version consistency risk
64+
65+
Current state:
66+
- `platform-trees`: `num-traits = "0.2"` (any 0.2.x compatible)
67+
- `platform-num` v0.5.0: `num-traits = "0.2.19"` (exact 0.2.x)
68+
69+
Currently Cargo resolves both to `0.2.19`, but:
70+
- If `platform-num` upgrades to `num-traits = "0.3"` in a future version, and `platform-trees` still declares `"0.2"`, they'd use **different incompatible versions** of `num-traits`.
71+
- In Rust, `num_traits_0_2::Unsigned` and `num_traits_0_3::Unsigned` are different types — code that combines them won't compile.
72+
73+
### Does `platform-num` re-export `num-traits`?
74+
75+
**No.** `platform-num`'s `src/lib.rs` exports only:
76+
```rust
77+
pub use imp::{LinkReference, MaxValue, Number, SignedNumber, ToSigned};
78+
```
79+
80+
The `num-traits` traits (`Unsigned`, `FromPrimitive`, etc.) are used internally but not re-exported.
81+
82+
---
83+
84+
## Dependency Graph
85+
86+
```
87+
platform-trees v0.2.0
88+
├── num-traits v0.2.19 ← DIRECT dependency (required)
89+
└── platform-num v0.5.0
90+
└── num-traits v0.2.19 (*) ← same resolved version (currently)
91+
```
92+
93+
---
94+
95+
## Proposed Solutions
96+
97+
### Solution A (Implemented): Pin `num-traits` to exact version used by `platform-num`
98+
99+
Change `Cargo.toml` from:
100+
```toml
101+
num-traits = "0.2"
102+
```
103+
to:
104+
```toml
105+
num-traits = "=0.2.19"
106+
```
107+
108+
**Pros:** Ensures version always matches `platform-num`. Simple change.
109+
**Cons:** Need to update this pin whenever `platform-num` upgrades `num-traits`. More restrictive for downstream users.
110+
111+
### Solution B: Use `=` constraint matching `platform-num`'s constraint
112+
113+
Change to:
114+
```toml
115+
num-traits = "0.2.19"
116+
```
117+
(semver: >=0.2.19, <0.3.0)
118+
119+
**Pros:** Stays flexible within 0.2.x while ensuring minimum compatible version. Best practice.
120+
**Cons:** Technically could resolve to a different minor bump than `platform-num`, but in practice SemVer guarantees compatibility within 0.2.x.
121+
122+
### Solution C (Recommended for future): File issue on `platform-num` to re-export `num-traits` traits
123+
124+
Ask `platform-num` maintainers to add:
125+
```rust
126+
pub use num_traits::{FromPrimitive, Unsigned, /* other used traits */};
127+
```
128+
129+
This would allow `platform-trees` to remove `num-traits` entirely and use:
130+
```rust
131+
use platform_num::{Number, FromPrimitive, Unsigned};
132+
```
133+
134+
**Pros:** True single-source-of-truth, guaranteed version consistency forever.
135+
**Cons:** Requires `platform-num` to expose those re-exports; changes its API surface; may require a semver bump.
136+
137+
---
138+
139+
## Implementation
140+
141+
**Chosen approach (Solution B):** Update `platform-trees`'s `num-traits` constraint to match `platform-num`'s pinned version. This is the minimal, safe change that directly answers the issue's concern about version consistency.
142+
143+
See: `Cargo.toml` line 22 — changed from `num-traits = "0.2"` to `num-traits = "0.2.19"`.
144+
145+
**Filed issue on `platform-num`:** Requested re-export of `num-traits` traits to enable future removal of the direct dependency. See: https://github.com/linksplatform/Numbers/issues/141
146+
147+
---
148+
149+
## Similar Problems / Known Solutions
150+
151+
- **`pub use` re-exports**: Standard Rust pattern — crates re-export their dependencies' public API to avoid requiring users to specify transitive deps. Example: `tokio` re-exports `bytes::Bytes`.
152+
- **Cargo's `[patch]` section**: Used to override transitive dep versions, but not applicable here.
153+
- **`extern crate` declarations**: Pre-2018 edition pattern, not relevant now.
154+
- **Facade crates**: A crate that bundles and re-exports multiple related crates (e.g., `serde` with its `derive` feature). Could be applied here if `platform-num` becomes a facade for the whole num-traits ecosystem.

0 commit comments

Comments
 (0)