Pre-RFC: Deprecation for Everyone!

Following my failed target_version RFC, there is one idea I want to salvage: allowing non-lang items to be deprecated.

Currently, this feature is restricted to lang items APIs distributed with rustc, presumably because the since field refers to rust version, but I see no point where this is actually checked.

Lifting the restriction seems easy enough, and it would open smoother upgrade paths for library writers.

So is there any technical reason other than “we didn’t get around to it yet” to keep this limitation? I know that I see enough use cases, does it need an RFC (considering the feature is already there, albeit restricted to lang items)?

2 Likes

What do you mean by lang items here?

Do you mean libs shipped with rustc? (because lang items are something different)

Removing #![feature(staged_api)] sounds like an okay idea to me. @brson might have thoughts on whether this should be done.

This is hugely wanted. Deprecation allows libraries to sanely evolve their api. Unstable etc markers are not as important.

Yes, I mean libs shipped with rustc. I think this feature is mostly useful to library writers who currently can only document (and not even that in a canonical way) that a certain API is going to go away in the future.

Mind you, my own crate doesn’t yet need that feature – but I’m thinking about the future. We already have two lints in rust-clippy that can only be quitened by changing/renaming certain functions – but this means either somehow deprecating the old names or breaking users’ code.

I also think that stability should be a thing that libraries can be used, mostly because rustdoc reports on it, and it is strange that it is mostly just for rustc and the stdlib…

Yes, why not? Unless someone comes up with a compelling reason to restrict it to rust lib, let library authors use both features. I suspect that having the possibility may allow library authors more openness in advancing their APIs. If just one author can get feedback earlier, or needs less time to get rid of an API item that hinders further development, the time spent to remove the restriction will have been worth it.

I think adding #[deprecated] for users is a good idea, and one we intended to revisit when we restricted the stability attributes last year.

It does need a fresh pass over the design I think since the in-tree version is tailored to the project’s needs.

1 Like

What part of the design do you think needs revisiting? The attribute itself is pretty much done. I recently read a discussion about how the docs should show version information; this would make it easy to see how recent any deprecation is.

the in-tree version is tailored to the project's needs

I don't see why the needs of the standard library should be so different from other library crates. But I'm open to discuss the fine points of the design:

  • Attributes: #[deprecated(since="1.0.0", reason="I was sick of maintaining it")]and #[unstable(feature="moo", reason="Moo!", issue="12345")] (optional, let's get deprecation on track first)
  • values: versions should be semver (the docs should state this) to reduce room for error. I might add a lint to ensure this in clippy. reasons should be readable and to the point and will be part of the documentation.
  • Using marked APIs leads to a lint warning. I think we may want to cap the level to never become Deny, because I've seen a few projects where a #[deny(warnings)] broke the build. But I don't care too much – whoever does this deserves breakage.
  • rustdoc marks up both – I don't see a reason why we should change this

From a quick look at the code:

  • There are rules that required #[deprecated] to be paired with #[stable] or #[unstable]. These don't apply if we don't expose the latter attributes.
  • The parser appears to be lenient with what inner meta items #[deprecated] takes. In particular, it appears to accept feature and issue and do nothing with them. This isn't acceptable for a stable feature.
  • The meaning of since in-tree is specifically tied to language revisions. That doesn't make sense out of tree, and it should be specified what that version number means.

Thank you for this valuable input. Whoever wants to have a look, the source is in src/libsyntax/attrs.rs line 388 and following (this defines stability attributes and operations on them), as well as src/librustc_lint/builtin.rs, line 2060 and following (this is the lint against deprecated items).

I’ll try to have a more in-depth look at the code and set up an RFC once I find the time.

Edit: A few points from me:

  • The #[(un)stable] requirement for #[deprecated] could be added as a lint which would be set to Warn within the rust build and default to Allow The Stability::Level enum would need to get a Unspecified variant against which the aforementioned lint would check. This way we can ensure that stability is specified on all std items, and whoever wants to require this on their project can activate the lint
  • feature should be restricted to an actual feature flag – Cargo-based projects could check the Cargo.toml, while there should be a way to check this for non-Cargo projects like Rust and Servo.
  • issue is a documentation item, as far as I’m concerned. Perhaps a case could be made that this should either be a number (optionally prefixed with #) or a URL that points to the issue on some tracker. rustdoc could get an option to link this to the actual issue (along with a default issue tracker URL), which would be kinda neat
  • since outside of the rust distribution would refer to the version of the current crate, as set by cargo (presumably read via env!("CARGO_PKG_VERSION")), the rust build process can set this to the current rust version. I’m unsure if Servo needs something similar.

Update: I have written up an RFC here. @Manishearth @brson Do you think I should PR? Or do you see issues with the proposal?

I think the out-of-tree #[deprecated] form should not be visualised as just an extension of the in-tree one. We should regard that system as purely magic, or as if they were renamed rustc_{unstable,stable,deprecated}, so that they’re not tainting the design. E.g. that RFC talks about tweaking the implementation details of the current system, rather than describing the high level behaviour that we actually want from this system/giving examples.

One thing in particular: the behaviour of features in std I don’t think makes a lot of sense for external crates, but it seems you’re just adopting it wholesale (or at least, it’s not clear to me what the intention is)?

@llogiq @huon I agree that this RFC should basically pretend the existing system does not exist and should describe the feature from scratch. It will be clearer to other readers that way, without requiring them to understand the historical context. Perhaps some of the background details can be in their own (later) section.

You’re right, I was thinking in terms of implementing this stuff, when I should have taken a step back and design from a clean slate. I will update the RFC text accordingly.

Perhaps it’s best to reduce the publicly visible complexity and start with the #[deprecated] attribute, listing the other attributes under “Alternatives” for now. That will reduce the surface area and is also more easily motivated.

Edit: I’ve just rewritten the RFC text. @huon @brson better now?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.