# How to use #[unstable_feature_bound]
## Introduction
Previously, if we have a stable type ``StableType`` and stable trait ``StableTrait``, ``impl StableTrait for StableType`` will be instantly stable, and there is no way to mark the impl as unstable.
In [#140399](https://github.com/rust-lang/rust/pull/140399#issuecomment-3070894211), we started to provide a way to mark an impl as unstable through ``#[unstable_feature_bound(feature1, feature2,..)]``, for example:
```rust=
#![stable(feature = "a", since = "1.1.1" )]
#[stable(feature = "a", since = "1.1.1" )]
pub trait Foo {
#[stable(feature = "a", since = "1.1.1" )]
fn foo();
}
#[stable(feature = "a", since = "1.1.1" )]
pub struct Bar;
#[unstable_feature_bound(feat_bar)]
#[unstable(feature = "feat_bar", issue = "none" )]
impl Foo for Bar {
fn foo() {}
}
```
## Usage
``#[unstable_feature_bound]`` should be used together with ``#[unstable]``.
```rust=
#[unstable_feature_bound(feat_bar)]
#[unstable(feature = "feat_bar", issue = "none" )]
impl Foo for Bar {
fn foo() {}
}
```
Conceptually, ``#[unstable_feature_bound]`` is a where-clause, just like
```rust=
impl Foo for Bar
where unstable_feature_bound(feat_name) {}
```
If we are in std / core, ``#[unstable_feature_bound(feat_name)]`` is always required to use anything that is annotated with ``#[unstable_feature_bound(feat_name)]``.
Outside of std/core, any item annonated with ``#[unstable_feature_bound(feat_name)]`` in std / core will be treated like a normal unstable feature. Users just need to enable the feature through ``#![feature(feat_name)]`` to use the item.
**Usage example in std / core:**
```rust=
#![stable(feature = "a", since = "1.1.1" )]
#[stable(feature = "a", since = "1.1.1" )]
pub trait Foo {
#[stable(feature = "a", since = "1.1.1" )]
fn foo();
}
#[stable(feature = "a", since = "1.1.1" )]
pub struct Bar;
// If this impl is annotated with #[unstable_feature_bound(feat_bar)]...
#[unstable_feature_bound(feat_bar)]
#[unstable(feature = "feat_bar", issue = "none" )]
impl Foo for Bar {
fn foo() {}
}
// Then the same #[unstable_feature_bound(feat_bar)] is needed
// to use anything annonated with #[unstable_feature_bound(feat_bar)].
#[unstable_feature_bound(feat_bar)]
#[unstable(feature = "feat_bar", issue = "none" )]
fn bar() {
Bar::foo();
}
// The same rule also applies to `bar2`, since it uses `bar`.
#[unstable_feature_bound(feat_bar)]
#[unstable(feature = "feat_bar", issue = "none" )]
fn bar2() {
bar();
}
```
**Usage example outside of std / core**:
```rust=
// If we have the code below in std / core...
// ----- std / core ----------------------------------------
#![stable(feature = "a", since = "1.1.1" )]
#[stable(feature = "a", since = "1.1.1" )]
pub trait Foo {
#[stable(feature = "a", since = "1.1.1" )]
fn foo();
}
#[stable(feature = "a", since = "1.1.1" )]
pub struct Bar;
// If this impl is annotated with #[unstable_feature_bound(feat_bar)]...
#[unstable_feature_bound(feat_bar)]
#[unstable(feature = "feat_bar", issue = "none" )]
impl Foo for Bar {
fn foo() {}
}
// ----- std / core ----------------------------------------
//----- Outside of std / core ----------------------------
// Then the feature `feat_bar` should be enabled to use the impl.
#![feature(feat_bar)]
use std::{Foo, Bar}
fn main() {
Bar::foo();
}
//----- Outside of std / core ----------------------------
```
## Limitation
We do not support:
- Using ``#[unstable_feature_bound]`` within stable API. Once ``#[unstable_feature_bound]`` is used on an item, user will be required to enable the feature through ``#[feature]``, so using ``#[unstable_feature_bound]`` within stable API will essentially make the item unstable.
- Using ``#[unstable_feature_bound]`` on any item other than impls and free functions.
We plan to remove these limitations eventually.
## Some examples that are not allowed
```rust=
#[unstable_feature_bound(feat_bar)]
#[unstable(feature = "feat_foo", issue = "none" )]
impl Foo for Bar {
fn foo() {}
}
```
- the feature name in ``#[unstable]`` is not in ``#[unstable_feature_bound]``. In this case, the user is required to enable the feature through ``#![unstable(feat_bar)]`` instead of ``#![feature(feat_foo)]``.
```rust=
#![stable(feature = "a", since = "1.1.1" )]
#[stable(feature = "a", since = "1.1.1")]
#[unstable_feature_bound(feat_bar)]
fn bar() {}
```
- If an item is annotated with ``#[unstable_feature_bound]``, the user will be required to enable the feature through ``#![feature]``. So the item is essentially no longer stable.
The examples above will fail with error. If you think there are more cases that are confusing / should not be allowed, feel free to ping @tiif on github / zulip.