summaryrefslogtreecommitdiffstats
path: root/src/test/ui/nll/issue-61320-normalize.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/nll/issue-61320-normalize.rs')
-rw-r--r--src/test/ui/nll/issue-61320-normalize.rs160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/test/ui/nll/issue-61320-normalize.rs b/src/test/ui/nll/issue-61320-normalize.rs
new file mode 100644
index 000000000..095bef03f
--- /dev/null
+++ b/src/test/ui/nll/issue-61320-normalize.rs
@@ -0,0 +1,160 @@
+// Regression test for #61320
+// This is the same issue as #61311, just a larger test case.
+
+// check-pass
+
+pub struct AndThen<A, B, F>
+where
+ A: Future,
+ B: IntoFuture,
+{
+ state: (A, B::Future, F),
+}
+
+pub struct FutureResult<T, E> {
+ inner: Option<Result<T, E>>,
+}
+
+impl<T, E> Future for FutureResult<T, E> {
+ type Item = T;
+ type Error = E;
+
+ fn poll(&mut self) -> Poll<T, E> {
+ unimplemented!()
+ }
+}
+
+pub type Poll<T, E> = Result<T, E>;
+
+impl<A, B, F> Future for AndThen<A, B, F>
+where
+ A: Future,
+ B: IntoFuture<Error = A::Error>,
+ F: FnOnce(A::Item) -> B,
+{
+ type Item = B::Item;
+ type Error = B::Error;
+
+ fn poll(&mut self) -> Poll<B::Item, B::Error> {
+ unimplemented!()
+ }
+}
+
+pub trait Future {
+ type Item;
+
+ type Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error>;
+
+ fn and_then<F, B>(self, f: F) -> AndThen<Self, B, F>
+ where
+ F: FnOnce(Self::Item) -> B,
+ B: IntoFuture<Error = Self::Error>,
+ Self: Sized,
+ {
+ unimplemented!()
+ }
+}
+
+pub trait IntoFuture {
+ /// The future that this type can be converted into.
+ type Future: Future<Item = Self::Item, Error = Self::Error>;
+
+ /// The item that the future may resolve with.
+ type Item;
+ /// The error that the future may resolve with.
+ type Error;
+
+ /// Consumes this object and produces a future.
+ fn into_future(self) -> Self::Future;
+}
+
+impl<F: Future> IntoFuture for F {
+ type Future = F;
+ type Item = F::Item;
+ type Error = F::Error;
+
+ fn into_future(self) -> F {
+ self
+ }
+}
+
+impl<F: ?Sized + Future> Future for ::std::boxed::Box<F> {
+ type Item = F::Item;
+ type Error = F::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ (**self).poll()
+ }
+}
+
+impl<T, E> IntoFuture for Result<T, E> {
+ type Future = FutureResult<T, E>;
+ type Item = T;
+ type Error = E;
+
+ fn into_future(self) -> FutureResult<T, E> {
+ unimplemented!()
+ }
+}
+
+struct Request<T>(T);
+
+trait RequestContext {}
+impl<T> RequestContext for T {}
+struct NoContext;
+impl AsRef<NoContext> for NoContext {
+ fn as_ref(&self) -> &Self {
+ &NoContext
+ }
+}
+
+type BoxedError = Box<dyn std::error::Error + Send + Sync>;
+type DefaultFuture<T, E> = Box<dyn Future<Item = T, Error = E> + Send>;
+
+trait Guard: Sized {
+ type Result: IntoFuture<Item = Self, Error = BoxedError>;
+ fn from_request(request: &Request<()>) -> Self::Result;
+}
+
+trait FromRequest: Sized {
+ type Context;
+ type Future: Future<Item = Self, Error = BoxedError> + Send;
+ fn from_request(request: Request<()>) -> Self::Future;
+}
+
+struct MyGuard;
+impl Guard for MyGuard {
+ type Result = Result<Self, BoxedError>;
+ fn from_request(_request: &Request<()>) -> Self::Result {
+ Ok(MyGuard)
+ }
+}
+
+struct Generic<I> {
+ _inner: I,
+}
+
+impl<I> FromRequest for Generic<I>
+where
+ MyGuard: Guard,
+ <MyGuard as Guard>::Result: IntoFuture<Item = MyGuard, Error = BoxedError>,
+ <<MyGuard as Guard>::Result as IntoFuture>::Future: Send,
+ I: FromRequest<Context = NoContext>,
+{
+ type Future = DefaultFuture<Self, BoxedError>;
+ type Context = NoContext;
+ fn from_request(headers: Request<()>) -> DefaultFuture<Self, BoxedError> {
+ let _future = <MyGuard as Guard>::from_request(&headers)
+ .into_future()
+ .and_then(move |_| {
+ <I as FromRequest>::from_request(headers)
+ .into_future()
+ .and_then(move |fld_inner| Ok(Generic { _inner: fld_inner }).into_future())
+ });
+ panic!();
+ }
+}
+
+fn main() {}