Skip to content

Commit 2608a51

Browse files
authored
Make type inference work for ServiceExt (#566)
Unfortunately, making type inference work for this requires removing the generic parameter from ServiceExt, which in turn requires removing the tower::Service supertrait. This made the Sealed trait useless, and while I was at it I also removed the Sized supertrait in favor of Sized bounds on all current trait methods (this allows backwards-compatibly adding methods that don't require Self to be Sized to be added). This means that now you can call all of these methods on _anything_, the resulting type just isn't going to be very useful if the type you're calling the method on isn't a tower::Service<http::Request<B>> (extra bounds may apply depending on the exact method).
1 parent c61fb8d commit 2608a51

File tree

1 file changed

+105
-33
lines changed

1 file changed

+105
-33
lines changed

tower-http/src/service_ext.rs

Lines changed: 105 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
11
#[allow(unused_imports)]
22
use http::header::HeaderName;
33

4-
mod sealed {
5-
#[allow(unreachable_pub, unused)]
6-
pub trait Sealed<R> {}
7-
}
8-
94
/// Extension trait that adds methods to any [`Service`] for adding middleware from
105
/// tower-http.
116
///
127
/// [`Service`]: tower::Service
138
#[cfg(feature = "util")]
149
// ^ work around rustdoc not inferring doc(cfg)s for cfg's from surrounding scopes
15-
pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
10+
pub trait ServiceExt {
1611
/// Propagate a header from the request to the response.
1712
///
1813
/// See [`tower_http::propagate_header`] for more details.
1914
///
2015
/// [`tower_http::propagate_header`]: crate::propagate_header
2116
#[cfg(feature = "propagate-header")]
22-
fn propagate_header(
23-
self,
24-
header: HeaderName,
25-
) -> crate::propagate_header::PropagateHeader<Self> {
17+
fn propagate_header(self, header: HeaderName) -> crate::propagate_header::PropagateHeader<Self>
18+
where
19+
Self: Sized,
20+
{
2621
crate::propagate_header::PropagateHeader::new(self, header)
2722
}
2823

@@ -33,7 +28,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
3328
/// [`tower_http::add_extension`]: crate::add_extension
3429
/// [request extensions]: https://docs.rs/http/latest/http/struct.Extensions.html
3530
#[cfg(feature = "add-extension")]
36-
fn add_extension<T>(self, value: T) -> crate::add_extension::AddExtension<Self, T> {
31+
fn add_extension<T>(self, value: T) -> crate::add_extension::AddExtension<Self, T>
32+
where
33+
Self: Sized,
34+
{
3735
crate::add_extension::AddExtension::new(self, value)
3836
}
3937

@@ -43,7 +41,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
4341
///
4442
/// [`tower_http::map_request_body`]: crate::map_request_body
4543
#[cfg(feature = "map-request-body")]
46-
fn map_request_body<F>(self, f: F) -> crate::map_request_body::MapRequestBody<Self, F> {
44+
fn map_request_body<F>(self, f: F) -> crate::map_request_body::MapRequestBody<Self, F>
45+
where
46+
Self: Sized,
47+
{
4748
crate::map_request_body::MapRequestBody::new(self, f)
4849
}
4950

@@ -53,7 +54,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
5354
///
5455
/// [`tower_http::map_response_body`]: crate::map_response_body
5556
#[cfg(feature = "map-response-body")]
56-
fn map_response_body<F>(self, f: F) -> crate::map_response_body::MapResponseBody<Self, F> {
57+
fn map_response_body<F>(self, f: F) -> crate::map_response_body::MapResponseBody<Self, F>
58+
where
59+
Self: Sized,
60+
{
5761
crate::map_response_body::MapResponseBody::new(self, f)
5862
}
5963

@@ -68,7 +72,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
6872
feature = "compression-gzip",
6973
feature = "compression-zstd",
7074
))]
71-
fn compression(self) -> crate::compression::Compression<Self> {
75+
fn compression(self) -> crate::compression::Compression<Self>
76+
where
77+
Self: Sized,
78+
{
7279
crate::compression::Compression::new(self)
7380
}
7481

@@ -83,7 +90,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
8390
feature = "decompression-gzip",
8491
feature = "decompression-zstd",
8592
))]
86-
fn decompression(self) -> crate::decompression::Decompression<Self> {
93+
fn decompression(self) -> crate::decompression::Decompression<Self>
94+
where
95+
Self: Sized,
96+
{
8797
crate::decompression::Decompression::new(self)
8898
}
8999

@@ -97,7 +107,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
97107
/// [`tower_http::trace`]: crate::trace
98108
/// [`TraceLayer`]: crate::trace::TraceLayer
99109
#[cfg(feature = "trace")]
100-
fn trace_for_http(self) -> crate::trace::Trace<Self, crate::trace::HttpMakeClassifier> {
110+
fn trace_for_http(self) -> crate::trace::Trace<Self, crate::trace::HttpMakeClassifier>
111+
where
112+
Self: Sized,
113+
{
101114
crate::trace::Trace::new_for_http(self)
102115
}
103116

@@ -111,7 +124,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
111124
/// [`tower_http::trace`]: crate::trace
112125
/// [`TraceLayer`]: crate::trace::TraceLayer
113126
#[cfg(feature = "trace")]
114-
fn trace_for_grpc(self) -> crate::trace::Trace<Self, crate::trace::GrpcMakeClassifier> {
127+
fn trace_for_grpc(self) -> crate::trace::Trace<Self, crate::trace::GrpcMakeClassifier>
128+
where
129+
Self: Sized,
130+
{
115131
crate::trace::Trace::new_for_grpc(self)
116132
}
117133

@@ -125,6 +141,8 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
125141
fn follow_redirects(
126142
self,
127143
) -> crate::follow_redirect::FollowRedirect<Self, crate::follow_redirect::policy::Standard>
144+
where
145+
Self: Sized,
128146
{
129147
crate::follow_redirect::FollowRedirect::new(self)
130148
}
@@ -139,7 +157,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
139157
fn sensitive_headers(
140158
self,
141159
headers: impl IntoIterator<Item = HeaderName>,
142-
) -> crate::sensitive_headers::SetSensitiveHeaders<Self> {
160+
) -> crate::sensitive_headers::SetSensitiveHeaders<Self>
161+
where
162+
Self: Sized,
163+
{
143164
use tower_layer::Layer as _;
144165
crate::sensitive_headers::SetSensitiveHeadersLayer::new(headers).layer(self)
145166
}
@@ -154,7 +175,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
154175
fn sensitive_request_headers(
155176
self,
156177
headers: impl IntoIterator<Item = HeaderName>,
157-
) -> crate::sensitive_headers::SetSensitiveRequestHeaders<Self> {
178+
) -> crate::sensitive_headers::SetSensitiveRequestHeaders<Self>
179+
where
180+
Self: Sized,
181+
{
158182
crate::sensitive_headers::SetSensitiveRequestHeaders::new(self, headers)
159183
}
160184

@@ -168,7 +192,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
168192
fn sensitive_response_headers(
169193
self,
170194
headers: impl IntoIterator<Item = HeaderName>,
171-
) -> crate::sensitive_headers::SetSensitiveResponseHeaders<Self> {
195+
) -> crate::sensitive_headers::SetSensitiveResponseHeaders<Self>
196+
where
197+
Self: Sized,
198+
{
172199
crate::sensitive_headers::SetSensitiveResponseHeaders::new(self, headers)
173200
}
174201

@@ -185,7 +212,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
185212
self,
186213
header_name: HeaderName,
187214
make: M,
188-
) -> crate::set_header::SetRequestHeader<Self, M> {
215+
) -> crate::set_header::SetRequestHeader<Self, M>
216+
where
217+
Self: Sized,
218+
{
189219
crate::set_header::SetRequestHeader::overriding(self, header_name, make)
190220
}
191221

@@ -201,7 +231,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
201231
self,
202232
header_name: HeaderName,
203233
make: M,
204-
) -> crate::set_header::SetRequestHeader<Self, M> {
234+
) -> crate::set_header::SetRequestHeader<Self, M>
235+
where
236+
Self: Sized,
237+
{
205238
crate::set_header::SetRequestHeader::appending(self, header_name, make)
206239
}
207240

@@ -215,7 +248,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
215248
self,
216249
header_name: HeaderName,
217250
make: M,
218-
) -> crate::set_header::SetRequestHeader<Self, M> {
251+
) -> crate::set_header::SetRequestHeader<Self, M>
252+
where
253+
Self: Sized,
254+
{
219255
crate::set_header::SetRequestHeader::if_not_present(self, header_name, make)
220256
}
221257

@@ -232,7 +268,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
232268
self,
233269
header_name: HeaderName,
234270
make: M,
235-
) -> crate::set_header::SetResponseHeader<Self, M> {
271+
) -> crate::set_header::SetResponseHeader<Self, M>
272+
where
273+
Self: Sized,
274+
{
236275
crate::set_header::SetResponseHeader::overriding(self, header_name, make)
237276
}
238277

@@ -248,7 +287,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
248287
self,
249288
header_name: HeaderName,
250289
make: M,
251-
) -> crate::set_header::SetResponseHeader<Self, M> {
290+
) -> crate::set_header::SetResponseHeader<Self, M>
291+
where
292+
Self: Sized,
293+
{
252294
crate::set_header::SetResponseHeader::appending(self, header_name, make)
253295
}
254296

