For example, I depend on Foo v1, and would like to upgrade to Foo v2. Currently mainstream languages either use a type system to indicate the upgrade was unsuccessful (can't catch everything, and still require the user to patch things), or allow the user to muddle along, knowing things might break subtly but not enough to be "bothersome" (e.g. node ecosystem).
So one Foo upgrade is costing O(n) in refactoring cost where n = dependents of Foo. Given enough patience the Foo author could make an adaptor between v1 and v2 to reduce it to O(1) upgrade (inside Foo itself), but this is asking so much that nobody sensibly do it, except for big projects which provide great migration warnings, codemods, bridges, etc.
This, combined with, say, plaintext structural sharing/diffing between library versions (so that code size doesn't blow up if you have 5 transitive dependencies on Foo), might solve two important problems of dependency/versioning hell imo, and keep software as fresh as realistically possible.
I understand the general version of this is uncomputable, but that's my question: is there research on constraining the expressivity of an language just enough to make version upgrade of a library mostly automatable? Here's an idea: first-class support for fetching the code of a transition between v1 and v2, half-automated by the language & tools, half community-maintained & uploaded to a dedicated place. Alternatively, push as much as possible to data instead of functions, to make writing transition code (which would simply be massaging data from one form to another) much easier, like GraphQL deprecation strategies (https://facebook.github.io/graphql/#sec-Object-Field-depreca...)
Real-life example: two React.js components written under two different React versions naturally don't interoperate. You can't include one inside another. Right now you "can", but this is thanks to sheer human effort from React.js to maintain backward compatibility, so components using React 15 work with components using 14, etc. Same for Java, Windows, and others. The language doesn't help you with that at all. Semi/fully automated version transition/code generation would be a killer language feature.