Skip to content

Skip redundant next-solver fulfillment scans - #161477

Closed
anonrig wants to merge 2 commits into
rust-lang:mainfrom
anonrig:next-solver-skip-redundant-fulfillment
Closed

Skip redundant next-solver fulfillment scans#161477
anonrig wants to merge 2 commits into
rust-lang:mainfrom
anonrig:next-solver-skip-redundant-fulfillment

Conversation

@anonrig

@anonrig anonrig commented Aug 21, 2026

Copy link
Copy Markdown

Refs #159933

r? lcnr

Next-solver fulfillment still walks the entire pending queue on every try_evaluate_obligations even when remaining goals are stalled on type variables older than anything that just changed.

This adds a conservative skip:

  • record the smallest type vid equated, sub-unified, or instantiated since the last fulfillment pass (snapshot-aware via the infer undo log)
  • record the largest stalled type vid / sub-root among pending goals
  • skip the retain_mut walk when every pending goal is type-var-only, opaque storage is unchanged, and every infer change is to a newer vid

Int/float/const stalls, mixed opaque counts, overflow, and -Zdisable-fast-paths keep the existing path.

Alternative to #161348: one min/max vid pair instead of two revisions plus an FxIndexSet of sub-roots.

On the #159933 reproducer (--crate-type=lib --edition=2024 --emit=metadata):

N before after
2,000 3.484s 1.078s
4,000 13.459s 4.061s

When every pending goal is stalled only on type inference variables
older than any vid changed since the last fulfillment pass, skip
walking the pending queue. This removes the quadratic rescan from
large typeck bodies (rustc#159933) without tracking a set of vids.

Int/float/const stalls and opaque-storage count mismatches still
take the existing retain_mut path. -Zdisable-fast-paths disables
the skip.
@rustbot

rustbot commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred to the core trait solver

cc @rust-lang/initiative-trait-system-refactor

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Aug 21, 2026
@rustbot

rustbot commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the pull request, and welcome! The Rust Project has assigned @lcnr (or someone else) to review your changes, you should hear from them (or someone else) within the next two weeks.

Please see the contribution instructions for more information.

@rust-log-analyzer

This comment has been minimized.

typos already allowlists 'unstalled'; the verb form trips CI.
@lqd

lqd commented Aug 21, 2026

Copy link
Copy Markdown
Member

Could you say if https://github.com/rust-lang/rust/blob/main/AGENTS.md works with Cursor?

@anonrig

anonrig commented Aug 21, 2026

Copy link
Copy Markdown
Author

Could you say if https://github.com/rust-lang/rust/blob/main/AGENTS.md works with Cursor?

Unfortunately I'm AFK and cursor remote agents doesn't support skills.

@lqd

lqd commented Aug 21, 2026

Copy link
Copy Markdown
Member

Check this out then, which is the welcome bot's message posted on your other Cursor PR:

Please see the contribution instructions and our LLM policy for more information.

@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job aarch64-gnu-llvm-21-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
---- [ui] tests/ui/traits/next-solver/generalize/subtype-obligations-bivariant-args.rs#next stdout ----

error in revision `next`: test compilation failed although it shouldn't!
status: exit status: 101
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/traits/next-solver/generalize/subtype-obligations-bivariant-args.rs" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--cfg" "next" "--check-cfg" "cfg(test,FALSE,old,next)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/ui/traits/next-solver/generalize/subtype-obligations-bivariant-args.next" "-Znext-solver=coherence" "-A" "unused" "-W" "unused_attributes" "-A" "internal_features" "-A" "incomplete_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/aarch64-unknown-linux-gnu/native/rust-test-helpers" "-Znext-solver"
stdout: none
--- stderr -------------------------------
##[error]error: internal compiler error: compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:121:17: did not expect successful goal when collecting ambiguity errors for `Binder { value: SubtypePredicate { a_is_expected: false, a: S/#0, b: S/#0 }, bound_vars: [] }`
  --> /checkout/tests/ui/traits/next-solver/generalize/subtype-obligations-bivariant-args.rs:28:17
   |
LL |           let x = match self {
   |  _________________^
LL | |             State::Active { .. } => None,
---
thread 'rustc' (169922) panicked at compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:121:17:
Box<dyn Any>
stack backtrace:
   0: std::panicking::begin_panic::<rustc_errors::ExplicitBug>
   1: <rustc_errors::diagnostic::BugAbort as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
   2: <rustc_errors::DiagCtxtHandle>::span_bug::<rustc_span::span_encoding::Span, alloc::string::String>
   3: rustc_middle::util::bug::opt_span_bug_fmt::<rustc_span::span_encoding::Span>::{closure#0}
   4: rustc_middle::ty::context::tls::with_opt::<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}
   5: rustc_middle::ty::context::tls::with_context_opt::<rustc_middle::ty::context::tls::with_opt<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}, !>
   6: rustc_middle::util::bug::span_bug_fmt::<rustc_span::span_encoding::Span>
   7: <rustc_infer::infer::InferCtxt>::probe::<(rustc_trait_selection::traits::FulfillmentErrorCode, bool), rustc_trait_selection::solve::fulfill::derive_errors::fulfillment_error_for_stalled::{closure#0}>
   8: rustc_trait_selection::solve::fulfill::derive_errors::fulfillment_error_for_stalled
   9: <rustc_trait_selection::traits::FulfillmentError as rustc_infer::traits::engine::FromSolverError<rustc_trait_selection::solve::fulfill::NextSolverError>>::from_solver_error
  10: <core::iter::adapters::map::Map<core::iter::adapters::chain::Chain<core::iter::adapters::map::Map<thin_vec::Drain<(rustc_infer::traits::Obligation<rustc_middle::ty::predicate::Predicate>, core::option::Option<rustc_type_ir::solve::GoalStalledOn<rustc_middle::ty::context::TyCtxt>>)>, rustc_trait_selection::solve::fulfill::collect_remaining_errors_impl<rustc_trait_selection::traits::FulfillmentError>::{closure#0}>, core::iter::adapters::map::Map<alloc::vec::drain::Drain<rustc_infer::traits::Obligation<rustc_middle::ty::predicate::Predicate>>, rustc_trait_selection::solve::fulfill::collect_remaining_errors_impl<rustc_trait_selection::traits::FulfillmentError>::{closure#1}>>, rustc_trait_selection::solve::fulfill::collect_remaining_errors_impl<rustc_trait_selection::traits::FulfillmentError>::{closure#2}> as core::iter::traits::iterator::Iterator>::next
  11: rustc_trait_selection::solve::fulfill::collect_remaining_errors_impl::<rustc_trait_selection::traits::FulfillmentError>
  12: <rustc_hir_typeck::fn_ctxt::FnCtxt>::report_ambiguity_errors
  13: rustc_hir_typeck::typeck_with_inspect
      [... omitted 2 frames ...]
  14: <rustc_middle::query::plumbing::TyCtxtEnsureOk>::typeck::<rustc_span::def_id::LocalDefId>
  15: <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners::<rustc_hir_analysis::check_crate::{closure#1}>::{closure#0}
  16: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_data_structures::sync::parallel::par_for_each_in<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners<rustc_hir_analysis::check_crate::{closure#1}>::{closure#0}>::{closure#0}::{closure#1}::{closure#0}>>
  17: rustc_data_structures::sync::parallel::par_for_each_in::<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners<rustc_hir_analysis::check_crate::{closure#1}>::{closure#0}>
  18: rustc_hir_analysis::check_crate
  19: rustc_interface::passes::analysis
      [... omitted 2 frames ...]
  20: std::panicking::catch_unwind::<core::option::Option<rustc_interface::queries::Linker>, core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}>::{closure#2}::{closure#0}>>
  21: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<<rustc_middle::ty::context::GlobalCtxt>::enter<rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}>::{closure#2}, core::option::Option<rustc_interface::queries::Linker>>::{closure#1}, core::option::Option<rustc_interface::queries::Linker>>::{closure#0}, core::option::Option<rustc_interface::queries::Linker>>
  22: <rustc_middle::ty::context::TyCtxt>::create_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}>::{closure#2}>
  23: rustc_interface::passes::create_and_enter_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}>
  24: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#2}::{closure#0}>>
  25: rustc_interface::interface::run_compiler::<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#2}
  26: rustc_span::create_session_globals_then::<(), rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#2}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}::{closure#0}>
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: please make sure that you have updated to the latest nightly

note: rustc 1.100.0-nightly (5f026ab1b 2026-08-21) running on aarch64-unknown-linux-gnu

note: compiler flags: -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/cargo -Z ignore-directory-in-diagnostics-source-blocks=/checkout/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -Z next-solver=coherence -C rpath -C debuginfo=0 -Z next-solver

query stack during panic:
#0 [typeck_root] type-checking `<impl at /checkout/tests/ui/traits/next-solver/generalize/subtype-obligations-bivariant-args.rs:23:1: 25:27>::foo`
#1 [analysis] running analysis passes on crate `subtype_obligations_bivariant_args`
end of query stack
##[error]error: internal compiler error: compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:121:17: did not expect successful goal when collecting ambiguity errors for `Binder { value: CoercePredicate { a: Foo<u32, u32>, b: Foo<u32, u32> }, bound_vars: [] }`
  --> /checkout/tests/ui/traits/next-solver/generalize/subtype-obligations-bivariant-args.rs:48:13
   |
LL |     let x = None.unwrap();
   |             ^^^^^^^^^^^^^


thread 'rustc' (169922) panicked at compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:121:17:
Box<dyn Any>
stack backtrace:
   0: std::panicking::begin_panic::<rustc_errors::ExplicitBug>
   1: <rustc_errors::diagnostic::BugAbort as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
   2: <rustc_errors::DiagCtxtHandle>::span_bug::<rustc_span::span_encoding::Span, alloc::string::String>
   3: rustc_middle::util::bug::opt_span_bug_fmt::<rustc_span::span_encoding::Span>::{closure#0}
   4: rustc_middle::ty::context::tls::with_opt::<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}
   5: rustc_middle::ty::context::tls::with_context_opt::<rustc_middle::ty::context::tls::with_opt<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}, !>
   6: rustc_middle::util::bug::span_bug_fmt::<rustc_span::span_encoding::Span>
   7: <rustc_infer::infer::InferCtxt>::probe::<(rustc_trait_selection::traits::FulfillmentErrorCode, bool), rustc_trait_selection::solve::fulfill::derive_errors::fulfillment_error_for_stalled::{closure#0}>
   8: rustc_trait_selection::solve::fulfill::derive_errors::fulfillment_error_for_stalled
   9: <rustc_trait_selection::traits::FulfillmentError as rustc_infer::traits::engine::FromSolverError<rustc_trait_selection::solve::fulfill::NextSolverError>>::from_solver_error
  10: <core::iter::adapters::map::Map<core::iter::adapters::chain::Chain<core::iter::adapters::map::Map<thin_vec::Drain<(rustc_infer::traits::Obligation<rustc_middle::ty::predicate::Predicate>, core::option::Option<rustc_type_ir::solve::GoalStalledOn<rustc_middle::ty::context::TyCtxt>>)>, rustc_trait_selection::solve::fulfill::collect_remaining_errors_impl<rustc_trait_selection::traits::FulfillmentError>::{closure#0}>, core::iter::adapters::map::Map<alloc::vec::drain::Drain<rustc_infer::traits::Obligation<rustc_middle::ty::predicate::Predicate>>, rustc_trait_selection::solve::fulfill::collect_remaining_errors_impl<rustc_trait_selection::traits::FulfillmentError>::{closure#1}>>, rustc_trait_selection::solve::fulfill::collect_remaining_errors_impl<rustc_trait_selection::traits::FulfillmentError>::{closure#2}> as core::iter::traits::iterator::Iterator>::next
  11: rustc_trait_selection::solve::fulfill::collect_remaining_errors_impl::<rustc_trait_selection::traits::FulfillmentError>
  12: <rustc_hir_typeck::fn_ctxt::FnCtxt>::report_ambiguity_errors
  13: rustc_hir_typeck::typeck_with_inspect
      [... omitted 2 frames ...]
  14: <rustc_middle::query::plumbing::TyCtxtEnsureOk>::typeck::<rustc_span::def_id::LocalDefId>
  15: <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners::<rustc_hir_analysis::check_crate::{closure#1}>::{closure#0}
  16: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_data_structures::sync::parallel::par_for_each_in<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners<rustc_hir_analysis::check_crate::{closure#1}>::{closure#0}>::{closure#0}::{closure#1}::{closure#0}>>
  17: rustc_data_structures::sync::parallel::par_for_each_in::<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners<rustc_hir_analysis::check_crate::{closure#1}>::{closure#0}>
  18: rustc_hir_analysis::check_crate
  19: rustc_interface::passes::analysis
      [... omitted 2 frames ...]
  20: std::panicking::catch_unwind::<core::option::Option<rustc_interface::queries::Linker>, core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}>::{closure#2}::{closure#0}>>
  21: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<<rustc_middle::ty::context::GlobalCtxt>::enter<rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}>::{closure#2}, core::option::Option<rustc_interface::queries::Linker>>::{closure#1}, core::option::Option<rustc_interface::queries::Linker>>::{closure#0}, core::option::Option<rustc_interface::queries::Linker>>
  22: <rustc_middle::ty::context::TyCtxt>::create_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}>::{closure#2}>
  23: rustc_interface::passes::create_and_enter_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}>
  24: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#2}::{closure#0}>>
  25: rustc_interface::interface::run_compiler::<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#2}
  26: rustc_span::create_session_globals_then::<(), rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#2}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}::{closure#0}>
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: please make sure that you have updated to the latest nightly

note: rustc 1.100.0-nightly (5f026ab1b 2026-08-21) running on aarch64-unknown-linux-gnu

note: compiler flags: -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/cargo -Z ignore-directory-in-diagnostics-source-blocks=/checkout/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -Z next-solver=coherence -C rpath -C debuginfo=0 -Z next-solver

query stack during panic:
#0 [typeck_root] type-checking `main`
#1 [analysis] running analysis passes on crate `subtype_obligations_bivariant_args`
end of query stack
error: aborting due to 2 previous errors
------------------------------------------

---- [ui] tests/ui/traits/next-solver/generalize/subtype-obligations-bivariant-args.rs#next stdout end ----

@lqd

lqd commented Aug 21, 2026

Copy link
Copy Markdown
Member

Thanks for the pull request, and welcome! The Rust Project has assigned @lcnr (or someone else) to review your changes, you should hear from them (or someone else) within the next two weeks.

Please see the contribution instructions for more information.

Note for @rust-lang/triagebot: the above is missing the LLM policy link that is present e.g. in #161481 (comment)

@anonrig anonrig closed this Aug 21, 2026
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 21, 2026
@Urgau

Urgau commented Aug 21, 2026

Copy link
Copy Markdown
Member

Note for @rust-lang/triagebot: the above is missing the LLM policy link that is present e.g. in #161481 (comment)

The PR adding it (#161393) was only merged 35 minutes ago. The welcome message was posted 1 hour ago.

@lqd

lqd commented Aug 21, 2026

Copy link
Copy Markdown
Member

thanks @Urgau <3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants