Rust (and its package manager, Cargo) handle this problem fairly well. It’ll try to resolve shared dependencies to a single version, but if it can’t, then it’s perfectly fine to have multiple versions of a package in your dependency tree. This is very common for things like the “itertools” library - a collection of small functions that will rarely, if ever, get exposed in your public API.
Types from different versions of the same package are considered distinct (even if their definitions are the same), so if you try to pass a Foo from version 1.0.0 to a function expecting a Foo from version 2.0.0, then you’ll get a somewhat confusing “Expected Foo but got Foo” error.
There’s a clever solution called the “semver trick”, where you publish a package that depends on an older version of itself as a means of getting around this problem. I’m not sure whether that trick applies to Elm though.