Keeping around unstable features until their replacements hit stable

I hit an interesting issue recently; in a crate I maintain, we have a cargo feature which enables and uses the unstable external_doc feature so that docs.rs can load doc comments from a README.md. This works because docs.rs runs against nightly.

This feature got removed because a replacement got stabilised. This is great - the stabilised feature is excellent, and a very clean answer to the problem. I'm looking forward to deleting our old code and using the new form.

However, the replacement uses syntax which was not previously accepted by the parser, and so cannot be conditionally enabled (i.e. we cannot #![cfg_attr(feature = "external_doc", doc = include_str!("../README.md"))]). Worse than that, the code we want to conditionally enable is in an inner attribute, so we can't do something sneaky like conditionally load a file containing the inner attribute depending on compiler version.

This puts us in a slightly tricky position. As things currently stand, I don't think we can reasonably release new versions of the crate until after the next stable release. The old way has been removed, so if we release our existing code, docs.rs will fail to generate documentation for our crate - this is unfortunate. If we replace the old way with the new one, our crate won't compile on stable, because the replacement feature is currently only on beta - this is a hard blocker. There are hacks we can perform, but they're definitely hacks.

You could argue that we made this mess for ourselves by choosing to pull in an unstable feature, but it feels like it would perhaps be considerate in the future to delay removing features until the replacement hits stable, rather than just blocking on getting merged into nightly - at least where this doesn't pose significant problems for the implementation. Could we perhaps aim for this as a best-effort guideline?

(In the mean time, I'd love it if we reverted the feature removal and re-landed it in three weeks time when 1.54.0 hits stable...)

2 Likes

Just to confirm, are you saying that you're not looking to use the nightly feature on older nightly versions, but you need to support both nightly and stable (with nightly features enabled only on nightly), and the nature of this change is that you can't use conditional compilation for it?

Exactly so.

I'm comfortable with feature deletion meaning that future versions of nightly won't support old versions of my crate, and future versions of my crate won't support old versions of nightly - that's a very reasonable result of using nightly. It's just the lack of an overlap window that I'm finding problematic.

1 Like

You can use -Zcrate-attr to inject the #![doc] attribute only on docs.rs I think.

You can use the new attribute conditionally:


#![cfg_attr(feature = "doc", feature(extended_key_value_attributes))]
#![cfg_attr(feature = "doc", cfg_attr(all(), doc = include_str!("../README.md")))]
3 Likes

This would be lovely - do you know if crate-attr is documented anywhere? Unfortunately I couldn't find it...

Ooh, fantastic - I didn't realise you could do a double-layer of cfg_attr to stop the parser eagerly evaluating it. This indeed solves my issue in this instance, thanks!