From 6cab00592eb075951231336be37d94ca3bb2df65 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 21 Aug 2025 15:53:18 +0200 Subject: [PATCH] fulfill: dedup newly added obligations --- .../src/solve/fulfill.rs | 19 ++++++++++---- .../const-generics/issues/issue-88119.stderr | 26 +------------------ ...-type-const-bound-usage-fail-2.next.stderr | 8 +----- .../assoc-type-const-bound-usage-fail-2.rs | 2 +- ...oc-type-const-bound-usage-fail.next.stderr | 8 +----- .../assoc-type-const-bound-usage-fail.rs | 2 +- .../const-traits/trait-where-clause-const.rs | 1 - .../trait-where-clause-const.stderr | 14 +--------- 8 files changed, 20 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 3f628d8066203..6f0d484f9dfa2 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -2,6 +2,7 @@ use std::marker::PhantomData; use std::mem; use std::ops::ControlFlow; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::thinvec::ExtractIf; use rustc_hir::def_id::LocalDefId; use rustc_infer::infer::InferCtxt; @@ -19,7 +20,7 @@ use rustc_next_trait_solver::solve::{ }; use rustc_span::Span; use thin_vec::ThinVec; -use tracing::instrument; +use tracing::{debug, instrument}; use self::derive_errors::*; use super::Certainty; @@ -57,6 +58,7 @@ pub struct FulfillmentCtxt<'tcx, E: 'tcx> { #[derive(Default, Debug)] struct ObligationStorage<'tcx> { + dedup: FxHashSet<(ty::ParamEnv<'tcx>, ty::Predicate<'tcx>)>, /// Obligations which resulted in an overflow in fulfillment itself. /// /// We cannot eagerly return these as error so we instead store them here @@ -67,7 +69,14 @@ struct ObligationStorage<'tcx> { } impl<'tcx> ObligationStorage<'tcx> { - fn register( + fn register(&mut self, obligation: PredicateObligation<'tcx>) { + if self.dedup.insert((obligation.param_env, obligation.predicate)) { + self.pending.push((obligation, None)); + } else { + debug!("skipping already registered obligation: {obligation:?}"); + } + } + fn readd_pending( &mut self, obligation: PredicateObligation<'tcx>, stalled_on: Option>>, @@ -161,7 +170,7 @@ where obligation: PredicateObligation<'tcx>, ) { assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots()); - self.obligations.register(obligation, None); + self.obligations.register(obligation); } fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { @@ -205,7 +214,7 @@ where // Only goals proven via the trait solver should be region dependent. Certainty::Yes => {} Certainty::Maybe(_) => { - self.obligations.register(obligation, None); + self.obligations.readd_pending(obligation, None); } } continue; @@ -256,7 +265,7 @@ where infcx.push_hir_typeck_potentially_region_dependent_goal(obligation); } } - Certainty::Maybe(_) => self.obligations.register(obligation, stalled_on), + Certainty::Maybe(_) => self.obligations.readd_pending(obligation, stalled_on), } } diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr index 0aabf48011dcd..0e216043ff433 100644 --- a/tests/ui/const-generics/issues/issue-88119.stderr +++ b/tests/ui/const-generics/issues/issue-88119.stderr @@ -30,18 +30,6 @@ note: required by a bound in `<&T as ConstName>` LL | [(); name_len::()]:, | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` -error[E0275]: overflow evaluating the requirement `[(); name_len::()] well-formed` - --> $DIR/issue-88119.rs:21:10 - | -LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^ - | -note: required by a bound in `<&T as ConstName>` - --> $DIR/issue-88119.rs:21:5 - | -LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` - error[E0275]: overflow evaluating the requirement `&mut T: [const] ConstName` --> $DIR/issue-88119.rs:26:49 | @@ -66,18 +54,6 @@ note: required by a bound in `<&mut T as ConstName>` LL | [(); name_len::()]:, | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` -error[E0275]: overflow evaluating the requirement `[(); name_len::()] well-formed` - --> $DIR/issue-88119.rs:28:10 - | -LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^ - | -note: required by a bound in `<&mut T as ConstName>` - --> $DIR/issue-88119.rs:28:5 - | -LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` - error[E0275]: overflow evaluating the requirement `&&mut u8: ConstName` --> $DIR/issue-88119.rs:33:35 | @@ -90,6 +66,6 @@ error[E0275]: overflow evaluating the requirement `&mut &u8: ConstName` LL | pub const ICE_2: &'static [u8] = <&mut &u8 as ConstName>::NAME_BYTES; | ^^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr index a0474e65efeba..ef533525d7afb 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr @@ -4,12 +4,6 @@ error[E0277]: the trait bound `U: [const] Other` is not satisfied LL | T::Assoc::::func(); | ^^^^^^^^^^^^^ -error[E0277]: the trait bound `U: [const] Other` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5 - | -LL | ::Assoc::::func(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs index 5338c27bedca5..759d1f6ec6cba 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs @@ -24,7 +24,7 @@ const fn fails() { T::Assoc::::func(); //~^ ERROR the trait bound `U: [const] Other` is not satisfied ::Assoc::::func(); - //~^ ERROR the trait bound `U: [const] Other` is not satisfied + //[current]~^ ERROR the trait bound `U: [const] Other` is not satisfied } const fn works() { diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr index 20b01d06e8d5e..7335a2980112a 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr @@ -4,12 +4,6 @@ error[E0277]: the trait bound `T: [const] Trait` is not satisfied LL | T::Assoc::func(); | ^^^^^^^^ -error[E0277]: the trait bound `T: [const] Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:19:5 - | -LL | ::Assoc::func(); - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs index 4940b3a1aa6ce..caef3178a394b 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs @@ -17,7 +17,7 @@ const fn unqualified() { T::Assoc::func(); //~^ ERROR the trait bound `T: [const] Trait` is not satisfied ::Assoc::func(); - //~^ ERROR the trait bound `T: [const] Trait` is not satisfied + //[current]~^ ERROR the trait bound `T: [const] Trait` is not satisfied } const fn works() { diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.rs b/tests/ui/traits/const-traits/trait-where-clause-const.rs index ccb514086cc87..76daabe0a3f37 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-const.rs +++ b/tests/ui/traits/const-traits/trait-where-clause-const.rs @@ -21,7 +21,6 @@ const fn test1() { T::b(); //~^ ERROR the trait bound T::c::(); - //~^ ERROR the trait bound } const fn test2() { diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.stderr b/tests/ui/traits/const-traits/trait-where-clause-const.stderr index 71f9bdff8786e..02d351f7e1a4a 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-const.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause-const.stderr @@ -10,18 +10,6 @@ note: required by a bound in `Foo::b` LL | fn b() where Self: [const] Bar; | ^^^^^^^^^^^ required by this bound in `Foo::b` -error[E0277]: the trait bound `T: [const] Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:23:12 - | -LL | T::c::(); - | ^ - | -note: required by a bound in `Foo::c` - --> $DIR/trait-where-clause-const.rs:16:13 - | -LL | fn c(); - | ^^^^^^^^^^^ required by this bound in `Foo::c` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`.