Detect edition 2018 from cargo build.rs?


#1

I’m writing a code-generation library that is called from build.rs of projects using it (ructe, a webpage template language). In that, it would be nice to generate edition 2018-compatible code in crates that has enabled edition 2018, while still generating edition 2015-compatible code otherwise.

To make that easier, it would be very nice if cargo defined an edition variable RUST_EDITION (or something similiar), setting it to 2018 if edition 2018 is enabled and either setting it to 2015 or leaving it undefined otherwise.

I don’t see such a variable in the cargo book and I don’t find anything like it when I test with rustc 1.31.0-nightly (423d81098 2018-10-08). Has it been suggested earlier? Should it be implemented?

Otherwise, my library could of course find and parse the Cargo.toml of the user crate, but I think that seems more complicated than it should be.


#2

I’d encourage you to allow passing an argument to your code that specifies the edition, instead of intuiting it.

For the vast majority of cases, knowing the current edition is probably just not a good idea. Code generation is a reasonable case, I just don’t think it’s common enough to warrant the variable. I’d also be worried that people would misuse the variable for the “wrong” reasons, were it present.

What is an example of the kind of code that being generated which needs to change due to different editions?


#3

I havn’t really done anything with edition=2018 yet, so I’m not really sure what I need yet. One thing that seems incompatible is some local module paths I generate that apparently should start with crate:: in edition=2018 and not otherwise. But maybe I can fix those paths using self:: or super:: instead so I won’t need crate:: anyway? I’ll do some experimentation on that.

An argument in the build.rs call to ructe might be a good solution. But then I thought that it might be better to state it as a feature of the build-dependency, and then I thought that since the edition already is mentioned in Cargo.toml I shouldn’t require a duplication of it …


#4

This seems like you are enforcing the generated code to live at a specific location in the user’s hierarchy, which seems less-than-ideal. What if the user wants to call the code generation twice for different modules, or just wants to nest it a few levels deep as part of a larger project?


#5

Definitely not a feature, if there are multiple crates in the build tree depending on your crate, one of which is 2015 and one 2018, then the feature will be activated for both (features are always unioned).

An environment variable for the current build sounds fine to me, but also niche enough that just passing an additional parameter in the build.rs also sounds fine.

Technically it is supposed to be possible to generate only 2015 code and have that work on both 2015 and 2018. Features such as leading crate:: are required in 2018, but also supported in 2015. From RFC 2052:

code that compiles without warnings on the previous epoch (under the latest compiler release) will compile without errors on the next epoch

It’s only once there is a third edition that it will be necessary to generate different code for different editions (edition 2015 code would not be guaranteed to compile on edition 2022, but you could get away with just generating edition 2015 and edition 2018 and leave edition 2022 using the edition 2018 code). That said, you might want to use some 2018 only features if available, so having some way to know the current edition could still be useful.


#6

Yes, I managed to check the paths (using super:: instead of crate::) so the same generated code is compatible with both edition 2015 and 2018. Thank you @shepmaster!

So I won’t be doing any edition-detection or any kind of edition-selection parameter for now. But I can’t guarantee I won’t try again when I see an incompatible edition 2018 feature that I actually want to use.