Due to the significant improvements in package management in Emacs 25.1, I do not think there is any reason to continue maintaining the generated Emacs package sets in Nixpkgs. The combination of
package-archive-priorities
,use-package
can take the place of any Emacs+Nixpkgs configuration today. I think it is only sensible to keep around packages that have Nixpkgs-specific patches or that need to integrate with other packages.
I intend to remove the generated packages from master 14 days from today, on 8 October 2016. If anyone cannot live without them and would like to take over maintaining them, I'm happy to do that instead. Of course, this would not affect any stable branch or any package that isn't generated by emacs2nix.
Attn. @chaoflow @lovek323 @peti @the-kenny @jwiegley (Emacs maintainers)
Attn. @oxij (melpa2nix)
Hi @ttuegel, this sounds reasonable, but how many configurations is it going to break, and will people be notified in some way of the "new way" to configure their Emacsen?
This would break many configurations. Unfortunately, we don't have a way in Nixpkgs to notify users about package deprecation (#15357). The best we can do right now is announce through the usual channels, primarily the mailing list. This is something nixos-weekly would be good for, but it doesn't seem like that got off the ground.
What is declarative package management with use-package
and where can I find out more about it?
It seems to me that the argument for keeping them is the same as the argument for using Nix in general: a declarative specification of what is installed, and especially if one uses melpa
packages, the ability to roll-back from upgrades that break things.
@ttuegel If your only concern is effort in keeping them up to date, then I would be happy to take on that task; the fact is, I've been regenerating them every week or two for the last few months anyway, I've just not necessarily submitted the changes out of a desire to avoiding excessive churn and/or too many requests for you to merge stuff. In fact, I finished regenerating a new package set about 15 minutes before I saw this issue. :)
Of course, if there are other considerations that make you think it is a bad idea---rather than it just being a task you don't want to feel obliged to keep on top of---I'm also fine with that; as you say, some improvements in 25.1 make it feel less tedious to do it that way. But if it's just the time and attention issue, I feel comfortable I could take up that slack.
@peti I assume that @ttuegel is referring to https://github.com/jwiegley/use-package#for-packageel-users.
It seems to me that the argument for keeping them is the same as the argument for using Nix in general: a declarative specification of what is installed, and especially if one uses melpa packages, the ability to roll-back from upgrades that break things.
The first point (a declarative specification) is now accomplished by Emacs alone, in my opinion. I hadn't considered the roll-back feature that Nix provides. I've never used it for Emacs myself because it would require rolling back my entire system. I also can't think of a time when something was so broken I would consider it. I can see why that would be a desirable feature, though. You _can_ accomplish this by keeping your ~/.emacs.d/elpa
under version control, although I acknowledge that may be undesirable for other reasons.
If your only concern is effort in keeping them up to date, then I would be happy to take on that task; the fact is, I've been regenerating them every week or two for the last few months anyway, I've just not necessarily submitted the changes out of a desire to avoiding excessive churn and/or too many requests for you to merge stuff. In fact, I finished regenerating a new package set about 15 minutes before I saw this issue.
It's certainly the case that I don't update them as often as I should, and this is only going to get worse now that I don't use them. That's not my only concern, though. As you pointed out, there is a huge amount of churn because packages are updated very quickly. Our generated packages are almost always out of date. I also question if this is good stewardship of our community's resources. I already had to disable Emacs packages on Hydra; is it a good use of bandwidth to continue distributing the expressions in the channel?
@ttuegel I'm supportive of whatever you choose.
I wonder, in addition, about the various emacs packages either in all-package.nix
or emacs-package.nix
, the vast majority of which are equally superfluous, and often out-of-date.
It seems that if they are left in place, they're just going to represent an attractive nuisance---leading users to use them, and developers to add additional packages, or update existing ones, at which point we have the worst of both worlds?
I dunno, maybe I'm trying to be too hard-line about it, but it seems like most if not all deserve the same treatment.
Not that I have the time or expertise to help with the workload, but does emacs 25.1 package.el support rollbacks, and how? Can I bring up an exact configuration of my emacs on another machine from a declarative init.el? This is why I really like nix in this regard.
As a sort of poor man's declarative emacs configuration, I like @jwiegley's git submodule approach too, because it automatically gives version pinning, and rollback after an unwanted update is just a git reset
. Many major disadvantages though:
Also nix allows fetching from a local (source code) directory, which package.el does not? (I know package.el can fetch/install from a local file.) This is nice in my opinion because it means not being limited to what is on the package archives (elpa/melpa). In this regard, nix just works and has all the features expected from a package manager.
But yes because the nix expressions are outdated a lot of the time, for the majority of emacs packages, personally I use @jwiegley's approach + quelpa because it's good enough for me.
All that being said, I obviously do support removing the generated emacs packages if it means less confusion and less (useless) workload, as long as the mechanism to use nix for emacs packages still exists, or did you want to remove that as well? If not for anything else, I think nix is still very useful for use with emacs packages that require non-elisp components (just want to clarify on your "need to integrate with other packages" point).
It seems that if they are left in place, they're just going to represent an attractive nuisance---leading users to use them, and developers to add additional packages, or update existing ones, at which point we have the worst of both worlds?
I agree, but I don't think I have the power to unilaterally remove them!
does emacs 25.1 package.el support rollbacks, and how?
No.
Can I bring up an exact configuration of my emacs on another machine from a declarative init.el?
Yes, except for the package _versions_. However, you can't actually do this with Nix: there aren't binaries on Hydra for Emacs packages, so once a package is updated upstream, it will fail to build and install. Of course, if your configuration is recent enough, everything will still work, but you would also get the same versions from MELPA et al.
Also nix allows fetching from a local (source code) directory, which package.el does not?
package.el
doesn't build from source, you want to look at package-build.el
. The Emacs ecosystem is not setup to do builds from source, but I think Quelpa will do what you want here.
If not for anything else, I think nix is still very useful for use with emacs packages that require non-elisp components
Yes. I don't intend to change anything about the human-created packages. I'm just talking about the machine-generated package expressions for pure-Elisp packages.
Yes, except for the package versions.
Bit of a shame, I thought this was possible but I admit I haven't used nix for an emacs package in a while.
package.el doesn't build from source, you want to look at package-build.el. The Emacs ecosystem is not setup to do builds from source, but I think Quelpa will do what you want here.
Yes I know. I also know about package-build, it also doesn't do this because of lack of interest I assume. It's why in quelpa I added the ability to do this.
Yes. I don't intend to change anything about the human-created packages. I'm just talking about the machine-generated package expressions for pure-Elisp packages.
Anyway, thank you for the quick reply! This is all I wanted to know, and I agree with whatever you choose too. :+1:
One disadvantage of Emacs' builtin package management is that it cannot install packages that have components written in languages other than elisp, i.e. one cannot install structured-haskell-mode this way because it depends on an executable that is written in Haskell and Emacs does not know how to compile it.
I, too, am concerned with what @peti mentions. It's likely that we have to maintain a set of emacs-packages in nixpkgs for the sake of packages with native dependencies.
One disadvantage of Emacs' builtin package management is that it cannot install packages that have components written in languages other than elisp, i.e. one cannot install structured-haskell-mode this way because it depends on an executable that is written in Haskell and Emacs does not know how to compile it.
.
I, too, am concerned with what @peti mentions. It's likely that we have to maintain a set of emacs-packages in nixpkgs for the sake of packages with native dependencies.
Right, I'm not suggesting removal of any packages with native dependencies. I'm only talking about removing the packages generated by my emacs2nix tool, which doesn't know anything about native dependencies.
However, this alludes to another problem. We have packages with native dependencies and Emacs dependencies, so it may still happen that we have outdated, pure-Elisp packages in Nixpkgs. That is not a good situation; it doesn't interact well with installing pure-Elisp packages through package.el
.
One way to solve this problem would be: instead of installing Emacs packages to a profile, we use Nix to build a "private ELPA" with the packages with native dependencies. Then, users could install from this package archive using package.el
. All the unmodified dependencies would come from upstream (ELPA or MELPA).
Another way to solve this problem: instead of distributing modified Emacs packages with native dependencies, we could distribute live patches (one of the advantages of an interpreted system). To be concrete, take @peti's example, structured-haskell-mode. We could build the Haskell executable normally, but instead of distributing the Emacs mode with it, we would ship some initialization code like
.elisp
(eval-after-load 'shm (patch-shm-native-dependencies))
This would require a bit of package-specific knowledge, though.
So I am sure there's a counter-example out there somewhere, but in general I don't think emacs packages are as tightly tied to the binaries they need as @peti suggests.
While certainly you could easily end up in a situation where you have, say, the hindent
binary installed but no actual hindent
package installed in emacs (or vice versa), I think most emacs packages of that sort simply assume that they will find the executable they're looking for in the path (or complain loudly), so having their installation processes tied together isn't actually necessary---just install the emacs package via package.el
, install the corresponding binary via nix
.
In general, I don't think emacs packages are as tightly tied to the binaries they need as @peti suggests.
It is true that this case is rare. Nonetheless, these cases _do_ exist and I wonder what the recommended way of dealing with them could be. structured-haskell-mode has two components: the structured-haskell-mode executable and the elisp library that implements the actual Emacs mode on top of it.The elisp code also depends on haskell-mode
, which is a pure elisp library. This means that when we compile shm's elisp library, we have to pick some version of haskell-mode to pass in as a build input. Now, if haskell-mode is not a part of Nixpkgs any more, where does that build input come from? To compile shm's elisp mode reliably, we need all transitive dependencies of that package available in Nixpkgs, which might be a non-trivial number (although I'm just guessing, I haven't checked).
The alternative is to use Nix to build that executable (because Emacs can't do it) and package.el to build the elisp mode (because Nix can't do it) and then use them together. Now, I suspect that approach would probably work fine most of the time, but honestly, if these two parts ever get out of sync and subsequently interact poorly in some way, then I sure as hell don't want to be responsible for diagnosing and debugging those symptoms because that is not going to be fun.
Peter Simons [email protected] writes:
It is true that this case is rare. Nonetheless, these cases _do_ exist
and I wonder what the recommended way of dealing with them could be.
This is still an open issue, not solved by package.el nor by nix. For
packages where the binary is usually used standalone with emacs as an
optional interface, it's common to just ship the elisp with the
source distribution of the binary and put it in
$out/share/emacs/site-lisp
(or similar).
sadly this isn't applicable for libraries with package.el dependencies.
The cleanest solution here would be to write the elisp in such a way
that it detects if it's missing dependencies and make it generate a
user-error
.
I don't think that we should create our own package.el repository just
for packages with native dependencies. We need to keep in mind that we
want to have _less_ work in the end, not more :)
I don't think including _just_ the packages needed for all packages with
native deps is less work in the end, so we might as well keep all of
melpa-stable (or other repos).
My suggestion is: Simplify emacs2nix and teach it (to some degree) about
native dependencies. A simple json file with a mapping of package-name
-> [nix-attr-path, ...] should suffice here.
Another improvement would be to emit compacted JSON for the generated
emacs package set. This would minimize the differences in each commit.
Another thing: We tend to have this or a similar discussion whenever we include automatically generated packages in nixpkgs.
Is there some kind of guideline, or at least some consent, on if/how we should include these? There are good cases for and against including them, and I think some standardized way of packaging/updating/committing/tooling would be very helpful. For example we could write us a bot that automatically runs a bash script every two days (or so) that runs tools for different languages to automatically update their libs. If all tests succeed the bot would automatically merge it. We could even do this (almost) completely on Hydra.
What's the performance on JSON in nix? It's quite easy to emit it from practically any language, and I think it's a good way of storing hashes/urls/names for _many_ packages (emacs, chicken, haskell(?)). This would simplify tooling as the tools wouldn't have to emit nix expressions directly. Plus such JSON can be diffed easily and possibly even shared with guix
.
The alternative is to use Nix to build that executable (because Emacs can't do it) and package.el to build the elisp mode (because Nix can't do it) and then use them together. Now, I suspect that approach would probably work fine most of the time, but honestly, if these two parts ever get out of sync and subsequently interact poorly in some way, then I sure as hell don't want to be responsible for diagnosing and debugging those symptoms because that is not going to be fun.
@peti This is what I am suggesting we do. If there are synchronization problems between the Elisp part and the native part, that is the responsibility of the package author. I know I must seem like the callous sort of distribution maintainer whose response to everything is, "Blame upstream!" But, we have to draw a line somewhere. I think if an Elisp package requires a particular version of a native executable, it's the package author's responsibility to check for that condition and inform the user if it's not satisfied.
I don't think including _just_ the packages needed for all packages with native deps is less work in the end, so we might as well keep all of melpa-stable (or other repos).
@the-kenny We can't keep just MELPA Stable because it has dependencies on MELPA. :weary: At that point, we might as well keep everything.
My suggestion is: Simplify emacs2nix and teach it (to some degree) about native dependencies. A simple json file with a mapping of package-name -> [nix-attr-path, ...] should suffice here.
I'm not sure what you mean by "simplify emacs2nix". Handling native dependencies would be a significant and unnecessary complication. Native dependencies of generated packages can be handled by an override on the Nix side.
Another improvement would be to emit compacted JSON for the generated emacs package set. This would minimize the differences in each commit.
This would significantly _increase_ the commit size. Right now, updating a package only changes the version number, the Git revision (or Mercurial, Bazaar, etc.), and the source hash. The diffs for individual packages are quite small and are actually intelligible to a human. The only reason the update commits are as large as they are is because we're updating thousands of packages at once.
What's the performance on JSON in nix? It's quite easy to emit it from practically any language, and I think it's a good way of storing hashes/urls/names for many packages (emacs, chicken, haskell(?)). This would simplify tooling as the tools wouldn't have to emit nix expressions directly. Plus such JSON can be diffed easily and possibly even shared with guix.
The performance of Nix's JSON parser is absolutely terrible. I originally did JSON with emacs2nix. Not only is the parser's performance bad, but after Nix parses the JSON, you have to turn it into packages on the Nix side. That involves some actual computation, mostly string handling. Anything in Nix that isn't strictly declarative is impossibly slow.
Also, Nix's JSON parser only supports a _subset_ of JSON. Which subset? Your guess is as good as mine. At least, I know it doesn't support Unicode strings. That alone probably isn't a deal-breaker, unless you happen to be using a JSON-generating library in your language of choice which assumes full JSON compliance.
Personally, I would keep the nix-generated set, if you happen remove it,
I would just revert that and start updating MELPA in my own branch of
rejected pull requests and their extensions (which is ~100 patches ahead
of nixpkgs already anyway).
I really want all of my systems with all the configs to be generated
from a repository with branches (yes, from time to time I have to have
branches in my nixpkgs and backport commits between them) with proper
rollbacks (yes, including everything, it saved my ass at least twice,
I'm okay with sacrificing x5 disk space for that, if necessary, this is
one of the two reasons I use nix).
Now, I understand your pain of MELPA updates, I think there are are
several options (assuming we still want to package them in nix):
Personally, I would be totally okay with pulling a couple more
repositories / channels on updates.
I would prefer the last variant, not only for emacs, but also for
Haskell packages, btw.
What is needed here, I think, is we should standardize the interface for
nixpkgs' package sets updates. I would love to be able do
$ cd ~/src/nixpkgs; nix-build -A nixpkgs-package-sets;
$ ./result/bin/nixpkgs-package-sets --update emacs --update-nix '*'
(this fetches MELPA and regenerates all the nix files)
or, say, only some of them:
$ ./result/bin/nixpkgs-package-sets --update emacs --update-nix 'magit*'
(this fetches MELPA and regenerates all the nix files, but leaves
everything that does not match "magit*" regexp in the old state)
(one can then check that they and their deps actually build with
`nox`)
and have it do all the things, or fail (leaving the tree in a clean
state), without fumbling in different sub-directories of nixpkgs.
Because there is considerable interest in the ability to rollback configurations with Nix, and because Emacs doesn't offer this feature natively, I will not delete the generated packages at this time. To keep them, I think their quality must improve; therefore, I suggest the following:
Right now, it takes three commands to update a package set, but this could be automated down to one command for all the package sets. @mdorman If I get this part working, are you still willing to take over periodic updates?
emacsPackages
with emacsPackagesNg
. The former has no automatically-updated packages and is generally out-of-date. emacsPackages
also has relatively few packages. As @mdorman put it, they are an attractive nuisance. We have avoided making this change before because it could break configurations, but there is a new stable release due in a few days, so this is the best time to introduce breaking changes into master. @oxij I think this is the rejected PR you referred to; is it in any condition to be re-opened?
If we continue to carry the generated packages, I think we should at least keep the promise that building your configuration on different machines will actually _work_. Right now, it mostly works, which is the worst possible state. (If it didn't work at all, at least it wouldn't be surprising.) This means removing the generated packages that are fetched from EmacsWiki or CVS repositories. These fetch methods are actually deprecated upstream, so I don't think this is a radical step.
This issue has appeared several times, although I didn't mention it here. You can't have multiple versions of the same package in your Emacs environment! To take a recent example, if one package depends on avy-0.4.0
then _every_ Emacs package that depends on avy
must use that version. The generated Nix expressions will happily let you override the dependencies of just one package, with unpredictable results. While we can never stop a determined user from shooting themselves in the foot, we could at least not hand them the gun.
@ttuegel Yes, I would be happy to keep on top of this. And, in fact, I already have this pared down to one command, though it's very much tuned to my local setup; I could spend a little time getting it upstreamable.
I'll also mention that your excision of duplicated (and largely out of date) packages from emacs-packages.nix
almost perfectly matches my similar change.
You can't have multiple versions of the same package in your Emacs environment!
I think this is just the way elisp works though? So not sure if much can be done about protecting against this if that's what you meant?
I think this is just the way elisp works though? So not sure if much can be done about protecting against this if that's what you meant?
Yes, this is how Elisp works. Nix doesn't know that, so Nix will happily let you install two packages depending on different versions of a common dependency. As a result, bad things happen.
Ah I see that's why https://github.com/NixOS/nixpkgs/issues/18976 happened. Sorry for the noise, thanks again.
@ttuegel
- [ ] Fully automate package updates.
:+1:
- [ ] Finish replacing
emacsPackages
withemacsPackagesNg
.
:+1:
The former has no automatically-updated packages and is generally
out-of-date.emacsPackages
also has relatively few packages. As
@mdorman put it, they are an attractive nuisance. We have avoided
making this change before because it could break configurations, but
there is a new stable release due in a few days, so this is the best
time to introduce breaking changes into master. @oxij I think this is
the rejected PR you referred to; is it in any condition to be
re-opened?
Yep, I have some of that there, but I'm not sure that it's realistically
possible to push that to 16.09. I did rewrite most of emacsPackages into
emacsPackagesNg (or thrown them away because MELPA has them already),
but I didn't test most of them to actually work.
What we could totally do, though, is to officially deprecate
emacsPackages in 16.09 and then chop at them piece by piece via:
emacsPackages = {
...
package = emacsPackagesNg.package;
...
}
emacsPackagesNg = {
package = actual-package-expression;
}
- [ ] Remove generated packages that do not have reproducible builds.
Agreed.
- [ ] Fix (prohibit) dependency overriding.
Agreed.
@ttuegel I think we should close this, and open a "emacsPackages ->
emacsPackagesNg" issue instead.
I propose merging the following as a start (it deprecates the use of callPackage in
emacsPackages, really, but prints a long-ish warning)
https://github.com/NixOS/nixpkgs/compare/release-16.09...oxij:rework/deprecate-emacsPackages?expand=1
I'm not sure that it's realistically possible to push that to 16.09
The feature-merge window for 16.09 closed last month, I'm only discussing changes to master. I think it's safe to risk breaking master now because users can fall back from unstable to 16.09 without great difficulty.
I propose merging the following as a start (it deprecates the use of callPackage in emacsPackages, really, but prints a long-ish warning)
Have you checked that this doesn't print a warning when you do nix-instantiate
? Otherwise, nix-env
will spew that warning even when the user isn't actually using emacsPackages
. I've tried to deprecate packages this way before without success.
Thomas Tuegel [email protected] writes:
I propose merging the following as a start (it deprecates the use of callPackage in emacsPackages, really, but prints a long-ish warning)
Have you checked that this doesn't print a warning when you do
nix-instantiate
?
Otherwise,nix-env
will spew that warning even when the user isn't
actually usingemacsPackages
. I've tried to deprecate packages this
way before without success.
It doesn't seem to spew anything on nix-instantiate and nix-env when
evaluating other packages:
$ nix-env --file ./default.nix -i -A firefox
<silent>
$ nix-env --file ./default.nix -i -A emacsPackages.bbdb
<print the warning>
Any news on this?
I have changes that move a number of emacsPackages.* to be references to emacsPackageNg.*. Generally of the form:
(and remove the corresponding file) hand-maintained expression.
I have been reluctant to push them upstream because I am uncertain how to be sure they don't break anything. I'm interested in suggestions, even if they're somewhat manual (instantiate a shell with just that emacs package installed, verify it is available, turn on the major mode or evaluate a likely function, for instance).
I'm happy to do the legwork of implementation, but I don't feel qualified to lead figuring out what the right process should be, so I would appreciate any suggestions.
Michael Alan Dorman writes:
I have changes that move a number of emacsPackages.* to be references to emacsPackageNg.*. Generally of the form:
- haskellMode = callPackage ../applications/editors/emacs-modes/haskell { };
- haskellMode = emacsPackagesNg.haskell-mode;
(and remove the corresponding file) hand-maintained expression.
And those should be one change per commit so that
I have been reluctant to push them upstream because I am uncertain how
to be sure they don't break anything.
if something breaks (and something will) one could easily revert only
that part.
Also note that doing
- haskellMode = emacsPackagesNg.haskell-mode;
might be incorrect, since both emacsPackages
and emacsPackagesNg
have emacs
parameter, and it should match. I.e. you'll need to
redefine emacsPackagesNg
inside of emacsPackages
.
I'm interested in suggestions, even if they're somewhat manual
(instantiate a shell with just that emacs package installed, verify it
is available, turn on the major mode or evaluate a likely function,
for instance).
I'm happy to do the legwork of implementation, but I don't feel
qualified to lead figuring out what the right process should be, so I
would appreciate any suggestions.
That's a lot of work, and this testing doesn't guarantee anything since
many packages will load, but won't work as expected (yay! e-lisp!).
I would just skip that step and let people that use emacsPackages use
and test new expressions. Hopefully, emacsPackagesNg exists long enough
so that at least most of them would actually work.
I have changes that move a number of emacsPackages.* to be references to emacsPackageNg.*. Generally of the form:
As for the rest, I would still stub them with
https://github.com/oxij/nixpkgs/commit/eab72e44382b8be3f3bcb7a107cf2e109b05958f
(top commit of
https://github.com/oxij/nixpkgs/tree/pkgs/deprecate/emacsPackages)
because it's helpful, and actually works as expected despite the comments above.
If I were motivated enough I would cherry pick (or not, whatever) that
top commit, do those stubbing changes, one per commit, and file a PR.
Spent the last 20 minutes trying to figure out why my intero
install was so old...
This will be the cause 馃槃
Bit of a coincidence you closing this just as I was having trouble with figuring out what exactly to do in order to install things like ProofGeneral, ttuegel!, @ttuegel!
What, exactly, is the current method to install ProofGeneral, anyway? It doesn't seem to be doable with emacsPackagesNg.
What, exactly, is the current method to install ProofGeneral, anyway? It doesn't seem to be doable with emacsPackagesNg.
I don't believe it is part of emacsPackagesNg
, but you should be able to install it from emacsPackages
anyway.
Closed #18934.
Closed why? Has this been implemented?
Closed why? Has this been implemented?
No, I closed it because (per the discussion above) we decided to keep the generated packages for the forseeable future.
Ah, good. You got me sweating there.
Most helpful comment
Because there is considerable interest in the ability to rollback configurations with Nix, and because Emacs doesn't offer this feature natively, I will not delete the generated packages at this time. To keep them, I think their quality must improve; therefore, I suggest the following:
Right now, it takes three commands to update a package set, but this could be automated down to one command for all the package sets. @mdorman If I get this part working, are you still willing to take over periodic updates?
emacsPackages
withemacsPackagesNg
.The former has no automatically-updated packages and is generally out-of-date.
emacsPackages
also has relatively few packages. As @mdorman put it, they are an attractive nuisance. We have avoided making this change before because it could break configurations, but there is a new stable release due in a few days, so this is the best time to introduce breaking changes into master. @oxij I think this is the rejected PR you referred to; is it in any condition to be re-opened?If we continue to carry the generated packages, I think we should at least keep the promise that building your configuration on different machines will actually _work_. Right now, it mostly works, which is the worst possible state. (If it didn't work at all, at least it wouldn't be surprising.) This means removing the generated packages that are fetched from EmacsWiki or CVS repositories. These fetch methods are actually deprecated upstream, so I don't think this is a radical step.
This issue has appeared several times, although I didn't mention it here. You can't have multiple versions of the same package in your Emacs environment! To take a recent example, if one package depends on
avy-0.4.0
then _every_ Emacs package that depends onavy
must use that version. The generated Nix expressions will happily let you override the dependencies of just one package, with unpredictable results. While we can never stop a determined user from shooting themselves in the foot, we could at least not hand them the gun.