Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

subscriber: make boxed subscribers not useless #2023

Merged
merged 5 commits into from
Mar 25, 2022
Merged

subscriber: make boxed subscribers not useless #2023

merged 5 commits into from
Mar 25, 2022

Conversation

hawkw
Copy link
Member

@hawkw hawkw commented Mar 25, 2022

Motivation

Currently, there is an impl<C: Collect> Subscribe for Box<dyn Subscribe<C>> intended to allow type-erasing a subscriber.
Unfortunately, however, this impl is...completely and utterly useless.

In order to be set as the default, a collector must be Send + Sync + 'static. Because the boxed trait object does not bound the subscriber
with these traits, adding a boxed subscriber to a collector will make
that collector impossible to use. This means that a Box<dyn Subscribe<C>> has no practical purpose whatsoever.

Solution

This branch adds an impl<C: Collect> for Box<dyn Subscribe<C> + Send + Sync + 'static>, and removes the useless impl.

In addition, I've improved the documentation on runtime configuration of
subscribers to include an example of using Box to type-erase a
subscriber. This is, incidentally, how I found out that using Boxed
subscribers is currently useless.

Notes

  • When this change is backported to v0.1.x, we'll have to un-delete the
    useless impl for Box<dyn Layer<S>>, as removing it is technically a
    breaking change. But, no one is actually using that impl for any
    practical purpose, since they...can't.

  • We may want to just add a Self: Send + Sync + 'static bound to the
    Subscribe trait, too; this would make it much easier to avoid this
    kind of issue in the future. But, that's a breaking change that can't
    easily be backported to v0.1.x

this moves the "runtime configuration with subscribers" section into a
subsection of "composing subscribers".

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
@hawkw hawkw self-assigned this Mar 25, 2022
@hawkw hawkw requested review from davidbarsky and a team as code owners March 25, 2022 18:18
@hawkw hawkw enabled auto-merge (squash) March 25, 2022 18:20
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
@hawkw hawkw merged commit afdad8f into master Mar 25, 2022
@hawkw hawkw deleted the eliza/fix-box branch March 25, 2022 18:38
hawkw added a commit that referenced this pull request Mar 25, 2022
Depends on #2023 

## Motivation

Currently, `FmtSubscriber` holds a `PhantomData<C>` with the `Collect`
type it wraps. This is unfortunate because it means that the
subscriber's auto traits such as `Send`, `Sync`, and `'static` (as well
as `UnwindSafe`, `Unpin`, etc) depend on the collector type's auto
traits...but the subscriber will never actually _store_ a value of type
`C`. While all collectors will be `Send + Sync + 'static` in practice,
the `PhantomData` means that functions returning a boxed `FmtSubscriber`
must unnecessarily bound the collector type parameter.

## Solution

This commit changes the `PhantomData` to `PhantomData<fn(C)>`, solving
the problem.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit that referenced this pull request Mar 25, 2022
## Motivation

PR #2023 made the `impl Subscribe` for boxed `dyn Subscribe` trait
objects actually be useful. One minor annoyance when working with boxed
trait objects is that, in some cases, in order to use `Box::new` to
erase a subscriber's type, it's necessary to add a type annotation like
this:
```rust
let boxed_subscriber: Box<dyn Subscribe<_> + Send + Sync + 'static>
    = Box::new(some_subscriber);
```

Because the trait object includes `Send + Sync + 'static`, this is a bit
wordy to type out.

## Solution

This commit adds a `Subscribe::boxed` method that takes `Self` and boxes
it as a type-erased `dyn Subscribe` trait object. This can then be
chained after a a chain of subscriber builder methods. Because the
`boxed` method _explicitly_ returns a `dyn Subscribe + ...` trait
object, it's not necessary to use a wordy type annotation when
using this method.
hawkw added a commit that referenced this pull request Mar 26, 2022
## Motivation

PR #2023 made the `impl Subscribe` for boxed `dyn Subscribe` trait
objects actually be useful. One minor annoyance when working with boxed
trait objects is that, in some cases, in order to use `Box::new` to
erase a subscriber's type, it's necessary to add a type annotation like
this:
```rust
let boxed_subscriber: Box<dyn Subscribe<_> + Send + Sync + 'static>
    = Box::new(some_subscriber);
```

Because the trait object includes `Send + Sync + 'static`, this is a bit
wordy to type out.

## Solution

This commit adds a `Subscribe::boxed` method that takes `Self` and boxes
it as a type-erased `dyn Subscribe` trait object. This can then be
chained after a a chain of subscriber builder methods. Because the
`boxed` method _explicitly_ returns a `dyn Subscribe + ...` trait
object, it's not necessary to use a wordy type annotation when
using this method.
hawkw added a commit that referenced this pull request Mar 29, 2022
Currently, there is an `impl<S: Subscriber> Layer for Box<dyn
Layer<S> + Send + Sync>` intended to allow type-erasing a subscriber.
This change improves the documentation on runtime configuration of
layers to include an example of using `Box` to type-erase a
layer.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit that referenced this pull request Mar 29, 2022
Depends on #2023

## Motivation

Currently, `FmtLayer` holds a `PhantomData<S>` with the `Subscriber`
type it wraps. This is unfortunate because it means that the
layer's auto traits such as `Send`, `Sync`, and `'static` (as well
as `UnwindSafe`, `Unpin`, etc) depend on the `Subscriber` type's auto
traits...but the layer will never actually _store_ a value of type
`S`. While all `Subscriber` will be `Send + Sync + 'static` in practice,
the `PhantomData` means that functions returning a boxed `FmtLayer`
must unnecessarily bound the subscriber type parameter.

## Solution

This commit changes the `PhantomData` to `PhantomData<fn(S)>`, solving
the problem.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit that referenced this pull request Mar 29, 2022
## Motivation

PR #2023 made the `impl Layer` for boxed `dyn Layer` trait
objects actually be useful. One minor annoyance when working with boxed
trait objects is that, in some cases, in order to use `Box::new` to
erase a `Layer`'s type, it's necessary to add a type annotation like
this:
```rust
let boxed_layer: Box<dyn Layer<_> + Send + Sync + 'static>
    = Box::new(some_layer);
```

Because the trait object includes `Send + Sync + 'static`, this is a bit
wordy to type out.

## Solution

This commit adds a `Layer::boxed` method that takes `Self` and boxes
it as a type-erased `dyn Layer` trait object. This can then be
chained after a a chain of layer builder methods. Because the
`boxed` method _explicitly_ returns a `dyn Layer<_> + ...` trait
object, it's not necessary to use a wordy type annotation when
using this method.
hawkw added a commit that referenced this pull request Mar 29, 2022
Currently, there is an `impl<S: Subscriber> Layer for Box<dyn
Layer<S> + Send + Sync>` intended to allow type-erasing a subscriber.
This change improves the documentation on runtime configuration of
layers to include an example of using `Box` to type-erase a
layer.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit that referenced this pull request Mar 29, 2022
Depends on #2023

## Motivation

Currently, `FmtLayer` holds a `PhantomData<S>` with the `Subscriber`
type it wraps. This is unfortunate because it means that the
layer's auto traits such as `Send`, `Sync`, and `'static` (as well
as `UnwindSafe`, `Unpin`, etc) depend on the `Subscriber` type's auto
traits...but the layer will never actually _store_ a value of type
`S`. While all `Subscriber` will be `Send + Sync + 'static` in practice,
the `PhantomData` means that functions returning a boxed `FmtLayer`
must unnecessarily bound the subscriber type parameter.

## Solution

This commit changes the `PhantomData` to `PhantomData<fn(S)>`, solving
the problem.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit that referenced this pull request Mar 29, 2022
## Motivation

PR #2023 made the `impl Layer` for boxed `dyn Layer` trait
objects actually be useful. One minor annoyance when working with boxed
trait objects is that, in some cases, in order to use `Box::new` to
erase a `Layer`'s type, it's necessary to add a type annotation like
this:
```rust
let boxed_layer: Box<dyn Layer<_> + Send + Sync + 'static>
    = Box::new(some_layer);
```

Because the trait object includes `Send + Sync + 'static`, this is a bit
wordy to type out.

## Solution

This commit adds a `Layer::boxed` method that takes `Self` and boxes
it as a type-erased `dyn Layer` trait object. This can then be
chained after a a chain of layer builder methods. Because the
`boxed` method _explicitly_ returns a `dyn Layer<_> + ...` trait
object, it's not necessary to use a wordy type annotation when
using this method.
hawkw added a commit that referenced this pull request Apr 1, 2022
# 0.3.10 (Apr 1, 2022)

