Repository navigation
Open
Labels
C-bugCategory: This is a bug.Category: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️T-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.needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triagingThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
Description
rustc version
rustc 1.98.1 (48a229cea 2026-09-01)
cargo 1.98.1 (797e8a9bc 2026-08-05)
aarch64-apple-darwin
Compiler flags
--crate-type bin -C embed-bitcode=no -C debuginfo=2 -C split-debuginfo=unpacked -C incremental=[REDACTED]
(Note: some flags are provided/hidden by cargo; run with RUST_BACKTRACE=1 for the full query stack.)
Error output
The build first reports a (legitimate) lifetime error, then rustc panics with an
internal compiler error during incremental compilation:
error[E0597]: `pool` does not live long enough
--> src/api.rs:38:21
|
37 | async fn get_stores(State(pool): State<SqlitePool>) -> Result<Json<Vec<Store>>, ApiError> {
| ---- binding `pool` declared here
38 | Store::find_all(&pool).await.map(Json).map_err(Into::into)
| ----------------^^^^^-------------------------------------
| | |
| | borrowed value does not live long enough
| argument requires that `pool` is borrowed for `'static`
39 | }
| - `pool` dropped here while still borrowed
|
note: requirement that the value outlives `'static` introduced here
--> /Users/cztomsik/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/result.rs:962:12
|
962 | O: [const] FnOnce(E) -> F + [const] Destruct,
| ^^^^^^^^^^^^^^^^^^^^^^
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
--> src/api.rs:38:5
|
38 | Store::find_all(&pool).await.map(Json).map_err(Into::into)
| ^^^^^^^^^^^^^^^^^^^^^^
help: use the precise capturing `use<...>` syntax to make the captures explicit
--> src/db.rs:15:78
|
15 | pub async fn find_all(pool: &SqlitePool) -> Result<Vec<Store>, impl Error + use<>> {
| +++++++
error: internal compiler error: encountered incremental compilation error with evaluate_obligation(72315dfcc89c95ea-6ce2a7b955f286e6)
|
= note: please follow the instructions below to create a bug report with the provided information
= note: for incremental compilation bugs, having a reproduction is vital
= note: an ideal reproduction consists of the code before and some patch that then triggers the bug when applied and compiled again
= note: as a workaround, you can run `cargo clean -p bo_main` or `cargo clean` to allow your project to compile
thread 'rustc' (896020) panicked at /rustc-dev/48a229ceaefd4985c50990b14116b6d856af0985/compiler/rustc_middle/src/verify_ich.rs:82:9:
Found unstable fingerprints for evaluate_obligation(72315dfcc89c95ea-6ce2a7b955f286e6): Ok(EvaluatedToOk)
stack backtrace:
0: 0x10ae5688c - <<std[5d97c59e5e5fafcc]::sys::backtrace::BacktraceLock>::print::DisplayBacktrace as core[663bb9e1522ba5ef]::fmt::Display>::fmt
1: 0x108123e94 - core[663bb9e1522ba5ef]::fmt::write
2: 0x10ae6d5ec - <std[5d97c59e5e5fafcc]::sys::stdio::unix::Stderr as core[663bb9e1522ba5ef]::io::Write>::write_fmt
3: 0x10ae2b1b8 - std[5d97c59e5e5fafcc]::panicking::default_hook::{closure#0}
4: 0x10ae47d2c - std[5d97c59e5e5fafcc]::panicking::default_hook
5: 0x10ae482f8 - std[5d97c59e5e5fafcc]::panicking::update_hook::<alloc[cc4db322bb1ac55d]::boxed::Box<rustc_driver_impl[6570ee80102c2b15]::install_ice_hook::{closure#1}>>::{closure#0}
6: 0x10ae482f8 - std[5d97c59e5e5fafcc]::panicking::panic_with_hook
7: 0x10ae2b23c - std[5d97c59e5e5fafcc]::panicking::panic_handler::{closure#0}
8: 0x10ae21b1c - <std[5d97c59e5e5fafcc]::sys::backtrace::__rust_end_short_backtrace::<std[5d97c59e5e5fafcc]::panicking::panic_handler::{closure#0}, !>
9: 0x10ae2c764 - __rustc[100742bb89c490cb]::rust_begin_unwind
10: 0x10af12760 - core[663bb9e1522ba5ef]::panicking::panic_fmt
11: 0x10aff3040 - rustc_middle[5cf943406889ed]::verify_ich::incremental_verify_ich_failed
12: 0x10a20690c - rustc_middle[5cf943406889ed]::verify_ich::incremental_verify_ich::<rustc_middle[5cf943406889ed]::query::erase::ErasedData<[u8; 2usize]>>
13: 0x10a2801b0 - rustc_query_impl[2b0e3be29859969b]::execution::try_execute_query::<rustc_middle[5cf943406889ed]::query::caches::DefaultCache<rustc_type_ir[a678fd3fb3f11]::canonical::CanonicalQueryInput<rustc_middle[5cf943406889ed]::ty::context::TyCtxt, rustc_middle[5cf943406889ed]::ty::ParamEnvAnd<rustc_middle[5cf943406889ed]::ty::predicate::Predicate>>, rustc_middle[5cf943406889ed]::query::erase::ErasedData<[u8; 2usize]>>, true>
14: 0x10a421960 - rustc_query_impl[2b0e3be29859969b]::query_impl::evaluate_obligation::execute_query_incr::__rust_end_short_backtrace
15: 0x10abd40b8 - <rustc_infer[1800e56c0cab7b30]::infer::InferCtxt as rustc_trait_selection[dd66be20177c957b]::traits::query::evaluate_obligation::InferCtxtExt>::evaluate_obligation
16: 0x10abd4474 - <rustc_infer[1800e56c0cab7b30]::infer::InferCtxt as rustc_trait_selection[dd66be20177c957b]::traits::query::evaluate_obligation::InferCtxtExt>::evaluate_obligation_no_overflow
17: 0x10ab3e19c - <rustc_trait_selection[dd66be20177c957b]::traits::fulfill::FulfillProcessor>::process_trait_obligation
18: 0x10abf214c - <rustc_trait_selection[dd66be20177c957b]::traits::fulfill::FulfillProcessor as rustc_data_structures[566e056540f4032a]::obligation_forest::ObligationProcessor>::process_obligation
19: 0x10a961608 - <rustc_data_structures[566e056540f4032a]::obligation_forest::ObligationForest<rustc_trait_selection[dd66be20177c957b]::traits::fulfill::PendingPredicateObligation>>::process_obligations::<rustc_trait_selection[dd66be20177c957b]::traits::fulfill::FulfillProcessor>
20: 0x1093c95e8 - <rustc_trait_selection[dd66be20177c957b]::traits::fulfill::FulfillmentContext<rustc_trait_selection[dd66be20177c957b]::traits::FulfillmentError> as rustc_infer[1800e56c0cab7b30]::traits::engine::TraitEngine<rustc_trait_selection[dd66be20177c957b]::traits::FulfillmentError>>::try_evaluate_obligations
21: 0x109327c6c - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_argument_types
22: 0x1092e869c - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::confirm_builtin_call
23: 0x1092cf8fc - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_expr_kind
24: 0x1092e52dc - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
25: 0x109327f70 - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_argument_types
26: 0x1092ccd9c - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_expr_kind
27: 0x1092e52dc - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
28: 0x1092c453c - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_expr_kind
29: 0x1092e52dc - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
30: 0x109298a08 - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_expr_block::{closure#0}
31: 0x1093253e8 - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_expr_block
32: 0x1092e52dc - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
33: 0x1092e3210 - <rustc_hir_typeck[ea3a3b088ed04c48]::fn_ctxt::FnCtxt>::check_return_or_body_tail
34: 0x1093aab14 - rustc_hir_typeck[ea3a3b088ed04c48]::check::check_fn
35: 0x10928eaa8 - rustc_hir_typeck[ea3a3b088ed04c48]::typeck_with_inspect::{closure#0}
36: 0x1092b586c - rustc_hir_typeck[ea3a3b088ed04c48]::typeck_root
...
query stack during panic:
#0 [evaluate_obligation] evaluating trait selection obligation `core::option::Option<sqlx_core::pool::Pool<sqlx_sqlite::database::Sqlite>>: core::marker::Send`
#1 [typeck_root] type-checking `api::router`
... and 1 other queries... use `env RUST_BACKTRACE=1` to see the full query stack
error: could not compile `bo_main` (bin "bo_main") due to 3 previous errors
Workaround
cargo clean -p bo_main (or a full cargo clean) makes the project compile again
(the remaining E0597 is a genuine, expected user error — see below).
Reproduction steps
- Use the crate below (
Cargo.toml+ 4 source files, all inline at the bottom). cargo build— the crate does not compile:Store::find_allreturns
Result<_, impl Error>where the anonymous error captures a non-'static
lifetime derived from&pool(Rust 2024impl Traitcapture rules). This
produces the E0597 error above.- Run
cargo buildagain (incremental) — rustc panics with the ICE
"Found unstable fingerprints for evaluate_obligation".
The combination that appears to trigger the ICE:
edition = "2024"- an
async fnwhose return type containsimpl Traitwith the 2024
(all-capture) lifetime rules, producing a type/lifetime error during
typeck, followed by a second incremental compilation. - The failing obligation is an auto-trait (
Send) evaluation, consistent
with async-fn desugaring (polling ofasync fnbodies requiresSend).
Expected behavior
rustc should report the (real) lifetime error without panicking; the
evaluate_obligation fingerprint should be stable across incremental
compilations.
Crate: Cargo.toml
[package]
name = "bo_main"
version = "0.1.0"
edition = "2024"
[dependencies]
axum = { version = "0.8.9", features = ["macros"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
anyhow = "1"
serde_json = "1"
serde = { version = "1", features = ["derive"] }
sqlx = { version = "0.9.0", features = ["sqlite", "runtime-tokio"] }Crate: src/main.rs
mod api;
mod config;
mod db;
use config::Config;
fn env_flag(name: &str) -> bool {
std::env::var(name).is_ok_and(|v| v == "1")
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let data = std::fs::read_to_string("config.json")?;
let config: Config = serde_json::from_str(&data)?;
println!("config: {:?}", config);
let pool = db::init(&config.db_path).await?;
if env_flag("MIGRATE") {
db::migrate(&pool).await?;
println!("database migrations applied");
}
if env_flag("SEED") {
db::seed(&pool).await?;
println!("database seeded");
}
// TODO: config
let addr = "127.0.0.1:3000";
let listener = tokio::net::TcpListener::bind(addr).await?;
println!("bo_admin listening on http://{}", addr);
axum::serve(listener, api::router(pool)).await?;
Ok(())
}Crate: src/api.rs
use crate::db::Store;
use axum::extract::State;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::routing::get;
use axum::{Json, Router};
use sqlx::SqlitePool;
struct ApiError(anyhow::Error);
impl<E> From<E> for ApiError
where
E: Into<anyhow::Error>,
{
fn from(err: E) -> Self {
Self(err.into())
}
}
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Something went wrong: {}", self.0),
)
.into_response()
}
}
pub fn router(pool: SqlitePool) -> axum::Router {
Router::new()
.route("/stores", get(get_stores))
.with_state(pool)
}
#[axum::debug_handler]
async fn get_stores(State(pool): State<SqlitePool>) -> Result<Json<Vec<Store>>, ApiError> {
Store::find_all(&pool).await.map(Json).map_err(Into::into)
}Crate: src/db.rs
use serde::Serialize;
use sqlx::Executor;
use sqlx::FromRow;
use sqlx::SqlitePool;
use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions};
use std::error::Error;
#[derive(Debug, Clone, Serialize, FromRow)]
pub struct Store {
pub id: Option<i64>,
pub name: String,
pub url: String,
}
impl Store {
pub async fn find_all(pool: &SqlitePool) -> Result<Vec<Store>, impl Error> {
sqlx::query_as::<_, Store>("SELECT id, name, url FROM store")
.fetch_all(pool)
.await
}
}
pub async fn init(db_path: &str) -> anyhow::Result<SqlitePool> {
// TODO: mkdir -p parent dir from db_path
let options = SqliteConnectOptions::default()
.filename(db_path)
.create_if_missing(true)
.journal_mode(SqliteJournalMode::Wal)
.foreign_keys(true);
let pool = SqlitePoolOptions::new()
.max_connections(5)
.connect_with(options)
.await?;
Ok(pool)
}
pub async fn migrate(pool: &SqlitePool) -> anyhow::Result<()> {
// TODO: real migration, once we get out of the PoC phase.
let sql = r#"
...
"#;
pool.execute(sql).await?;
Ok(())
}
pub async fn seed(pool: &SqlitePool) -> anyhow::Result<()> {
todo!()
}Crate: src/config.rs
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub struct Config {
pub db_path: String,
}Metadata
Metadata
Assignees
Labels
C-bugCategory: This is a bug.Category: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️T-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.needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triagingThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
Activity
Dnreikronos commentedon Sep 26, 2026
Hey, I spent some time on this and got it to reproduce locally, on stable 1.98.1 (same build as yours) and on nightly-2026-08-10.
At first building the broken code twice didn't ICE for me, I just got the E0597 both times. What does trigger it is having a build that actually compiles first and then switching to the broken version. So if
find_allstarts out returningResult<Vec<Store>, impl Error + use<>>(or plainsqlx::Error), you build once, then change it to justimpl Errorand build again, and it panics on the sameOption<Pool<Sqlite>>: Sendquery from the report. I'm guessing that's pretty much what happened on your side while editing. It also still happens without#[axum::debug_handler]btw.Newer nightlies don't ICE anymore, so I bisected that and it points to #160619, which turned the next solver on by default on nightly. So nightly doesn't really fix it, it just stops using the old solver in typeck, and
evaluate_obligationonly gets used by the old solver. To double check I built current main with-Znext-solver=coherenceso typeck goes back to the old solver, and it ICEs the same way. So stable and beta are still hit by this.After that I looked around and this seems to be a duplicate of #157854, which already has a smaller repro and the fixed-by-next-solver label. Someone there bisected the original regression to #155355, the change that lets the old solver save cycle results in the global cache once an error has happened. That makes the result depend on whether an error showed up earlier in the session, and incremental catches the mismatch on the next build. I think that matches what's going on here too, since the E0597 comes from borrowck of
get_stores, and that borrowck runs in the middle of the trait solving for theSendcheck.Personally I think closing this as a duplicate of #157854 is fine, the next solver is where things are heading and I get the feeling nobody wants to mess with the old solver's caching again. It does kinda suck for people on stable in the meantime though, there are quite a few reports of this exact ICE. Until then
cargo clean -p bo_maingets you unstuck, like the ICE message says.cztomsik commentedon Sep 27, 2026
Yes, long story short I've been trying some stupid things (mostly refreshing my memory, I've not been around Rust for 3+ years I think) and changing signatures, and it worked before, and then at some point, compiler panicked and only
cargo cleanhelped. I am not experienced with compiler dev enough to tell if it's duplicate, but feel free to close this. I just wanted to let somebody know (before I clean the evidence).and IIRC, yes, it was after adding
impl Erroras you say and I am not stuck anymore, I simply changed signatures to returnsqlx::Errorinstead, which is what I should do anyway. But thank you for looking into this quickly :)