@@ -262,7 +304,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
262304
self,
263305
header_name: HeaderName,
264306
make: M,
265-
) -> crate::set_header::SetResponseHeader<Self, M> {
307+
) -> crate::set_header::SetResponseHeader<Self, M>
308+
where
309+
Self: Sized,
310+
{
266311
crate::set_header::SetResponseHeader::if_not_present(self, header_name, make)
267312
}
268313

@@ -278,6 +323,7 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
278323
make_request_id: M,
279324
) -> crate::request_id::SetRequestId<Self, M>
280325
where
326+
Self: Sized,
281327
M: crate::request_id::MakeRequestId,
282328
{
283329
crate::request_id::SetRequestId::new(self, header_name, make_request_id)
@@ -291,6 +337,7 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
291337
#[cfg(feature = "request-id")]
292338
fn set_x_request_id<M>(self, make_request_id: M) -> crate::request_id::SetRequestId<Self, M>
293339
where
340+
Self: Sized,
294341
M: crate::request_id::MakeRequestId,
295342
{
296343
self.set_request_id(crate::request_id::X_REQUEST_ID, make_request_id)
@@ -305,7 +352,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
305352
fn propagate_request_id(
306353
self,
307354
header_name: HeaderName,
308-
) -> crate::request_id::PropagateRequestId<Self> {
355+
) -> crate::request_id::PropagateRequestId<Self>
356+
where
357+
Self: Sized,
358+
{
309359
crate::request_id::PropagateRequestId::new(self, header_name)
310360
}
311361

@@ -315,7 +365,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
315365
///
316366
/// [`tower_http::request_id`]: crate::request_id
317367
#[cfg(feature = "request-id")]
318-
fn propagate_x_request_id(self) -> crate::request_id::PropagateRequestId<Self> {
368+
fn propagate_x_request_id(self) -> crate::request_id::PropagateRequestId<Self>
369+
where
370+
Self: Sized,
371+
{
319372
self.propagate_request_id(crate::request_id::X_REQUEST_ID)
320373
}
321374

@@ -327,7 +380,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
327380
#[cfg(feature = "catch-panic")]
328381
fn catch_panic(
329382
self,
330-
) -> crate::catch_panic::CatchPanic<Self, crate::catch_panic::DefaultResponseForPanic> {
383+
) -> crate::catch_panic::CatchPanic<Self, crate::catch_panic::DefaultResponseForPanic>
384+
where
385+
Self: Sized,
386+
{
331387
crate::catch_panic::CatchPanic::new(self)
332388
}
333389

@@ -338,7 +394,10 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
338394
///
339395
/// [`tower_http::limit`]: crate::limit
340396
#[cfg(feature = "limit")]
341-
fn request_body_limit(self, limit: usize) -> crate::limit::RequestBodyLimit<Self> {
397+
fn request_body_limit(self, limit: usize) -> crate::limit::RequestBodyLimit<Self>
398+
where
399+
Self: Sized,
400+
{
342401
crate::limit::RequestBodyLimit::new(self, limit)
343402
}
344403

@@ -348,10 +407,23 @@ pub trait ServiceExt<R>: sealed::Sealed<R> + tower::Service<R> + Sized {
348407
///
349408
/// [`tower_http::normalize_path`]: crate::normalize_path
350409
#[cfg(feature = "normalize-path")]
351-
fn trim_trailing_slash(self) -> crate::normalize_path::NormalizePath<Self> {
410+
fn trim_trailing_slash(self) -> crate::normalize_path::NormalizePath<Self>
411+
where
412+
Self: Sized,
413+
{
352414
crate::normalize_path::NormalizePath::trim_trailing_slash(self)
353415
}
354416
}
355417

356-
impl<R, T> sealed::Sealed<R> for T where T: tower::Service<R> {}
357-
impl<R, T> ServiceExt<R> for T where T: tower::Service<R> {}
418+
impl<T> ServiceExt for T {}
419+
420+
#[cfg(all(test, feature = "fs", feature = "add-extension"))]
421+
mod tests {
422+
use super::ServiceExt;
423+
use crate::services;
424+
425+
#[allow(dead_code)]
426+
fn test_type_inference() {
427+
let _svc = services::fs::ServeDir::new(".").add_extension("&'static str");
428+
}
429+
}

0 commit comments

Comments
 (0)