From dd0c3450406ead90abfee84155187971c5f47bbf Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Tue, 17 Aug 2021 19:07:47 +0200 Subject: [PATCH] Improve compile times of `handle_error` and `check_infallible` (#198) * Improve compile times of `handle_error` This brings the compile time of the example posted [here][example] from 3 seconds down to 0.3 seconds for me. Having the bounds on the methods does improve UX but not worth sacrificing 10x compile time for. [example]: https://github.com/tokio-rs/axum/issues/145#issue-963183256 * Improve compile time of `check_infallible` * update changelog --- CHANGELOG.md | 4 ++++ src/routing/mod.rs | 48 +++++++++++++++++++++++++++++++--------------- src/service/mod.rs | 9 ++------- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a17c5f36..1fb67d66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 # Unreleased +- Overall compile time improvements. If you're having issues with compile time + please file an issue! - Make `FromRequest` default to being generic over `body::Body` ([#146](https://github.com/tokio-rs/axum/pull/146)) - Implement `std::error::Error` for all rejections ([#153](https://github.com/tokio-rs/axum/pull/153)) - Add `RoutingDsl::or` for combining routes ([#108](https://github.com/tokio-rs/axum/pull/108)) @@ -39,6 +41,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ServiceExt` has been removed and its methods have been moved to `RoutingDsl` ([#160](https://github.com/tokio-rs/axum/pull/160)) - `extractor_middleware` now requires `RequestBody: Default` ([#167](https://github.com/tokio-rs/axum/pull/167)) - Convert `RequestAlreadyExtracted` to an enum with each possible error variant ([#167](https://github.com/tokio-rs/axum/pull/167)) +- `RoutingDsl::check_infallible` now returns a `CheckInfallible` service. This + is to improve compile times. - These future types have been moved - `extract::extractor_middleware::ExtractorMiddlewareResponseFuture` moved to `extract::extractor_middleware::future::ResponseFuture` ([#133](https://github.com/tokio-rs/axum/pull/133)) diff --git a/src/routing/mod.rs b/src/routing/mod.rs index dfc1f54e..914221dc 100644 --- a/src/routing/mod.rs +++ b/src/routing/mod.rs @@ -8,7 +8,6 @@ use crate::{ connect_info::{Connected, IntoMakeServiceWithConnectInfo}, NestedUri, }, - response::IntoResponse, service::{HandleError, HandleErrorFromRouter}, util::ByteStr, }; @@ -416,28 +415,18 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized { /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` - fn handle_error( + fn handle_error( self, f: F, - ) -> HandleError - where - Self: Service, Response = Response>, - F: FnOnce(Self::Error) -> Result, - Res: IntoResponse, - ResBody: http_body::Body + Send + Sync + 'static, - ResBody::Error: Into + Send + Sync + 'static, - { + ) -> HandleError { HandleError::new(self, f) } /// Check that your service cannot fail. /// /// That is, its error type is [`Infallible`]. - fn check_infallible(self) -> Self - where - Self: Service, Error = Infallible>, - { - self + fn check_infallible(self) -> CheckInfallible { + CheckInfallible(self) } } @@ -964,6 +953,35 @@ fn strip_prefix(uri: &Uri, prefix: &str) -> Uri { Uri::from_parts(parts).unwrap() } +/// Middleware that statically verifies that a service cannot fail. +/// +/// Created with [`check_infallible`](RoutingDsl::check_infallible). +#[derive(Debug, Clone, Copy)] +pub struct CheckInfallible(S); + +impl Service for CheckInfallible +where + S: Service, +{ + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + #[inline] + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.0.poll_ready(cx) + } + + #[inline] + fn call(&mut self, req: R) -> Self::Future { + self.0.call(req) + } +} + +impl RoutingDsl for CheckInfallible {} + +impl crate::sealed::Sealed for CheckInfallible {} + #[cfg(test)] mod tests { use super::*; diff --git a/src/service/mod.rs b/src/service/mod.rs index 5dae742b..08c46970 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -453,15 +453,10 @@ impl OnMethod { /// details. /// /// [`RoutingDsl::handle_error`]: crate::routing::RoutingDsl::handle_error - pub fn handle_error( + pub fn handle_error( self, f: H, - ) -> HandleError - where - Self: Service, Response = Response>, - H: FnOnce(>>::Error) -> Result, - Res: IntoResponse, - { + ) -> HandleError { HandleError::new(self, f) } }