#[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
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 43 additions and 9 deletions

View file

@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# 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)

View file

@ -73,6 +73,7 @@ use tower_layer::Layer;
/// [`RequestExt::with_limited_body`]: crate::RequestExt::with_limited_body
/// [`RequestExt::into_limited_body`]: crate::RequestExt::into_limited_body
#[derive(Debug, Clone)]
#[must_use]
pub struct DefaultBodyLimit {
kind: DefaultBodyLimitKind,
}

View file

@ -30,6 +30,7 @@ use std::fmt;
/// }
/// ```
#[derive(Debug)]
#[must_use]
pub struct AppendHeaders<I>(pub I);
impl<I, K, V> IntoResponse for AppendHeaders<I>

View file

@ -9,11 +9,13 @@ and this project adheres to [Semantic Versioning].
- **added:** Add `Multipart`. This is similar to `axum::extract::Multipart`
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])
- **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
[#1809]: https://github.com/tokio-rs/axum/pull/1809
# 0.6.0 (24. February, 2022)

View file

@ -46,6 +46,7 @@ pin_project! {
/// ```
#[cfg(feature = "async-read-body")]
#[derive(Debug)]
#[must_use]
pub struct AsyncReadBody<R> {
#[pin]
read: StreamBody<ReaderStream<R>>,

View file

@ -108,6 +108,7 @@ use tower_service::Service;
///
/// See the [module docs](self) for examples.
#[derive(Debug, Clone)]
#[must_use]
pub enum Either<E1, E2> {
#[allow(missing_docs)]
E1(E1),
@ -119,6 +120,7 @@ pub enum Either<E1, E2> {
///
/// See the [module docs](self) for examples.
#[derive(Debug, Clone)]
#[must_use]
pub enum Either3<E1, E2, E3> {
#[allow(missing_docs)]
E1(E1),
@ -132,6 +134,7 @@ pub enum Either3<E1, E2, E3> {
///
/// See the [module docs](self) for examples.
#[derive(Debug, Clone)]
#[must_use]
pub enum Either4<E1, E2, E3, E4> {
#[allow(missing_docs)]
E1(E1),
@ -147,6 +150,7 @@ pub enum Either4<E1, E2, E3, E4> {
///
/// See the [module docs](self) for examples.
#[derive(Debug, Clone)]
#[must_use]
pub enum Either5<E1, E2, E3, E4, E5> {
#[allow(missing_docs)]
E1(E1),
@ -164,6 +168,7 @@ pub enum Either5<E1, E2, E3, E4, E5> {
///
/// See the [module docs](self) for examples.
#[derive(Debug, Clone)]
#[must_use]
pub enum Either6<E1, E2, E3, E4, E5, E6> {
#[allow(missing_docs)]
E1(E1),
@ -183,6 +188,7 @@ pub enum Either6<E1, E2, E3, E4, E5, E6> {
///
/// See the [module docs](self) for examples.
#[derive(Debug, Clone)]
#[must_use]
pub enum Either7<E1, E2, E3, E4, E5, E6, E7> {
#[allow(missing_docs)]
E1(E1),
@ -204,6 +210,7 @@ pub enum Either7<E1, E2, E3, E4, E5, E6, E7> {
///
/// See the [module docs](self) for examples.
#[derive(Debug, Clone)]
#[must_use]
pub enum Either8<E1, E2, E3, E4, E5, E6, E7, E8> {
#[allow(missing_docs)]
E1(E1),

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
// as an extractor
#[must_use]
pub struct JsonLines<S, T = AsExtractor> {
#[pin]
inner: Inner<S>,

View file

@ -94,6 +94,7 @@ use std::ops::{Deref, DerefMut};
/// ```
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(docsrs, doc(cfg(feature = "protobuf")))]
#[must_use]
pub struct Protobuf<T>(pub T);
#[async_trait]

View file

@ -30,6 +30,7 @@ use serde::Serialize;
/// ```
#[cfg_attr(docsrs, doc(cfg(feature = "erased-json")))]
#[derive(Debug)]
#[must_use]
pub struct ErasedJson(serde_json::Result<Bytes>);
impl ErasedJson {

View file

@ -33,6 +33,7 @@ use axum::{
/// # let _: Router = app;
/// ```
#[derive(Debug)]
#[must_use]
pub struct Resource<S = (), B = Body> {
pub(crate) name: String,
pub(crate) router: Router<S, B>,

View file

@ -7,12 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# Unreleased
- **fixed:** Add `#[must_use]` attributes to types that do nothing unless used ([#1809])
- **fixed:** Add `#[must_use]` to `WebSocketUpgrade::on_upgrade` ([#1801])
- **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
[#1806]: https://github.com/tokio-rs/axum/pull/1806
[#1809]: https://github.com/tokio-rs/axum/pull/1809
# 0.6.9 (24. February, 2023)

View file

@ -52,6 +52,7 @@ pin_project! {
/// ```
///
/// [`Stream`]: futures_util::stream::Stream
#[must_use]
pub struct StreamBody<S> {
#[pin]
stream: SyncWrapper<S>,

View file

@ -70,6 +70,7 @@ use tower_service::Service;
/// struct Foo(&'static str);
/// ```
#[derive(Debug, Clone, Copy, Default)]
#[must_use]
pub struct Extension<T>(pub T);
#[async_trait]

View file

@ -61,6 +61,7 @@ use std::ops::Deref;
/// [`Multipart`]: crate::extract::Multipart
#[cfg_attr(docsrs, doc(cfg(feature = "form")))]
#[derive(Debug, Clone, Copy, Default)]
#[must_use]
pub struct Form<T>(pub T);
#[async_trait]

View file

@ -97,6 +97,7 @@ use std::ops::{Deref, DerefMut};
/// ```
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
#[must_use]
pub struct Json<T>(pub T);
#[async_trait]

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.
///
/// [`Layer`]: tower::Layer
#[must_use]
pub struct FromExtractorLayer<E, S> {
state: S,
_marker: PhantomData<fn() -> E>,

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.
///
/// Created with [`from_fn`]. See that function for more details.
#[must_use]
pub struct FromFnLayer<F, S, T> {
f: F,
state: S,

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.
///
/// Created with [`map_request`]. See that function for more details.
#[must_use]
pub struct MapRequestLayer<F, S, T> {
f: F,
state: S,

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.
///
/// Created with [`map_response`]. See that function for more details.
#[must_use]
pub struct MapResponseLayer<F, S, T> {
f: F,
state: S,

View file

@ -39,6 +39,7 @@ pub use sse::Sse;
///
/// Will automatically get `Content-Type: text/html`.
#[derive(Clone, Copy, Debug)]
#[must_use]
pub struct Html<T>(pub 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_err))
.route("/", get(impl_trait_both))
@ -208,7 +209,7 @@ mod tests {
)
}
Router::<(), Body>::new()
_ = Router::<(), Body>::new()
.route("/", get(status))
.route("/", get(status_headermap))
.route("/", get(status_header_array))

View file

@ -53,6 +53,7 @@ use tokio::time::Sleep;
/// An SSE response
#[derive(Clone)]
#[must_use]
pub struct Sse<S> {
stream: S,
keep_alive: Option<KeepAlive>,
@ -163,6 +164,7 @@ where
/// Server-sent event
#[derive(Debug, Default, Clone)]
#[must_use]
pub struct Event {
buffer: BytesMut,
flags: EventFlags,
@ -383,6 +385,7 @@ bitflags::bitflags! {
/// Configure the interval between keep-alive messages, the content
/// of each message, and the associated stream.
#[derive(Debug, Clone)]
#[must_use]
pub struct KeepAlive {
event: Bytes,
max_interval: Duration,

View file

@ -513,6 +513,7 @@ where
/// S: Service<Request<Body>>,
/// {}
/// ```
#[must_use]
pub struct MethodRouter<S = (), B = Body, E = Infallible> {
get: MethodEndpoint<S, B, E>,
head: MethodEndpoint<S, B, E>,

View file

@ -48,6 +48,7 @@ pub use self::method_routing::{
pub(crate) struct RouteId(u32);
/// The router type for composing handlers and services.
#[must_use]
pub struct Router<S = (), B = Body> {
routes: HashMap<RouteId, Endpoint<S, B>>,
node: Arc<Node>,

View file

@ -522,7 +522,7 @@ fn routes_with_overlapping_method_routes() {
fn merging_with_overlapping_method_routes() {
async fn handler() {}
let app: Router = Router::new().route("/foo/bar", get(handler));
app.clone().merge(app);
_ = app.clone().merge(app);
}
#[crate::test]

View file

@ -257,7 +257,7 @@ async fn multiple_top_level_nests() {
#[crate::test]
#[should_panic(expected = "Invalid route: nested routes 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]

View file

@ -50,6 +50,7 @@ use std::{convert::Infallible, ops::Deref};
/// ```
#[cfg(feature = "headers")]
#[derive(Debug, Clone, Copy)]
#[must_use]
pub struct TypedHeader<T>(pub T);
#[async_trait]