-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Allow crates to specify the version of Rust in which they are written #1709
Conversation
Adding explicit versions to Cargo.toml is rather tedious. Couldn't Then, the developer could |
Hmm, I don't think information should be added to |
This field is added in which section of Cargo.toml? Could this be a dependency instead à la #1133 ? Can you add a 'rendered' link to the first post? |
Top level. @brson and I discovered that it's basically impossible to add anything not on the top level to
Dependency of what?
Done |
From IRC: not sure what, if anything, is needed to prepare for also tracking language features |
Rather than making this a separate item, why not define this in a similar style to #1707, with a versioned dependency on |
I'd also ask whether it makes more sense to version the language or to use versions of rustc itself. In principle, I like the idea of versioning the language, but doing so would require someone to maintain a semver for the language itself separately from rustc. If you decide to do that, I'd suggest separating the version of the standard library from the version of the language. You can determine the version of the standard library you depend on fairly easily: feed that version to rustc and tell it to not allow use of anything with a stability marker for a newer version. The language seems a bit harder to track a semver for. |
I'm not necessarily against that. I think it would be even more useful for features than tests. As I said in your rfc's thread, feel free to mine this RFC for motivation or whatever. One concern is that your proposal may break old versions of Cargo---Cargo only ignores certain unexpected keys, and mainly on the top level. Then again, this isn't really RFC's fault and we should have a better story for changing the
I think for the foreseeable future rust and Rust will have the same version, so this isn't really a burden right now? In practice each rustc release defines the rustc version cause we don't have a formal spec.
I like that. @eternaleye and I both hope parts of the standard library can be written in stable rust and migrated to crates.io. I think I'd amend #1133 to make standard library version requirements optional: if they are not filled in they are inferred from the language version.
True. I was hoping CI could be automated to use these versions---that would work for stdlib and language alike. |
I think it's fine to leave the language and libstd versions tied to rustc. It's similar to how Python versions are tied to CPython as the reference implementation. |
@cuviper even if the language version is defined by rustc, it's still nice to have that field in the verbose output for the sake of other implementations being able to inter-operate with cargo. |
@joshtriplett @cuviper: I personally see it as that (currently), the rustc implementation is the spec and includes within itself the only stdlib, and thus the "version" of the spec is the same as that of rustc is the same as that of the stdlib. In the future, the stdlib may be freed from rustc (by any number of means, not relevant here) and that may diverge in terms of numbering; further on, the language spec may be maintained in its own right and be versioned apart from any implementation. In the very long run, my hope is that we'd have a process around
Language versions then become simple sets of features. This resembles (in different ways) both the OpenGL and C/C++ processes, all of which are quite successful. |
I tested that specifically, and documented the result in RFC #1707. Cargo just treats it as an unknown crate, and handles it gracefully. If you depend on |
@joshtriplett OK that's a pretty reasonable failure case. |
Does it make sense to assume 1.0 at this point? With the release trains, how much code still uses 1.0 nowadays? On the other hand, assuming any other version would be arbitrary.
This smells of the web platform versioning havoc, where people were relying on user agent versions to infer capabilities. Everything was a mess, and eventually they figured out that it is much better to query for individual features. I’m not sure whether it would be an issue in the case of Rust, because at least we have semantic versioning. But if we would specify features instead of versions, then they should be enforced (the compiler should not allow any features that were not specified explicitly), otherwise it would be easy to accidentally use features. It is reminiscent of Haskell’s |
I strongly disagree: Which unstable features were stabilized in a Rust version is the single largest differentiator of Rust language versions. Moreover, by banning "*" from crates.io, the only features published crates could legally depend on would be those that have been included in a stable release - which, as I mentioned above, is currently equivalent to being included in a version of the language spec. This RFC isn't about specifying the version of any specific implementation (which is what user agent sniffing tries to do); it's about specifying the version of the language standard - more like saying "I want associated consts, which were standardized in 1.whatever, but other than that I don't need any features beyond those standardized in 1.2" In the OpenGL world, this works very, very well: OpenGL Whatever is defined exactly by the extensions it contains - a version is merely a shorthand for listing extensions. The result is quite close to what you're advocating - listing what extensions you require - just with a shorthand that makes it actually feasible, rather than an incredible pain in the ass given we have quite a few stabilized features already. Your other suggestion - preventing the use of features not explicitly listed - is (as far as I can tell) 100% infeasible and would require drastic surgery on rustc. Sadly. |
I suppose this could be considered decoratively querying for them all at once? It's certainly better than vendor prefixes, to take another web example.
With already stable features, this is true: they could "blend" with other stable features after they've been stabilized and thus there is no way to toggle them individually. For unstable features this is quite possible and I agree a good idea.
It is weird that this does fairly little for Cabal. I think the Haskell idiom of trying out new ideas as features the people use is good. Right now, yes there is the nightly ecosystem (and almost everything I do is part of it) but the "semi-stability" of versioned unstable features (may not work forever but no sudden breakage) might invite more users. |
I agree that specifying all features would be infeasible (both for the compiler to be able to toggle them individually, and for the user to specify them all), I just wanted to point out the similarity. You are right, in a sense Rust versions would be a shorthand for feature sets, and this will probably work out fine. But the issue of enforcing that the version is correct remains: what if I say But perhaps enforcing this is not Cargo’s responsibility? It could be left to crate authors, who could rely on CI for instance. With Travis CI it’s only a few lines to test on older compilers. |
The library already include stability annotations that say "stable as of version N". It seems potentially feasible to have the compiler let you pass a version number, and enforce that you can't access anything with a stability annotation for a newer version. |
@ruuda yeah outside of CI, this is honor system and unenforceable. Unfortunately, but no worse then version reqs on crates in that regard. :/ |
@joshtriplett That's a lot https://internals.rust-lang.org/t/pre-rfc-a-vision-for-platform-architecture-configuration-specific-apis/3502 preventing one from accidentally using unportable stuff. I think it's a good idea, but best left as future work https://internals.rust-lang.org/t/pre-rfc-a-vision-for-platform-architecture-configuration-specific-apis/3502 (a generalization is when two dependencies are unified, make sure their consumers only get what they asked for). |
Working on implementation https://github.com/QuiltOS/cargo/tree/rust-version |
What is the status of this? I ran into an issue today that I believe could have been prevented entirely by this RFC in its current form. |
Relevant prior RFC and discussion in #457. |
I like the idea here, and I like the simplicity. I believe we will want to expand into features and more precise nightly versioning, etc. But I think it is best to leave that for the future. Likewise, Cargo (in conjunction with Rustup) could automatically get the right version to build a crate and use that, but that seems like something to leave until later. I think a language version, and not versions for compiler, libs, etc. is the right approach. I don't have a preference between the proposed ad hoc value and using a dependency. My only worry is that 1.0 is the wrong default and that there should be an 'unspecified' default. The reason is that 1.0 is effectively the 'strongest' possible value (the hardest for a program to specify) and just because the program compiles today, there is no guarantee that it compiles with version 1.0. Random idea: the lockfile (or some other metadata store) could contain two versions - the specified version and the tested version, where the former is the value specified in the toml file and the later is the value Cargo actually used to build the crate. CI could expand the tested value to a list of tested versions. For anything user-facing, if the specified value is not specified, then the tested value can be used. |
Reposting some concern discussed in #1707:
|
@joshtriplett: As one of the more outspoken proponents of the "depend on features of the compiler" end of things, I do feel a need to raise a cautionary note that the semantics of this may well not match up as expected with cargo features on crate dependencies. As a result, I'd be hesitant to say that #1707's syntax does in fact "allow it" - it allows specifying crate-style feature requirements, but it's unknown whether the semantics actually line up. In essence, the "language version" consists of five parts:
Of all of these, only 5 is not expressible as a "feature" of some description - but 1-3 are a different kind of "feature" than 4, and only 4 necessarily maps to what Cargo usually means. In addition, 4 is perhaps better handled by hanging features off of dependencies on the stdlib, not the compiler. (I also feel like bug fixes in the stdlib are better handled with stdlib deps, and not compiler deps). Beyond that, if there's ever going to be support for using dependencies on I don't really have a solution to these concerns; this is more a plea for caution in presuming that the syntax we have (even extended) matches up with the tooling we would need for this use case. |
@eternaleye I agree that Cargo features don't fit perfectly, and soundness fixes or other semantically significant fixes are exactly what I had in mind when I said that versions would still be required. Personally, I do think that items 1 and 2 would work as Cargo features of rustc, and 3 and 4 belong either on rustc or std depending on if we split out standard library dependencies as separate. Distinctions like those are precisely why I think it makes sense to separate "syntax for tool dependencies" from "features", and separate both from "dependencies on std" (e.g. #1133). Supporting versioned dependencies on rustc would provide an improvement over the current situation, and due to things like soundness and semantic fixes, we know we'll need versioned dependencies even if we also support feature dependencies. |
@joshtriplett: Well, I'm very bullish on splitting out However, treating both 3 and 4 as Cargo features introduces another problem: You are now trying to fit two namespaces into one. In addition, I'm firmly of the opinion that 3 is a matter of As a result, I am very much not convinced 3 and 4 should both be mapped to Cargo features of To be honest, I see this as "The Revenge of the Son of Interface vs. Implementation" - there's the contract of any implementation of |
@eternaleye All of those seem like reasonable concerns to me. And I agree that all of them need resolving as part of any RFC to support feature dependencies on rustc or std. I just don't think we need to resolve that before we can introduce any mechanism to allow specifying dependencies on tools like rustc or cargo. |
I think the first step is introducing Cargo.toml schema versions. This would be a single top-level key (like this), ignored by older Cargo. Then we can experiment more freely. This is also needed for std-aware cargo and, if we do the same for lockfiles, deterministic crate source hashes. Note that cargo.toml schema breaking changes are no big deal because Cargo can easily learn how to parse all versions and make plans with a mixes. |
@Ericson2314 "Ignored by older Cargo" doesn't seem like a feature here; older Cargo needs to know that it doesn't understand the newer file. |
@joshtriplett True. We can find a different syntax for that, then. Or just live with it and declare the first Cargo understanding the field as truly forward compatible, cause we currently have no story right now one what older versions of Cargo do with other schema that post-date them. |
Summarizing some discussions today: @Ericson2314, @eternaleye, and I met on IRC, talked through the problem, and ended up drafting a successor RFC via Etherpad for both #1707 and #1709. We'll submit that RFC in the near future; that will serve as a baseline to solve the most critical core problem, and then we can build further work on top of that. |
This RFC makes it possible to introduce new Cargo features that older versions of Cargo would otherwise misunderstand, such as new types of dependencies or dependency semantics; the new schema version prevents those versions of Cargo from silently ignoring those features and misbehaving, and allows dependency resolution to work appropriately for both old and new Cargo. This serves as a successor to both rust-lang#1707 and rust-lang#1709, and provides a basis for other Cargo feature RFCs to build on. Co-authored by Josh Triplett (rust-lang#1707), @Ericson2314 (rust-lang#1709), and Alex Elsayed (@eternaleye).
@joshtriplett is this RFC superseded by #1953? Should it be closed? |
@nrc technically this and that do different things: this is about the rust langauge requirements, that is about the cargo langauge requirements. The teams seem to want a single version for everything, as expressed in the thread of that other RFC. That would entail taking elements from this and rewriting heavily. |
Unassigning myself because this moved to a team I'm not a part of. Ping @rust-lang/cargo for a new shepherd (and maybe an update). |
Team member @withoutboats has proposed to close this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
Oh, just saw this. Fine with me. |
This is an alternative to #1707 . I also plan to write an RFC covering the "Cargo.toml specification language", but the implementation for that is quite different because older Cargo can't even attempt to to parse the package, rather than merely not use it in the build plan. For this reason, perhap the two concepts should be handled separately.
Rendered