On Tue, Jan 27, 2026, at 8:13 PM, Jonas Smedegaard wrote: > Quoting Fabian Grünbichler (2026-01-27 19:38:32) >> On Mon, Jan 26, 2026, at 9:07 PM, Jonas Smedegaard wrote: >> > Quoting Fabian Grünbichler (2026-01-26 19:42:12) >> >> On Mon, Jan 26, 2026, at 8:17 AM, Jonas Smedegaard wrote: >> >> > 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. > [...] >> 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-~~) > > As I understand it, "in the context of Debian Rust (team) packages" and > "can only be encoded as..." is key to ensuring no dependency "leakage". > > Others in Debian may find it interesting that a) Rust crates in Debian > provide a wealth of virtual packages, but b) taking inspiration from > cross-boundary declarations in such packages is risky: The pattern of > using virtual dependencies to cover cross-boundary is not intended to > cover any crate within a version range available in Debian, but only > **same-source** crates. In other words, major-versioned virtual > dependencies are unsafe to use for cross-boundary declarations, and > consequently that it is unsafe to rely on version-branched source > packages for cross-boundary dependencies.
Yes, the whole scheme only works because of the restrictions placed on the source packages providing those packages. A version range is not generally safe to encode using separate encodings of the lower and upper bounds, for all the reasons you mentioned earlier in this thread! Fabian

