Open jethrogb opened 6 years ago
Speaking personally, now, if I squint, I see both ML-style modules and the portability lint as ways to make coarser-grained modules work better. For example, if every create has the same portability on every single item, one can sort of look at the dependency closure of a package to sort of see what the portability is. Likewise it's sometimes possible to avoid needing ML functors by a proliferation of helper creates (c.f inlining higher-order functions, like the function argument to map
).
This is perhaps the primary reason why I advocate for keeping std
a facade and staying the "many little crates" course. If we can make good incremental progress splitting off crates like alloc
and making them fully pluggable or fully portable, we can build up the momentum needed to push through these more advanced changes. Also, I feel that if there is a (not too ugly) solution to some portability problem with just plain crates v.s. those big guns, I think by virtue of its simplicity and isolation of a small independent interface, it is the better solution. So even if we had all the language features we want, I'd still advocate that route, and thus don't it will just be temporary stop-gap work that needs to be eventually done in practice.
@Ericson2314 do you want to write the text for this one?
@Ericson2314 taking a stab at it per @jethrogb's request:
Much the various abstractions in
std
require different implementations on different platforms. Currently, they are implemented for linux, windows, and macos in situ. The advantage of this is dispatch is fully static (done at compile time). The disadvantages of this isIt is not modular: it is often necessary to fork
std
to implement an additional platform, which ties one to a specific version of Rust with the costs of rebases. Even though the Rust team is willing to upstream ports ofstd
to obscure platforms, avoiding the rebase penalty, that work-around will never be totally sufficient because many of us want to develop the platform and thestd
port simultaneously (e.g.std
userland over kernel, orstd
directly against os-as-a-library).The interface is not checked: There is no automatic verification that the implementations present the same interface (at least the portion we wish to be the same).
As it turns out, these goals are fairly harmonious. As we better define the platform-specific "input interfaces" which are abstracted into
std
's "output interface", we get both the intended interface for platform-specific crate(s) that can live outside ofstd
, and a mechanism for enforcing that thestd
interfaces are maintained.The problem is a a fully perfect solution solution probably requires a lot of language work. The https://github.com/rust-lang/rfcs/blob/master/text/1868-portability-lint.md is needed when different parts of the same crate have different portability requirements, which at least will be the case with
std
itself but possibly also various platform-specific infra. [Imagine a general "Unix filesystem" implementation which is augmented with linux- or macos-specific functionality.] Also, if we need to "weave" together platform-specific and platform-agnostic functionality in increasingly complex (higher-order, in particular) ways, we will need a more expressive module system like ML's (read about "ML functors" if you are unfamiliar with this.)Historically, our biggest problem in solving this are that
Taking a step back, requirements are