Skip to content

"higher-ranked lifetime error" on rust 1.90 #147285

@dspyz-matician

Description

@dspyz-matician

This code compiles on 1.89 and then fails to compile with "higher-ranked lifetime error" starting in 1.90

I tried this code:

use hyper_util::rt::TokioIo;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio_rustls::{
    TlsConnector,
    rustls::pki_types::{IpAddr, ServerName},
};
use tonic::transport::{Endpoint, Uri};

pub trait AsyncStream: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static {}
impl<T: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static> AsyncStream for T {}
type BoxStream = Box<dyn AsyncStream>;

fn main() {
    println!("Hello, world!");
}

fn bad_fn(
    connector: TlsConnector,
    endpoint: Endpoint,
) -> impl Future<Output = Result<tonic::transport::Channel, tonic::transport::Error>> + Send {
    async move {
        let rpc_channel = endpoint
            .connect_with_connector(tower::service_fn(move |_: Uri| {
                let connector = connector.clone();
                let box_stream = get_box_stream();
                async move {
                    connector
                        .connect(
                            // This Address does not matter. I am using an ip address as opposed to a hostname to avoid
                            // an attempt at using SNI.
                            ServerName::IpAddress(IpAddr::V4("127.0.0.1".try_into().unwrap())),
                            box_stream,
                        )
                        .await
                        .map(|stream| TokioIo::new(Box::new(stream) as BoxStream))
                }
            }))
            .await?;
        Ok(rpc_channel)
    }
}

fn get_box_stream() -> BoxStream {
    todo!()
}

I expected to see this happen: Anything which compiled before the upgrade I would expect to compile after

Instead, this happened: It doesn't

Meta

rustc --version --verbose:

rustc 1.90.0 (1159e78c4 2025-09-14)
binary: rustc
commit-hash: 1159e78c4747b02ef996e55082b704c09b970588
commit-date: 2025-09-14
host: x86_64-unknown-linux-gnu
release: 1.90.0
LLVM version: 20.1.8
Backtrace

dspyz@davids-desktop:~/mwe$ RUST_BACKTRACE=1 cargo check
    Checking mwe v0.1.0 (/home/dspyz/mwe)
error: higher-ranked lifetime error
  --> src/main.rs:21:5
   |
21 | /     async move {
22 | |         let rpc_channel = endpoint
23 | |             .connect_with_connector(tower::service_fn(move |_: Uri| {
24 | |                 let connector = connector.clone();
...  |
39 | |         Ok(rpc_channel)
40 | |     }
   | |_____^

error: could not compile `mwe` (bin "mwe") due to 1 previous error

git repo here

It gets even weirder. If I change it to a trait method, I get:

the type `TokioIo<Box<dyn AsyncStream>>` does not fulfill the required lifetime

TokioIo<Box<dyn AsyncStream>> is a fully static type so it should fulfill all lifetimes.

use hyper_util::rt::TokioIo;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio_rustls::{
    TlsConnector,
    rustls::pki_types::{IpAddr, ServerName},
};
use tonic::transport::{Endpoint, Uri};

pub trait AsyncStream: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static {}
impl<T: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static> AsyncStream for T {}
type BoxStream = Box<dyn AsyncStream>;

fn main() {
    println!("Hello, world!");
}

trait BadTrait {
    fn bad_fn(
        connector: TlsConnector,
        endpoint: Endpoint,
    ) -> impl Future<Output = Result<tonic::transport::Channel, tonic::transport::Error>> + Send;
}

impl BadTrait for () {
    async fn bad_fn(
        connector: TlsConnector,
        endpoint: Endpoint,
    ) -> Result<tonic::transport::Channel, tonic::transport::Error> {
        let rpc_channel = endpoint
            .connect_with_connector(tower::service_fn(move |_: Uri| {
                let connector = connector.clone();
                let box_stream = get_box_stream();
                async move {
                    connector
                        .connect(
                            // This Address does not matter. I am using an ip address as opposed to a hostname to avoid
                            // an attempt at using SNI.
                            ServerName::IpAddress(IpAddr::V4("127.0.0.1".try_into().unwrap())),
                            box_stream,
                        )
                        .await
                        .map(|stream| TokioIo::new(Box::new(stream) as BoxStream))
                }
            }))
            .await?;
        Ok(rpc_channel)
    }
}

fn get_box_stream() -> BoxStream {
    todo!()
}
error[E0477]: the type `TokioIo<Box<dyn AsyncStream>>` does not fulfill the required lifetime
  --> src/main.rs:25:5
   |
25 | /     async fn bad_fn(
26 | |         connector: TlsConnector,
27 | |         endpoint: Endpoint,
28 | |     ) -> Result<tonic::transport::Channel, tonic::transport::Error> {
   | |___________________________________________________________________^
   |
note: type must satisfy the static lifetime as required by this binding
  --> src/main.rs:21:93
   |
21 |     ) -> impl Future<Output = Result<tonic::transport::Channel, tonic::transport::Error>> + Send;
   |                                                                                             ^^^^

error[E0477]: the type `{async block@src/main.rs:33:17: 33:27}` does not fulfill the required lifetime
  --> src/main.rs:25:5
   |
25 | /     async fn bad_fn(
26 | |         connector: TlsConnector,
27 | |         endpoint: Endpoint,
28 | |     ) -> Result<tonic::transport::Channel, tonic::transport::Error> {
   | |___________________________________________________________________^
   |
note: type must satisfy the static lifetime as required by this binding
  --> src/main.rs:21:93
   |
21 |     ) -> impl Future<Output = Result<tonic::transport::Channel, tonic::transport::Error>> + Send;
   |                                                                                             ^^^^

Metadata

Metadata

Labels

C-bugCategory: This is a bug.P-highHigh priorityS-has-bisectionStatus: A bisection has been found for this issueS-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions