RFC: Allow crates to specify the version of Rust in which they are written #1709
Adding explicit versions to Cargo.toml is rather tedious. Couldn't cargo publish also notify the repository (crates.io) about the version it was compiled with (maybe by automatically inserting some info into Cargo.toml).
Then, the developer could cargo publish the same version multiple times with different compiler versions, and these compiler versions would be added to the published crate.
Hmm, I don't think information should be added to Cargo.toml on upload. But cargo new can add the field based whatever rustc is on PATH, and cargo publish can complain if it's not present while proposing how to fill in the field the same way.
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?
This field is added in which section of Cargo.toml?
Top level. @brson and I discovered that it's basically impossible to add anything not on the top level to Cargo.toml without breaking old Cargo versions. This will half to be solved before #1133 can be merged.
Could this be a dependency instead à la #1133 ?
Dependency of what?
Can you add a 'rendered' link to the first post?
Done
From IRC:
<Ericson2314> not sure what, if anything, is needed to prepare for also tracking language features
<eternaleye> Ericson2314: Well, it's kind of like OpenGL
<eternaleye> OpenGL X is an aggregation of some number of OpenGL extensions
<eternaleye> Substitute OpenGL version for Rust version, and extensions for language #[feature] flags that have been stabilized.
<eternaleye> Personally, I'd favor rust = "version" overloaded with rust = { feature1 = stable, feature2 = stable, feature3 = * }
<Ericson2314> that makes sense
<Ericson2314> the -version is sort of redundant
<eternaleye> Or possibly them as separate keys, both optional - version and features
<eternaleye> As an example of where it matters, consider an alternate rust compiler, which implements associated items very early, but otherwise is only compatible up to Rust 1.2
<Ericson2314> that was my other thought
<Ericson2314> I'm fine either way
<Ericson2314> yeah definitely
<Ericson2314> should features either be '*' or stable?
<eternaleye> Also, feature1 = stable means it implements feature in the form it was stabilized; not that "this implements the version of rust it was first stable in"
<eternaleye> Well, that's the thing
<eternaleye> If we ever want to support actually using unstable features, we should track when those features change pre-stabilization
<eternaleye> And then you have, say, "simd = 0" vs "simd = 1" vs "simd = 2", and "simd = stable" is the same as "simd = 2"
<Ericson2314> eternaleye: agree on meaning of stable
<Ericson2314> yeah that sounds nice, but probably more controversial
<Ericson2314> as its convenient to break unstable thing whenever
<eternaleye> Yeah, hence my use of "*" - it's compatible with our current meaning of "*" around semver
<Ericson2314> yeah, good move :)
<eternaleye> Moreover, banning * from crates.io fits current policies
<eternaleye> While still allowing feature-based Rust requirements
Rather than making this a separate item, why not define this in a similar style to #1707, with a versioned dependency on lang:rust? That would allow, for instance, declaring a different dependency for dev-dependencies (perhaps tests need newer Rust to check the interaction with some feature), or declaring a different dependency based on a feature flag (enable a foo feature to use the foo feature of latest Rust).
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.
Rather than making this a separate item, why not define this in a similar style to #1707, with a versioned dependency on lang:rust?
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 Cargo.toml schema.
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.
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.
If you decide to do that, I'd suggest separating the version of the standard library from the version of the language.
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.
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.
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
- Specifying experimental language features
- Getting them implemented in independent implementations
- Iterating until the design is "ready"
- Include the language feature in a language version
- Implementations declare that they support that version
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.
One concern is that your proposal may break old versions of Cargo---Cargo only ignores certain unexpected keys, and mainly on the top level.
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 tool:cargo or tool:rustc, and you actually require that dependency, Cargo will say that it couldn't find that crate; if you don't actually require that dependency, such as for a non-default named feature, Cargo will ignore it and continue. That seems like the correct behavior.
If the field is absent, we assume the package is written in Rust 1.0.
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.
eternaleye Substitute OpenGL version for Rust version, and extensions for language #[feature] flags that have been stabilized.
eternaleye Personally, I'd favor rust = "version" overloaded with rust = { feature1 = stable, feature2 = stable, feature3 = * }
Ericson2314 that makes sense
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 extensions field in the Cabal file.
This is an alternative to #1707 . I also plan to write an RFC covering the "Cargo.toml", but the implementation for tha 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