Hi Fabian, Quoting Fabian Grünbichler (2026-01-26 19:42:12) > CC-ing the Rust team discussion list > > On Mon, Jan 26, 2026, at 8:17 AM, Jonas Smedegaard wrote: > > Quoting Daniel Kahn Gillmor (2026-01-26 05:23:44) > >> Hi Jonas-- > >> > >> On Sun 2026-01-25 09:42:21 +0100, Jonas Smedegaard wrote: > >> > Thanks, but I think you are mistaken: In my experience, "<= 0.6" is > >> > equivalent to "<= 0.6.*" (not "<= 0.6.0"). > >> > >> Interesting, thanks for pushing back and making me reconsider this! > >> > >> i read the cargo specification for version requirements: > >> > >> > >> https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#version-requirement-syntax > >> > >> and it appears to be ambiguous about what an explicit comparator means > >> if the patch level is unspecified. > >> > >> > If I was mistaken, then I believe that e.g. oxigraph, which for some > >> > time has carried this line: > >> > > >> > quick-xml = ">= 0.37, <= 0.38 > >> > > >> > would FTBFS with librust-quick-xml-dev 0.38.4-1, and that works fine. > >> > >> If you have evidence that this works, that's good enough for me. > > > > Speaking of versioning of Rust crates, I thought of another related one > > just after hitting send yesterday: > > > > I have noticed a common pattern in the Rust team of including features > > when declaring version constraints, like this: > > > > librust-rusqlite+blob-dev (<< 0.38-~~) > > librust-rusqlite+blob-dev (>= 0.29-~~) > > > > (the example is from librust-sequoia-cert-store-dev that you might be > > directly familiar with). > > > > That pattern has two weaknesses: It is escapable and it is vague. > > > > It is escapable because it permits a too old *and* and too new version, > > e.g. in above example it does not rule out Debian packages versioned > > 0.28-1 and 0.39-1. > > it does. there is only one source package providing the unversioned > package librust-sqlite-dev (and the corresponding +feature variants), > rust-sqlite. if that package's version is within the version range, it can > satisfy both dependencies. if it is not, it can only satisfy one of them. two > versions of the same package are not co-installable.
That sounds like a Rust team practice, not a dpkg issue in Debian in general, which I was reflecting on above. No problem, I don't mind us switching to talking about the Rust team conventions, more narrowly. Ok, so Rust-team crate packages provide unversioned virtual packages only for unversioned source packages. Which means that the example above would ignore a newly introduced version-branch e.g. of rust-rusqlite-0.29 (same way as e.g. rust-darling-0.14 is done). If we wanted the cross-boundary dependency to take alternative packages into account, then dependencies would need to be adjusted to instead be zero-bound (looking at how rust-darling-0.14 and rust-darling both provide zero-versioned virtual packages), but that would introduce the issue of "leaky" dependencies. > if the version range does not cross semver boundaries, then the range is not > encoded using the unversioned package, but using the "semver-dominant" > component. e.g., a range like >= 2.1, < 2.4 would be encoded as > librust-foobar-2-dev (>= 2.1-~~), librust-foobar-2-dev (<< 2.4), which might > be > satisfied by librust-foobar-2-dev built from rust-foobar-2 or by > librust-foobar-dev built from rust-foobar. in practice this is not an issue > either, since introducing rust-foobar-2 coincides with upgrading rust-foobar > to > 3 (or higher). Makes sense (except for the "either", see above). > this encoding was carefully chosen because the old way we encoded such version > ranges (using alternate build-/dependencies) was broken (indeterministic) and > not policy compliant. the rust team book still contains the old encoding, I > will update this ASAP. I am not familiar with that older style. Thanks for checking and fixing documentation related to that. > > I would, for dependencies that cross semver stability boundaries, stop > > care about feature and stop care about the least concerning of either > > upper or lower bounds, e.g. for the above example (where we factually > > know that lower bounds is not an issue) I would instead declare this: > > > > librust-rusqlite-dev (<< 0.38-~~) Oh, I forgot to refine after copying: I see no need for the trailing "lesser-than-any-debian-revision" rune, but would simplify to this: librust-rusqlite-dev (<< 0.38) > we (as in, the Rust team) have discussed dropping both the full 3-component > version provides/depends (those are rarely needed in the first place[0,1]) > and/or reducing the amount of feature related provides/depends. it requires > careful thought to not miss edge cases. Thanks for considering. Yes, I am aware it is not simple to do the change. > > That is half the amount of nodes to compute in the dependency graph, > > and a reduction in potentials for complexity due to reduces possibility > > types of edges. And likely more important, it reduces the size of the > > packaging metadata. > > in general, reducing dependencies like that should work. of course, it doesn't > account for valid package split along feature lines, or the fact that the > unversioned package is only provided by the non-semver-suffixed source > package. > so if you reduce dependencies in that fashion, it will likely work - but you > might be asked to adapt if a package is split or semver-suffixed later on, as > your package might FTFBS without those adaptations. Makes sense. Thanks for your comments, - Jonas -- * Jonas Smedegaard - idealist & Internet-arkitekt * Tlf.: +45 40843136 Website: http://dr.jones.dk/ * Sponsorship: https://ko-fi.com/drjones [x] quote me freely [ ] ask before reusing [ ] keep private

