instability/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
//! This crate provides attribute macros for specifying API stability of public API items of a
//! crate.
//!
//! The Rust standard library has a concept of [API stability] and custom attributes for managing
//! that on a per-item basis, but most of these attributes are not available for normal crates to
//! use, with the exception of the [`deprecated`] attribute. This crate seeks to provide similar
//! attributes on stable Rust, though tuned more toward what the needs of normal crate authors.
//!
//! For complete examples of how to use this crate, check out the source code for the
//! [`instability-example`] crate in the repository
//!
//! Currently, only the [`unstable`] attribute is available. Please see the documentation of that
//! macro for an explanation on what it does and how to use it.
//!
//! [API stability]: https://rustc-dev-guide.rust-lang.org/stability.html
//! [`deprecated`]:
//!     https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute
//! [`instability-example`]: https://github.com/ratatui-org/instability/tree/main/example
//! [`unstable`]: macro@unstable

use proc_macro::TokenStream;
use stable::stable_macro;
use unstable::unstable_macro;

mod item_like;
mod stable;
mod unstable;

/// Mark an API as unstable.
///
/// You can apply this attribute to an item in your public API that you would like to expose to
/// users, but are not yet ready for general use. This is useful when you want to let users try out
/// some new functionality for an API you haven't finished testing or designing, or for whatever
/// reason do not want to commit any stability guarantees for.
///
/// This attribute does the following things to annotated items:
///
/// - Changes the visibility of the item from `pub` to `pub(crate)` unless a certain crate feature
///   is enabled. This ensures that internal code within the crate can always use the item, but
///   downstream consumers cannot access it unless they opt-in to the unstable API.
/// - Annotated `impl` blocks will instead be removed.
/// - Changes the Visibility of certain child items of the annotated item (such as struct fields) to
///   match the item's visibility. Children that are not public will not be affected.
/// - Appends an "Stability" section to the item's documentation that notes that the item is
///   unstable and indicates the name of the crate feature to enable it.
///
/// Child items of annotated modules are unchanged, as it might be desirable to be able to re-export
/// them even if the module visibility is restricted. You should apply the attribute to each item
/// within the module with the same feature name if you want to restrict the module's contents
/// itself and not just the module namespace.
///
/// Note that unlike the [`unstable`][std-unstable] attribute used in the standard library, this
/// attribute does not apply itself recursively to child items.
///
/// [std-unstable]: https://rustc-dev-guide.rust-lang.org/stability.html
///
/// Applying this attribute to non-`pub` items is pointless and does nothing.
///
/// # Arguments
///
/// The `unstable` attribute supports optional arguments that can be passed to control its behavior.
///
/// - `feature`: the name of the unstable feature that should control this item's availability. This
///   will have the string `unstable-` prepended to it. If not specified, the item will instead be
///   guarded by a catch-all `unstable` feature.
/// - `issue`: a link or reference to a tracking issue for the unstable feature. This will be
///   included in the item's documentation.
///
/// # Examples
///
/// We can apply the attribute to a public function like so:
///
/// ```
/// /// This function does something really risky!
/// ///
/// /// Don't use it yet!
/// #[instability::unstable(feature = "risky-function")]
/// pub fn risky_function() {
///     unimplemented!()
/// }
/// ```
///
/// This will essentially be expanded to the following:
///
/// ```
/// /// This function does something really risky!
/// ///
/// /// Don't use it yet!
/// ///
/// /// # Availability
/// ///
/// /// **This API is marked as unstable** and is only available when the `unstable-risky-function`
/// /// crate feature is enabled. This comes with no stability guarantees, and could be changed or
/// /// removed at any time.
/// #[cfg(feature = "unstable-risky-function")]
/// pub fn risky_function() {
///     unimplemented!()
/// }
///
/// /// This function does something really risky!
/// ///
/// /// Don't use it yet!
/// #[cfg(not(feature = "unstable-risky-function"))]
/// pub(crate) fn risky_function() {
///     unimplemented!()
/// }
/// ```
///
/// We can also apply the attribute to an `impl` block like so:
///
/// ```
/// /// This structure is responsible for bar.
/// pub struct Foo;
///
/// #[instability::unstable(feature = "unstable-dependency")]
/// impl Default for Foo {
///     fn default() -> Self {
///         unimplemented!()
///     }
/// }
/// ```
#[proc_macro_attribute]
pub fn unstable(args: TokenStream, input: TokenStream) -> TokenStream {
    unstable_macro(args.into(), input.into()).into()
}

/// Mark an API as stable.
///
/// You can apply this attribute to an item in your public API that you would like to expose to
/// users, and are ready to make a stability guarantee for. This is useful when you have finished
/// testing and designing an API and are ready to commit to its design and stability.
///
/// This attribute does the following things to annotated items:
///
/// - Appends a "Stability" section to the item's documentation that notes that the item is stable
///   and indicates the version at which it was stabilized.
///
/// # Arguments
///
/// The `stable` attribute supports optional arguments that can be passed to control its behavior.
///
/// - `since`: the version at which the item was stabilized. This should be a string that follows
///   the [Semantic Versioning](https://semver.org) convention. If not specified, the item will be
///   marked as stable with no version information.
/// - `issue`: a link or reference to a tracking issue for the stabilized feature. This will be
///   included in the item's documentation.
///
/// # Examples
///
/// We can apply the attribute to a public function like so:
///
/// ```
/// /// This function does something really risky!
/// ///
/// /// Don't use it yet!
/// #[instability::stable(since = "v1.0.0")]
/// pub fn stable_function() {
///     unimplemented!()
/// }
/// ```
///
/// This will essentially be expanded to the following:
///
/// ```
/// /// This function does something really risky!
/// ///
/// /// Don't use it yet!
/// ///
/// /// # Stability
/// ///
/// /// This API was stabilized in version 1.0.0.
/// pub fn stable_function() {
///     unimplemented!()
/// }
/// ```
///
/// Applying this attribute to non-`pub` items is pointless and does nothing.
///
/// # Panics
///
/// This macro will panic if applied to an unsupported item type.
///
/// # Limitations
///
/// This attribute does not change the visibility of the annotated item. You should ensure that the
/// item's visibility is set to `pub` if you want it to be part of your crate's public API.
///
/// # See also
///
/// - The [`unstable`] attribute for marking an API as unstable.
///
/// [`unstable`]: macro@unstable
#[proc_macro_attribute]
pub fn stable(args: TokenStream, input: TokenStream) -> TokenStream {
    stable_macro(args.into(), input.into()).into()
}