Live data from Hacker News

Can a Rust binary use incompatible versions of the same library?

github.com

31–40 of 89 posts

Re: Can a Rust binary use incompatible versions of the same library?

#31
post #20

Earlier quoted context omitted.

I’m confused. If you rely on a feature introduced in X.y.z why would you specify X.y.0 to begin with (and not just X.y.z)? In practice, usual rust projects that have not put a ton of work into their dependencies encode X.y.z in Cargo.toml matching the current release at the time they developed the system. So you get at worst an unnecessarily higher version requirement but never a lower one. Moreover, rust semver woul…

It's easy to accidentally ship a minimum version requirement that is out of date when you also consistently use lock files pinned to newer versions. The code may silently depend on something introduced in a newer version pulled in by the lock file.

You can have a CI builder using direct-minimal-versions to check this.

Re: Can a Rust binary use incompatible versions of the same library?

#32
This isn’t a magic bullet. Using multiple versions of the same crate can still blow up your project.

For example, the compiler error in this example:

note: perhaps two different versions of crate `smithay_client_toolkit` are being used?

https://github.com/pop-os/launcher/issues/237

Re: Can a Rust binary use incompatible versions of the same library?

#33
post #24
post #16

Earlier quoted context omitted.

Go got this right: you want an incompatible version, you have to use a different import path. Then you can only pick one version (which is deterministically the lowest possible version) for a certain import path, not a hundred different versions. Also forces people to actually take backwards compatibility seriously.

But surely you can still run into the same issue: I import a@1 and b@1 a@1 transitively depends on c@1 b@1 transitively depends on c@2 Even with different import paths, I still have two different versions of c in my codebase. It'll just be that one of them is imported as "c" and the other will be imported as "c/v2" - but you don't need to worry about that, because that's happening in transitive dependencies that you'…

It’s c and c/v2, not c@1.0.0, c@1.0.5, c@1.0.10, c@1.1.3, c@2.0.0, c@2.3.1, ... Each necessary because packages in the middle have decided to pin versions or add upper bounds to work around bugs. That’s a huge difference.

Re: Can a Rust binary use incompatible versions of the same library?

#34
post #16

Earlier quoted context omitted.

Go got this right: you want an incompatible version, you have to use a different import path. Then you can only pick one version (which is deterministically the lowest possible version) for a certain import path, not a hundred different versions. Also forces people to actually take backwards compatibility seriously.

No one asked about Go here. And no, it didn’t, it’s the same PITA as in Java or maybe even worse because there are no workarounds like classloading or shading. You have no control over the transitive dependencies. The only thing you can do if there’s a conflict is asking the author to fix one of the conflicting libraries.

If someone talks about a problem I’ll damn well explain other people’s solutions as I please. And no, you resolve conflicts by not having conflicts in the first place.

Re: Can a Rust binary use incompatible versions of the same library?

#35
post #11

So both versions of log crate manage their own internal states within the same process? Would this lead to surprising results?

Their internal states in Rust are also namespaced, so two incompatible crates in the same process won't observe each others symbols. If they access external resources that are not namespaced though, that could be a problem.

How would that work for malloc? How can you have two different functions manage the same heap?

Re: Can a Rust binary use incompatible versions of the same library?

#37
post #26

Earlier quoted context omitted.

Backwards compatibility is more difficult in Rust for many reasons. For example, you can't add a new item to an enum without creating missing-case errors everywhere it is used.

You can use #[non_exhaustive] if you want to avoid this.

[deleted]

Re: Can a Rust binary use incompatible versions of the same library?

#38
post #16

Earlier quoted context omitted.

Go got this right: you want an incompatible version, you have to use a different import path. Then you can only pick one version (which is deterministically the lowest possible version) for a certain import path, not a hundred different versions. Also forces people to actually take backwards compatibility seriously.

Backwards compatibility is more difficult in Rust for many reasons. For example, you can't add a new item to an enum without creating missing-case errors everywhere it is used.

You can't add a method in Go without causing new interfaces to match, which breaks at runtime.

Re: Can a Rust binary use incompatible versions of the same library?

#39
post #35

Earlier quoted context omitted.

Their internal states in Rust are also namespaced, so two incompatible crates in the same process won't observe each others symbols. If they access external resources that are not namespaced though, that could be a problem.

How would that work for malloc? How can you have two different functions manage the same heap?

"The same heap" isn't a coherent concept here. Your malloc-implementing memory allocator has some global state, and that state has some pointers to some addresses it got from mmap and some metadata about how long those spans of memory are, which parts are unused, and how long the values it has returned from malloc previously are. If you managed to use two of these, they would each contain data referring to different non-overlapping sets of memory mappings. If you accidentally used a pointer from one with the other, you would go instantly to C UB land:

  The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
Post reply on HN