[Pkg-rust-maintainers] Bug#1116210: Bug#1116210: rust-bzip2: please upgrade to v0.6
Fabian Grünbichler
debian at fabian.gruenbichler.email
Tue Jan 27 18:38:32 GMT 2026
On Mon, Jan 26, 2026, at 9:07 PM, Jonas Smedegaard wrote:
> 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).
Yes, my response was of course fully in the context of Debian Rust (team)
packages.
For the avoidance of doubt, I'll spell out the policy ;)
rust-foobar will build librust-foobar-dev which will provide:
- librust-foobar-X-dev
- librust-foobar-X.Y-dev
- librust-foobar-X.Y.Z-dev
as well as (for every feature, `foobaz` being an example here):
- librust-foobar+foobaz-dev
- librust-foobar-X+foobaz-dev
- librust-foobar-X.Y+foobaz-dev
- librust-foobar-X.Y.Z+foobaz-dev
For some packages there might exist a separate binary package
librust-foobar+something-dev, which again provides all those versioned variants
for +something, as well as an unversionend and all the versioned variants for
other features that are grouped together with `something`.
Semver-suffixed packages like rust-foobar-0.Y or rust-foobar-X (where X != 0)
will build the corresponding librust-foobar-0.Y-dev / librust-foobar-X.dev,
which will provide
- librust-foobar-X-dev (if not already the binary package name)
- librust-foobar-X.Y-dev (if not already the binary package name)
- librust-foobar-X.Y.Z-dev
as well as (for every feature, `foobaz` being an example here):
- librust-foobar-X+foobaz-dev
- librust-foobar-X.Y+foobaz-dev
- librust-foobar-X.Y.Z+foobaz-dev
The same "there might be other +something binary packages" applies here as
well.
So in the case of rusqlite, at the moment, since it is still at version 0.x, we
will have rust-sqlite (the latest packaged version) and possibly
rust-sqlite-0.Y for various values of Y.
A version range like rusqlite = ">= 0.29, < 0.39" would thus cross semver
boundaries (by virtue of being at 0.Y, where every bump of Y is semver
breaking) can only be encoded as
librust-rusqlite+default-dev (<< 0.38.0-~~), librust-rusqlite+default-dev (>= 0.29-~~)
which can never be satisfied by packages built from rust-sqlite-0.Y, but only
by those built by rust-sqlite itself. by virtue of only a single version of
that package being installable, that single version must either satisfy both
version constraints, or none or only one, in which case the
(build-)dependencies would not be satisfiable.
> 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.
The version range encoding is special for that reason - we only emit ranges as
dependencies that are satisfiable by:
- only the packages built by rust-foobar (if range crosses semver boundaries)
- the packages built by rust-foobar-X(.Y) and rust-foobar, while both are still
at the same semver version (during the transition itself, if the range
doesn't cross semver boundaries)
- the packages built by rust-foobar-X(.Y), if the range doesn't cross semver
boundaries and the transition is done and rust-foobar has moved on
>> 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).
I hope the more detailed explanation above makes sense :)
>> 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.
the older style was:
foobar = ">= X, < Z" => librust-foobar-X-dev | librust-foobar-Y-dev | .. | librust-foobar-Z-dev
possibly with version constraints at the X and Z packages. this runs afoul of
the "buildds only pick first option in alternate dependencies" principle.
>> > 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)
>
FWIW, I plan to drop those pesky -~~ in debcargo, they make no sense AFAICT:
https://salsa.debian.org/rust-team/debcargo/-/issues/53
https://salsa.debian.org/rust-team/debcargo/-/commit/bdecd4e11c368c5768998aa7c5c401396e827bb3
>> 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
More information about the Pkg-rust-maintainers
mailing list