-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Open
Labels
C-bugCategory: This is a bug.Category: This is a bug.P-highHigh priorityHigh priorityS-has-bisectionStatus: A bisection has been found for this issueStatus: A bisection has been found for this issueS-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueStatus: 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.Relevant 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.Performance or correctness regression from one stable version to another.
Description
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
Assignees
Labels
C-bugCategory: This is a bug.Category: This is a bug.P-highHigh priorityHigh priorityS-has-bisectionStatus: A bisection has been found for this issueStatus: A bisection has been found for this issueS-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueStatus: 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.Relevant 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.Performance or correctness regression from one stable version to another.