This release adds several new features, including a `Filter`
implementation and new builder API for `EnvFilter`, support for using a
`Vec<L> where L: Layer` as a `Layer`, and a number of smaller API
improvements to make working with dynamic and reloadable layers easier.

### Added

- **registry**: Implement `Filter` for `EnvFilter`, allowing it to be
  used with per-layer filtering ([#1983])
  - **registry**: `Filter::on_new_span`, `Filter::on_enter`,
  `Filter::on_exit`, `Filter::on_close` and `Filter::on_record`
  callbacks to allow `Filter`s to track span states internally ([#1973],
  [#2017], [#2031])
- **registry**: `Filtered::filter` and `Filtered::filter_mut` accessors
  ([#1959])
- **registry**: `Filtered::inner` and `Filtered::inner_mut` accessors to
  borrow the wrapped `Layer` ([#2034])
- **layer**: Implement `Layer` for `Vec<L: Layer>`, to allow composing
  together a dynamically sized list of `Layer`s ([#2027])
- **layer**: `Layer::boxed` method to make type-erasing `Layer`s easier
  ([#2026])
- **fmt**: `fmt::Layer::writer` and `fmt::Layer::writer_mut` accessors
  ([#2034])
- **fmt**: `fmt::Layer::set_ansi` method to allow changing the ANSI
  formatting configuration at runtime ([#2034])
- **env-filter**: `EnvFilter::builder` to configure a new `EnvFilter`
  prior to parsing it ([#2035])
- Several documentation fixes and improvements ([#1972], [#1971],
  [#2023], [#2023])

### Fixed

- **fmt**: `fmt::Layer`'s auto traits no longer depend on the
  `Subscriber` type parameter's auto traits ([2025])
- **env-filter**: Fixed missing help text when the `ansi` feature is
  disabled ([#2029])

Thanks to new contributors @TimoFreiberg and @wagenet, as well as @CAD97
for contributing to this release!

[#1983]: #1983
[#1973]: #1973
[#2017]: #2017
[#2031]: #2031
[#1959]: #1959
[#2034]: #2034
[#2027]: #2027
[#2026]: #2026
[#2035]: #2035
[#1972]: #1972
[#1971]: #1971
[#2023]: #2023
hawkw added a commit that referenced this pull request Apr 1, 2022
# 0.3.10 (Apr 1, 2022)

This release adds several new features, including a `Filter`
implementation and new builder API for `EnvFilter`, support for using a
`Vec<L> where L: Layer` as a `Layer`, and a number of smaller API
improvements to make working with dynamic and reloadable layers easier.

### Added

- **registry**: Implement `Filter` for `EnvFilter`, allowing it to be
  used with per-layer filtering ([#1983])
  - **registry**: `Filter::on_new_span`, `Filter::on_enter`,
  `Filter::on_exit`, `Filter::on_close` and `Filter::on_record`
  callbacks to allow `Filter`s to track span states internally ([#1973],
  [#2017], [#2031])
- **registry**: `Filtered::filter` and `Filtered::filter_mut` accessors
  ([#1959])
- **registry**: `Filtered::inner` and `Filtered::inner_mut` accessors to
  borrow the wrapped `Layer` ([#2034])
- **layer**: Implement `Layer` for `Vec<L: Layer>`, to allow composing
  together a dynamically sized list of `Layer`s ([#2027])
- **layer**: `Layer::boxed` method to make type-erasing `Layer`s easier
  ([#2026])
- **fmt**: `fmt::Layer::writer` and `fmt::Layer::writer_mut` accessors
  ([#2034])
- **fmt**: `fmt::Layer::set_ansi` method to allow changing the ANSI
  formatting configuration at runtime ([#2034])
- **env-filter**: `EnvFilter::builder` to configure a new `EnvFilter`
  prior to parsing it ([#2035])
- Several documentation fixes and improvements ([#1972], [#1971],
  [#2023], [#2023])

### Fixed

- **fmt**: `fmt::Layer`'s auto traits no longer depend on the
  `Subscriber` type parameter's auto traits ([2025])
- **env-filter**: Fixed missing help text when the `ansi` feature is
  disabled ([#2029])

Thanks to new contributors @TimoFreiberg and @wagenet, as well as @CAD97
for contributing to this release!

[#1983]: #1983
[#1973]: #1973
[#2017]: #2017
[#2031]: #2031
[#1959]: #1959
[#2034]: #2034
[#2027]: #2027
[#2026]: #2026
[#2035]: #2035
[#1972]: #1972
[#1971]: #1971
[#2023]: #2023
hawkw added a commit that referenced this pull request Apr 1, 2022
# 0.3.10 (Apr 1, 2022)

This release adds several new features, including a `Filter`
implementation and new builder API for `EnvFilter`, support for using a
`Vec<L> where L: Layer` as a `Layer`, and a number of smaller API
improvements to make working with dynamic and reloadable layers easier.

### Added

- **registry**: Implement `Filter` for `EnvFilter`, allowing it to be
  used with per-layer filtering ([#1983])
  - **registry**: `Filter::on_new_span`, `Filter::on_enter`,
  `Filter::on_exit`, `Filter::on_close` and `Filter::on_record`
  callbacks to allow `Filter`s to track span states internally ([#1973],
  [#2017], [#2031])
- **registry**: `Filtered::filter` and `Filtered::filter_mut` accessors
  ([#1959])
- **registry**: `Filtered::inner` and `Filtered::inner_mut` accessors to
  borrow the wrapped `Layer` ([#2034])
- **layer**: Implement `Layer` for `Vec<L: Layer>`, to allow composing
  together a dynamically sized list of `Layer`s ([#2027])
- **layer**: `Layer::boxed` method to make type-erasing `Layer`s easier
  ([#2026])
- **fmt**: `fmt::Layer::writer` and `fmt::Layer::writer_mut` accessors
  ([#2034])
- **fmt**: `fmt::Layer::set_ansi` method to allow changing the ANSI
  formatting configuration at runtime ([#2034])
- **env-filter**: `EnvFilter::builder` to configure a new `EnvFilter`
  prior to parsing it ([#2035])
- Several documentation fixes and improvements ([#1972], [#1971],
  [#2023], [#2023])

### Fixed

- **fmt**: `fmt::Layer`'s auto traits no longer depend on the
  `Subscriber` type parameter's auto traits ([2025])
- **env-filter**: Fixed missing help text when the `ansi` feature is
  disabled ([#2029])

Thanks to new contributors @TimoFreiberg and @wagenet, as well as @CAD97
for contributing to this release!

[#1983]: #1983
[#1973]: #1973
[#2017]: #2017
[#2031]: #2031
[#1959]: #1959
[#2034]: #2034
[#2027]: #2027
[#2026]: #2026
[#2035]: #2035
[#1972]: #1972
[#1971]: #1971
[#2023]: #2023
hawkw added a commit that referenced this pull request Apr 1, 2022
# 0.3.10 (Apr 1, 2022)

This release adds several new features, including a `Filter`
implementation and new builder API for `EnvFilter`, support for using a
`Vec<L> where L: Layer` as a `Layer`, and a number of smaller API
improvements to make working with dynamic and reloadable layers easier.

### Added

- **registry**: Implement `Filter` for `EnvFilter`, allowing it to be
  used with per-layer filtering ([#1983])
  - **registry**: `Filter::on_new_span`, `Filter::on_enter`,
  `Filter::on_exit`, `Filter::on_close` and `Filter::on_record`
  callbacks to allow `Filter`s to track span states internally ([#1973],
  [#2017], [#2031])
- **registry**: `Filtered::filter` and `Filtered::filter_mut` accessors
  ([#1959])
- **registry**: `Filtered::inner` and `Filtered::inner_mut` accessors to
  borrow the wrapped `Layer` ([#2034])
- **layer**: Implement `Layer` for `Vec<L: Layer>`, to allow composing
  together a dynamically sized list of `Layer`s ([#2027])
- **layer**: `Layer::boxed` method to make type-erasing `Layer`s easier
  ([#2026])
- **fmt**: `fmt::Layer::writer` and `fmt::Layer::writer_mut` accessors
  ([#2034])
- **fmt**: `fmt::Layer::set_ansi` method to allow changing the ANSI
  formatting configuration at runtime ([#2034])
- **env-filter**: `EnvFilter::builder` to configure a new `EnvFilter`
  prior to parsing it ([#2035])
- Several documentation fixes and improvements ([#1972], [#1971],
  [#2023], [#2023])

### Fixed

- **fmt**: `fmt::Layer`'s auto traits no longer depend on the
  `Subscriber` type parameter's auto traits ([2025])
- **env-filter**: Fixed missing help text when the `ansi` feature is
  disabled ([#2029])

Thanks to new contributors @TimoFreiberg and @wagenet, as well as @CAD97
for contributing to this release!

[#1983]: #1983
[#1973]: #1973
[#2017]: #2017
[#2031]: #2031
[#1959]: #1959
[#2034]: #2034
[#2027]: #2027
[#2026]: #2026
[#2035]: #2035
[#1972]: #1972
[#1971]: #1971
[#2023]: #2023
hawkw added a commit that referenced this pull request Apr 1, 2022
# 0.3.10 (Apr 1, 2022)

This release adds several new features, including a `Filter`
implementation and new builder API for `EnvFilter`, support for using a
`Vec<L> where L: Layer` as a `Layer`, and a number of smaller API
improvements to make working with dynamic and reloadable layers easier.

### Added

- **registry**: Implement `Filter` for `EnvFilter`, allowing it to be
  used with per-layer filtering ([#1983])
- **registry**: `Filter::on_new_span`, `Filter::on_enter`,
  `Filter::on_exit`, `Filter::on_close` and `Filter::on_record`
  callbacks to allow `Filter`s to track span states internally ([#1973],
  [#2017], [#2031])
- **registry**: `Filtered::filter` and `Filtered::filter_mut` accessors
  ([#1959])
- **registry**: `Filtered::inner` and `Filtered::inner_mut` accessors to
  borrow the wrapped `Layer` ([#2034])
- **layer**: Implement `Layer` for `Vec<L: Layer>`, to allow composing
  together a dynamically sized list of `Layer`s ([#2027])
- **layer**: `Layer::boxed` method to make type-erasing `Layer`s easier
  ([#2026])
- **fmt**: `fmt::Layer::writer` and `fmt::Layer::writer_mut` accessors
  ([#2034])
- **fmt**: `fmt::Layer::set_ansi` method to allow changing the ANSI
  formatting configuration at runtime ([#2034])
- **env-filter**: `EnvFilter::builder` to configure a new `EnvFilter`
  prior to parsing it ([#2035])
- Several documentation fixes and improvements ([#1972], [#1971],
  [#2023], [#2023])

### Fixed

- **fmt**: `fmt::Layer`'s auto traits no longer depend on the
  `Subscriber` type parameter's auto traits ([#2025])
- **env-filter**: Fixed missing help text when the `ansi` feature is
  disabled ([#2029])

Thanks to new contributors @TimoFreiberg and @wagenet, as well as @CAD97
for contributing to this release!

[#1983]: #1983
[#1973]: #1973
[#2017]: #2017
[#2031]: #2031
[#1959]: #1959
[#2034]: #2034
[#2027]: #2027
[#2026]: #2026
[#2035]: #2035
[#1972]: #1972
[#1971]: #1971
[#2023]: #2023
[#2025]: #2025
[#2029]: #2029
kaffarell pushed a commit to kaffarell/tracing that referenced this pull request May 22, 2024
Currently, there is an `impl<S: Subscriber> Layer for Box<dyn
Layer<S> + Send + Sync>` intended to allow type-erasing a subscriber.
This change improves the documentation on runtime configuration of
layers to include an example of using `Box` to type-erase a
layer.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
kaffarell pushed a commit to kaffarell/tracing that referenced this pull request May 22, 2024
)

Depends on tokio-rs#2023

## Motivation

Currently, `FmtLayer` holds a `PhantomData<S>` with the `Subscriber`
type it wraps. This is unfortunate because it means that the
layer's auto traits such as `Send`, `Sync`, and `'static` (as well
as `UnwindSafe`, `Unpin`, etc) depend on the `Subscriber` type's auto
traits...but the layer will never actually _store_ a value of type
`S`. While all `Subscriber` will be `Send + Sync + 'static` in practice,
the `PhantomData` means that functions returning a boxed `FmtLayer`
must unnecessarily bound the subscriber type parameter.

## Solution

This commit changes the `PhantomData` to `PhantomData<fn(S)>`, solving
the problem.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
kaffarell pushed a commit to kaffarell/tracing that referenced this pull request May 22, 2024
## Motivation

PR tokio-rs#2023 made the `impl Layer` for boxed `dyn Layer` trait
objects actually be useful. One minor annoyance when working with boxed
trait objects is that, in some cases, in order to use `Box::new` to
erase a `Layer`'s type, it's necessary to add a type annotation like
this:
```rust
let boxed_layer: Box<dyn Layer<_> + Send + Sync + 'static>
    = Box::new(some_layer);
```

Because the trait object includes `Send + Sync + 'static`, this is a bit
wordy to type out.

## Solution

This commit adds a `Layer::boxed` method that takes `Self` and boxes
it as a type-erased `dyn Layer` trait object. This can then be
chained after a a chain of layer builder methods. Because the
`boxed` method _explicitly_ returns a `dyn Layer<_> + ...` trait
object, it's not necessary to use a wordy type annotation when
using this method.
kaffarell pushed a commit to kaffarell/tracing that referenced this pull request May 22, 2024
# 0.3.10 (Apr 1, 2022)

This release adds several new features, including a `Filter`
implementation and new builder API for `EnvFilter`, support for using a
`Vec<L> where L: Layer` as a `Layer`, and a number of smaller API
improvements to make working with dynamic and reloadable layers easier.

### Added

- **registry**: Implement `Filter` for `EnvFilter`, allowing it to be
  used with per-layer filtering ([tokio-rs#1983])
- **registry**: `Filter::on_new_span`, `Filter::on_enter`,
  `Filter::on_exit`, `Filter::on_close` and `Filter::on_record`
  callbacks to allow `Filter`s to track span states internally ([tokio-rs#1973],
  [tokio-rs#2017], [tokio-rs#2031])
- **registry**: `Filtered::filter` and `Filtered::filter_mut` accessors
  ([tokio-rs#1959])
- **registry**: `Filtered::inner` and `Filtered::inner_mut` accessors to
  borrow the wrapped `Layer` ([tokio-rs#2034])
- **layer**: Implement `Layer` for `Vec<L: Layer>`, to allow composing
  together a dynamically sized list of `Layer`s ([tokio-rs#2027])
- **layer**: `Layer::boxed` method to make type-erasing `Layer`s easier
  ([tokio-rs#2026])
- **fmt**: `fmt::Layer::writer` and `fmt::Layer::writer_mut` accessors
  ([tokio-rs#2034])
- **fmt**: `fmt::Layer::set_ansi` method to allow changing the ANSI
  formatting configuration at runtime ([tokio-rs#2034])
- **env-filter**: `EnvFilter::builder` to configure a new `EnvFilter`
  prior to parsing it ([tokio-rs#2035])
- Several documentation fixes and improvements ([tokio-rs#1972], [tokio-rs#1971],
  [tokio-rs#2023], [tokio-rs#2023])

### Fixed

- **fmt**: `fmt::Layer`'s auto traits no longer depend on the
  `Subscriber` type parameter's auto traits ([tokio-rs#2025])
- **env-filter**: Fixed missing help text when the `ansi` feature is
  disabled ([tokio-rs#2029])

Thanks to new contributors @TimoFreiberg and @wagenet, as well as @CAD97
for contributing to this release!

[tokio-rs#1983]: tokio-rs#1983
[tokio-rs#1973]: tokio-rs#1973
[tokio-rs#2017]: tokio-rs#2017
[tokio-rs#2031]: tokio-rs#2031
[tokio-rs#1959]: tokio-rs#1959
[tokio-rs#2034]: tokio-rs#2034
[tokio-rs#2027]: tokio-rs#2027
[tokio-rs#2026]: tokio-rs#2026
[tokio-rs#2035]: tokio-rs#2035
[tokio-rs#1972]: tokio-rs#1972
[tokio-rs#1971]: tokio-rs#1971
[tokio-rs#2023]: tokio-rs#2023
[tokio-rs#2025]: tokio-rs#2025
[tokio-rs#2029]: tokio-rs#2029
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants