Go 2 Generics: some features of contracts that I like
A major part of the Go 2 generics draft design is its use of contracts to specify constraints on what types are accepted by generic functions, which are essentially formalized function bodies. On the one hand I think that contracts today are too clever, but on the other hand I think that interfaces are not the right model for type constraints. Although the existing first Go 2 generics draft is probably dead at this point, since it's clear that the community is split, I still feel like writing down some features of contracts that I like (partly because I'd like to see them preserved in any future proposal).
The first thing is that contracts are effectively an API and are explicitly decoupled from the implementation of generic functions. This is good for all of the reasons that an API is good; it both constrains and frees the implementer, and lowers the chances that either users or implementers (or both) are quietly relying on accidental aspects of the implementation. As an API, in the best case contracts can provide straightforward documentation that is independent from a potentially complex implementation.
(I think it would be hard to provide this with the current version of contracts, due to them being too clever, but that's a separate thing.)
Because contracts have an independent existence, multiple things can all use the same contract. Because they're all using the same contract, it's guaranteed that they all accept the same types and that a type that can be used with one can be used with all. This is directly handy for methods of generic types (which might be a bit hard otherwise), but I think it's a good thing in general; it makes it both clear and easy to create a related group of generic functions that all operate on the same things, for example.
(In theory you can do this even if each implementation has a separate expression of the type constraints; you just make all of the separate type constraints be the same. But in practice this is prone to various issues and mistakes. A single contract both makes it immediately clear that everything accepts the same type and enforces that they do.)
The final thing I like about contracts is that they can explicitly
use (and thus require)
struct fields. This is a somewhat contentious
issue, but I don't like getters and setters
and I think that allowing for direct field access is more in the
spirit of Go's straightforward efficiency. Perhaps a sufficiently
clever compiler could inline those little getter and setter functions,
but with direct struct fields you don't have to count on that.
(I also feel that direct access to struct fields is in keeping with
direct access to type values, which very much should be part of any
generics implementation. If you cannot write
generic functions that are as efficient as the non-generic versions,
the generics approach is wrong.)
The potential risk to ZFS created by the shift in its userbase
The obvious conclusion we can draw from FreeBSD ZFS's shift to being based on ZFS on Linux is that the center of gravity of open source ZFS development has shifted to ZFS on Linux. FreeBSD ZFS is shifting its upstream because ZFS on Linux is increasingly where new development happens. A more imprecise and deeper conclusion is that in some sense, the ZFS userbase as a whole is increasingly shifting to Linux.
(It may be that the total numbers of people using ZFS on FreeBSD and Illumos is higher than the people using ZFS on Linux. But if so, the users of FreeBSD and Illumos ZFS don't seem to drive development in the way that happens with ZFS on Linux. There are many possible explanations for this, of course, because there are many factors involved.)
Unfortunately, I think that this shift creates risk due to a consequence of ZFS on Linux not being GPL-compatible, which is that working with the Linux kernel's ever-changing API could become sufficiently much of a problem that ZFS on Linux development could end up coming to a halt. If ZFS as a whole is increasingly dependent on ZFS on Linux development and ZFS on Linux development is partly a hostage to the not particularly friendly views of Linux kernel developers, a problem there affects not just ZFS on Linux but everyone.
At least some of the users of ZFS on Linux are OS-agnostic and are using Linux because they feel it is their best overall choice (that's certainly our view for our new fileservers). If ZoL ground to a halt and stopped being viable, they'd switch over to other OSes (FreeBSD for us). But the question there is whether they'd bring the development resources with them, so that people would do and fund more ZFS development on non-Linux platforms, or if some of the work that is currently being done to ZoL would basically just evaporate.
(One of the things I wonder about is if ZFS on Linux's existence outside the kernel has helped drive development of it. If you're interested in a new ZoL feature, you can develop or fund it on your own schedule, then probably deploy it even on old Linux kernels such as those found in the various 'long term support' Linuxes (because ZoL as a whole is careful to support them). In FreeBSD and Illumos, I think you're much more locked to the overall kernel version and thus the OS version; if you fund a new ZFS feature, you could wind up needing to deploy a whole new OS release to get what you want. If nothing else, this is a longer deployment cycle.)
Given this risk, I definitely hope that people keep doing ZFS work (and funding it) outside of ZFS on Linux. But unfortunately I'm not sure how likely that is. It's quite possible that there are plenty of other people like us, making a pragmatic choice that ZoL is currently good enough and means we can use Linux instead of having to build out and maintain another OS.
(Illumos is not viable for us today for various reasons. FreeBSD might have been, but we didn't try to evaluate it since Linux worked well enough and we already run lots of other Linux machines.)