#[must_use] all the things! (#1809)

This commit is contained in:
David Pedersen
2023-03-03 14:12:35 +01:00
committed by GitHub
parent 5a58edac16
commit 5606ea3f9e
26 changed files with 43 additions and 9 deletions
+3 -1
View File
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# Unreleased # Unreleased
- None. - **fixed:** Add `#[must_use]` attributes to types that do nothing unless used ([#1809])
[#1809]: https://github.com/tokio-rs/axum/pull/1809
# 0.3.2 (20. January, 2023) # 0.3.2 (20. January, 2023)
@@ -73,6 +73,7 @@ use tower_layer::Layer;
/// [`RequestExt::with_limited_body`]: crate::RequestExt::with_limited_body /// [`RequestExt::with_limited_body`]: crate::RequestExt::with_limited_body
/// [`RequestExt::into_limited_body`]: crate::RequestExt::into_limited_body /// [`RequestExt::into_limited_body`]: crate::RequestExt::into_limited_body
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[must_use]
pub struct DefaultBodyLimit { pub struct DefaultBodyLimit {
kind: DefaultBodyLimitKind, kind: DefaultBodyLimitKind,
} }
+1
View File
@@ -30,6 +30,7 @@ use std::fmt;
/// } /// }
/// ``` /// ```
#[derive(Debug)] #[derive(Debug)]
#[must_use]
pub struct AppendHeaders<I>(pub I); pub struct AppendHeaders<I>(pub I);
impl<I, K, V> IntoResponse for AppendHeaders<I> impl<I, K, V> IntoResponse for AppendHeaders<I>
+4 -2
View File
@@ -9,11 +9,13 @@ and this project adheres to [Semantic Versioning].
- **added:** Add `Multipart`. This is similar to `axum::extract::Multipart` - **added:** Add `Multipart`. This is similar to `axum::extract::Multipart`
except that it enforces field exclusivity at runtime instead of compile time, except that it enforces field exclusivity at runtime instead of compile time,
as this improves usability. as this improves usability ([#1692])
- **added:** Implement `Clone` for `CookieJar`, `PrivateCookieJar` and `SignedCookieJar` ([#1808]) - **added:** Implement `Clone` for `CookieJar`, `PrivateCookieJar` and `SignedCookieJar` ([#1808])
- **fixed:** Add `#[must_use]` attributes to types that do nothing unless used ([#1809])
[#1692]: https://github.com/tokio-rs/axum/pull/1692
[#1808]: https://github.com/tokio-rs/axum/pull/1808 [#1808]: https://github.com/tokio-rs/axum/pull/1808
[#1809]: https://github.com/tokio-rs/axum/pull/1809
# 0.6.0 (24. February, 2022) # 0.6.0 (24. February, 2022)
+1
View File
@@ -46,6 +46,7 @@ pin_project! {
/// ``` /// ```
#[cfg(feature = "async-read-body")] #[cfg(feature = "async-read-body")]
#[derive(Debug)] #[derive(Debug)]
#[must_use]
pub struct AsyncReadBody<R> { pub struct AsyncReadBody<R> {
#[pin] #[pin]
read: StreamBody<ReaderStream<R>>, read: StreamBody<ReaderStream<R>>,
+7
View File
@@ -108,6 +108,7 @@ use tower_service::Service;
/// ///
/// See the [module docs](self) for examples. /// See the [module docs](self) for examples.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[must_use]
pub enum Either<E1, E2> { pub enum Either<E1, E2> {
#[allow(missing_docs)] #[allow(missing_docs)]
E1(E1), E1(E1),
@@ -119,6 +120,7 @@ pub enum Either<E1, E2> {
/// ///
/// See the [module docs](self) for examples. /// See the [module docs](self) for examples.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[must_use]
pub enum Either3<E1, E2, E3> { pub enum Either3<E1, E2, E3> {
#[allow(missing_docs)] #[allow(missing_docs)]
E1(E1), E1(E1),
@@ -132,6 +134,7 @@ pub enum Either3<E1, E2, E3> {
/// ///
/// See the [module docs](self) for examples. /// See the [module docs](self) for examples.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[must_use]
pub enum Either4<E1, E2, E3, E4> { pub enum Either4<E1, E2, E3, E4> {
#[allow(missing_docs)] #[allow(missing_docs)]
E1(E1), E1(E1),
@@ -147,6 +150,7 @@ pub enum Either4<E1, E2, E3, E4> {
/// ///
/// See the [module docs](self) for examples. /// See the [module docs](self) for examples.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[must_use]
pub enum Either5<E1, E2, E3, E4, E5> { pub enum Either5<E1, E2, E3, E4, E5> {
#[allow(missing_docs)] #[allow(missing_docs)]
E1(E1), E1(E1),
@@ -164,6 +168,7 @@ pub enum Either5<E1, E2, E3, E4, E5> {
/// ///
/// See the [module docs](self) for examples. /// See the [module docs](self) for examples.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[must_use]
pub enum Either6<E1, E2, E3, E4, E5, E6> { pub enum Either6<E1, E2, E3, E4, E5, E6> {
#[allow(missing_docs)] #[allow(missing_docs)]
E1(E1), E1(E1),
@@ -183,6 +188,7 @@ pub enum Either6<E1, E2, E3, E4, E5, E6> {
/// ///
/// See the [module docs](self) for examples. /// See the [module docs](self) for examples.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[must_use]
pub enum Either7<E1, E2, E3, E4, E5, E6, E7> { pub enum Either7<E1, E2, E3, E4, E5, E6, E7> {
#[allow(missing_docs)] #[allow(missing_docs)]
E1(E1), E1(E1),
@@ -204,6 +210,7 @@ pub enum Either7<E1, E2, E3, E4, E5, E6, E7> {
/// ///
/// See the [module docs](self) for examples. /// See the [module docs](self) for examples.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[must_use]
pub enum Either8<E1, E2, E3, E4, E5, E6, E7, E8> { pub enum Either8<E1, E2, E3, E4, E5, E6, E7, E8> {
#[allow(missing_docs)] #[allow(missing_docs)]
E1(E1), E1(E1),
+1
View File
@@ -58,6 +58,7 @@ pin_project! {
/// ``` /// ```
// we use `AsExtractor` as the default because you're more likely to name this type if its used // we use `AsExtractor` as the default because you're more likely to name this type if its used
// as an extractor // as an extractor
#[must_use]
pub struct JsonLines<S, T = AsExtractor> { pub struct JsonLines<S, T = AsExtractor> {
#[pin] #[pin]
inner: Inner<S>, inner: Inner<S>,
+1
View File
@@ -94,6 +94,7 @@ use std::ops::{Deref, DerefMut};
/// ``` /// ```
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(docsrs, doc(cfg(feature = "protobuf")))] #[cfg_attr(docsrs, doc(cfg(feature = "protobuf")))]
#[must_use]
pub struct Protobuf<T>(pub T); pub struct Protobuf<T>(pub T);
#[async_trait] #[async_trait]
+1
View File
@@ -30,6 +30,7 @@ use serde::Serialize;
/// ``` /// ```
#[cfg_attr(docsrs, doc(cfg(feature = "erased-json")))] #[cfg_attr(docsrs, doc(cfg(feature = "erased-json")))]
#[derive(Debug)] #[derive(Debug)]
#[must_use]
pub struct ErasedJson(serde_json::Result<Bytes>); pub struct ErasedJson(serde_json::Result<Bytes>);
impl ErasedJson { impl ErasedJson {
+1
View File
@@ -33,6 +33,7 @@ use axum::{
/// # let _: Router = app; /// # let _: Router = app;
/// ``` /// ```
#[derive(Debug)] #[derive(Debug)]
#[must_use]
pub struct Resource<S = (), B = Body> { pub struct Resource<S = (), B = Body> {
pub(crate) name: String, pub(crate) name: String,
pub(crate) router: Router<S, B>, pub(crate) router: Router<S, B>,
+3 -2
View File
@@ -7,12 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# Unreleased # Unreleased
- **fixed:** Add `#[must_use]` attributes to types that do nothing unless used ([#1809])
- **fixed:** Add `#[must_use]` to `WebSocketUpgrade::on_upgrade` ([#1801]) - **fixed:** Add `#[must_use]` to `WebSocketUpgrade::on_upgrade` ([#1801])
- **fixed:** Fix routing issues when loading a `Router` via a dynamic library ([#1806]) - **fixed:** Fix routing issues when loading a `Router` via a dynamic library ([#1806])
[#1806]: https://github.com/tokio-rs/axum/pull/1806
[#1801]: https://github.com/tokio-rs/axum/pull/1801 [#1801]: https://github.com/tokio-rs/axum/pull/1801
[#1806]: https://github.com/tokio-rs/axum/pull/1806
[#1809]: https://github.com/tokio-rs/axum/pull/1809
# 0.6.9 (24. February, 2023) # 0.6.9 (24. February, 2023)
+1
View File
@@ -52,6 +52,7 @@ pin_project! {
/// ``` /// ```
/// ///
/// [`Stream`]: futures_util::stream::Stream /// [`Stream`]: futures_util::stream::Stream
#[must_use]
pub struct StreamBody<S> { pub struct StreamBody<S> {
#[pin] #[pin]
stream: SyncWrapper<S>, stream: SyncWrapper<S>,
+1
View File
@@ -70,6 +70,7 @@ use tower_service::Service;
/// struct Foo(&'static str); /// struct Foo(&'static str);
/// ``` /// ```
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[must_use]
pub struct Extension<T>(pub T); pub struct Extension<T>(pub T);
#[async_trait] #[async_trait]
+1
View File
@@ -61,6 +61,7 @@ use std::ops::Deref;
/// [`Multipart`]: crate::extract::Multipart /// [`Multipart`]: crate::extract::Multipart
#[cfg_attr(docsrs, doc(cfg(feature = "form")))] #[cfg_attr(docsrs, doc(cfg(feature = "form")))]
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[must_use]
pub struct Form<T>(pub T); pub struct Form<T>(pub T);
#[async_trait] #[async_trait]
+1
View File
@@ -97,6 +97,7 @@ use std::ops::{Deref, DerefMut};
/// ``` /// ```
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))] #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
#[must_use]
pub struct Json<T>(pub T); pub struct Json<T>(pub T);
#[async_trait] #[async_trait]
+1
View File
@@ -110,6 +110,7 @@ pub fn from_extractor_with_state<E, S>(state: S) -> FromExtractorLayer<E, S> {
/// See [`from_extractor`] for more details. /// See [`from_extractor`] for more details.
/// ///
/// [`Layer`]: tower::Layer /// [`Layer`]: tower::Layer
#[must_use]
pub struct FromExtractorLayer<E, S> { pub struct FromExtractorLayer<E, S> {
state: S, state: S,
_marker: PhantomData<fn() -> E>, _marker: PhantomData<fn() -> E>,
+1
View File
@@ -161,6 +161,7 @@ pub fn from_fn_with_state<F, S, T>(state: S, f: F) -> FromFnLayer<F, S, T> {
/// [`tower::Layer`] is used to apply middleware to [`Router`](crate::Router)'s. /// [`tower::Layer`] is used to apply middleware to [`Router`](crate::Router)'s.
/// ///
/// Created with [`from_fn`]. See that function for more details. /// Created with [`from_fn`]. See that function for more details.
#[must_use]
pub struct FromFnLayer<F, S, T> { pub struct FromFnLayer<F, S, T> {
f: F, f: F,
state: S, state: S,
+1
View File
@@ -165,6 +165,7 @@ pub fn map_request_with_state<F, S, T>(state: S, f: F) -> MapRequestLayer<F, S,
/// A [`tower::Layer`] from an async function that transforms a request. /// A [`tower::Layer`] from an async function that transforms a request.
/// ///
/// Created with [`map_request`]. See that function for more details. /// Created with [`map_request`]. See that function for more details.
#[must_use]
pub struct MapRequestLayer<F, S, T> { pub struct MapRequestLayer<F, S, T> {
f: F, f: F,
state: S, state: S,
+1
View File
@@ -149,6 +149,7 @@ pub fn map_response_with_state<F, S, T>(state: S, f: F) -> MapResponseLayer<F, S
/// A [`tower::Layer`] from an async function that transforms a response. /// A [`tower::Layer`] from an async function that transforms a response.
/// ///
/// Created with [`map_response`]. See that function for more details. /// Created with [`map_response`]. See that function for more details.
#[must_use]
pub struct MapResponseLayer<F, S, T> { pub struct MapResponseLayer<F, S, T> {
f: F, f: F,
state: S, state: S,
+3 -2
View File
@@ -39,6 +39,7 @@ pub use sse::Sse;
/// ///
/// Will automatically get `Content-Type: text/html`. /// Will automatically get `Content-Type: text/html`.
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
#[must_use]
pub struct Html<T>(pub T); pub struct Html<T>(pub T);
impl<T> IntoResponse for Html<T> impl<T> IntoResponse for Html<T>
@@ -98,7 +99,7 @@ mod tests {
} }
} }
Router::<(), Body>::new() _ = Router::<(), Body>::new()
.route("/", get(impl_trait_ok)) .route("/", get(impl_trait_ok))
.route("/", get(impl_trait_err)) .route("/", get(impl_trait_err))
.route("/", get(impl_trait_both)) .route("/", get(impl_trait_both))
@@ -208,7 +209,7 @@ mod tests {
) )
} }
Router::<(), Body>::new() _ = Router::<(), Body>::new()
.route("/", get(status)) .route("/", get(status))
.route("/", get(status_headermap)) .route("/", get(status_headermap))
.route("/", get(status_header_array)) .route("/", get(status_header_array))
+3
View File
@@ -53,6 +53,7 @@ use tokio::time::Sleep;
/// An SSE response /// An SSE response
#[derive(Clone)] #[derive(Clone)]
#[must_use]
pub struct Sse<S> { pub struct Sse<S> {
stream: S, stream: S,
keep_alive: Option<KeepAlive>, keep_alive: Option<KeepAlive>,
@@ -163,6 +164,7 @@ where
/// Server-sent event /// Server-sent event
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
#[must_use]
pub struct Event { pub struct Event {
buffer: BytesMut, buffer: BytesMut,
flags: EventFlags, flags: EventFlags,
@@ -383,6 +385,7 @@ bitflags::bitflags! {
/// Configure the interval between keep-alive messages, the content /// Configure the interval between keep-alive messages, the content
/// of each message, and the associated stream. /// of each message, and the associated stream.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[must_use]
pub struct KeepAlive { pub struct KeepAlive {
event: Bytes, event: Bytes,
max_interval: Duration, max_interval: Duration,
+1
View File
@@ -513,6 +513,7 @@ where
/// S: Service<Request<Body>>, /// S: Service<Request<Body>>,
/// {} /// {}
/// ``` /// ```
#[must_use]
pub struct MethodRouter<S = (), B = Body, E = Infallible> { pub struct MethodRouter<S = (), B = Body, E = Infallible> {
get: MethodEndpoint<S, B, E>, get: MethodEndpoint<S, B, E>,
head: MethodEndpoint<S, B, E>, head: MethodEndpoint<S, B, E>,
+1
View File
@@ -48,6 +48,7 @@ pub use self::method_routing::{
pub(crate) struct RouteId(u32); pub(crate) struct RouteId(u32);
/// The router type for composing handlers and services. /// The router type for composing handlers and services.
#[must_use]
pub struct Router<S = (), B = Body> { pub struct Router<S = (), B = Body> {
routes: HashMap<RouteId, Endpoint<S, B>>, routes: HashMap<RouteId, Endpoint<S, B>>,
node: Arc<Node>, node: Arc<Node>,
+1 -1
View File
@@ -522,7 +522,7 @@ fn routes_with_overlapping_method_routes() {
fn merging_with_overlapping_method_routes() { fn merging_with_overlapping_method_routes() {
async fn handler() {} async fn handler() {}
let app: Router = Router::new().route("/foo/bar", get(handler)); let app: Router = Router::new().route("/foo/bar", get(handler));
app.clone().merge(app); _ = app.clone().merge(app);
} }
#[crate::test] #[crate::test]
+1 -1
View File
@@ -257,7 +257,7 @@ async fn multiple_top_level_nests() {
#[crate::test] #[crate::test]
#[should_panic(expected = "Invalid route: nested routes cannot contain wildcards (*)")] #[should_panic(expected = "Invalid route: nested routes cannot contain wildcards (*)")]
async fn nest_cannot_contain_wildcards() { async fn nest_cannot_contain_wildcards() {
Router::<(), Body>::new().nest("/one/*rest", Router::new()); _ = Router::<(), Body>::new().nest("/one/*rest", Router::new());
} }
#[crate::test] #[crate::test]
+1
View File
@@ -50,6 +50,7 @@ use std::{convert::Infallible, ops::Deref};
/// ``` /// ```
#[cfg(feature = "headers")] #[cfg(feature = "headers")]
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[must_use]
pub struct TypedHeader<T>(pub T); pub struct TypedHeader<T>(pub T);
#[async_trait] #[async_trait]