From c2c9aad3f69515019a849e3c5451e7a1482febb0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Jul 2025 19:20:05 +0000 Subject: [PATCH 1/2] Make sure that users don't take region obligations in a snapshot --- compiler/rustc_infer/src/infer/outlives/obligations.rs | 1 + compiler/rustc_infer/src/infer/snapshot/undo_log.rs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index f272052aaa544..43504bd77c18b 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -166,6 +166,7 @@ impl<'tcx> InferCtxt<'tcx> { /// Trait queries just want to pass back type obligations "as is" pub fn take_registered_region_obligations(&self) -> Vec> { + assert!(!self.in_snapshot(), "cannot take registered region obligations in a snapshot"); std::mem::take(&mut self.inner.borrow_mut().region_obligations) } diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs index 6193f35f3eb60..34e649afedc69 100644 --- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs +++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs @@ -1,3 +1,4 @@ +use std::assert_matches::assert_matches; use std::marker::PhantomData; use rustc_data_structures::undo_log::{Rollback, UndoLogs}; @@ -73,7 +74,8 @@ impl<'tcx> Rollback> for InferCtxtInner<'tcx> { } UndoLog::ProjectionCache(undo) => self.projection_cache.reverse(undo), UndoLog::PushTypeOutlivesConstraint => { - self.region_obligations.pop(); + let popped = self.region_obligations.pop(); + assert_matches!(popped, Some(_), "pushed region constraint but could not pop it"); } } } From f6f2f83043001592f656fa988ef6015694d52ee9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Jul 2025 19:22:09 +0000 Subject: [PATCH 2/2] Simplify make_query_region_constraints --- .../src/type_check/constraint_conversion.rs | 3 +++ .../src/infer/canonical/query_response.rs | 22 +++++++++---------- .../src/solve/delegate.rs | 8 +------ .../src/traits/query/type_op/custom.rs | 5 +---- 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 8ed552cfa4f00..ca636a8c9992c 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -159,6 +159,9 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { } GenericArgKind::Type(mut t1) => { + // Scraped constraints may have had inference vars. + t1 = self.infcx.resolve_vars_if_possible(t1); + // Normalize the type we receive from a `TypeOutlives` obligation // in the new trait solver. if infcx.next_trait_solver() { diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 008ef6900089f..d5d49e3188aa8 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -13,7 +13,6 @@ use std::iter; use rustc_index::{Idx, IndexVec}; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::bug; -use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable}; use tracing::{debug, instrument}; @@ -23,7 +22,9 @@ use crate::infer::canonical::{ QueryRegionConstraints, QueryResponse, }; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; -use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin}; +use crate::infer::{ + DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin, TypeOutlivesConstraint, +}; use crate::traits::query::NoSolution; use crate::traits::{ObligationCause, PredicateObligations, ScrubbedTraitError, TraitEngine}; @@ -117,13 +118,7 @@ impl<'tcx> InferCtxt<'tcx> { let region_obligations = self.take_registered_region_obligations(); debug!(?region_obligations); let region_constraints = self.with_region_constraints(|region_constraints| { - make_query_region_constraints( - tcx, - region_obligations - .iter() - .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())), - region_constraints, - ) + make_query_region_constraints(tcx, region_obligations, region_constraints) }); debug!(?region_constraints); @@ -570,7 +565,7 @@ impl<'tcx> InferCtxt<'tcx> { /// creates query region constraints. pub fn make_query_region_constraints<'tcx>( tcx: TyCtxt<'tcx>, - outlives_obligations: impl Iterator, ty::Region<'tcx>, ConstraintCategory<'tcx>)>, + outlives_obligations: Vec>, region_constraints: &RegionConstraintData<'tcx>, ) -> QueryRegionConstraints<'tcx> { let RegionConstraintData { constraints, verifys } = region_constraints; @@ -599,8 +594,11 @@ pub fn make_query_region_constraints<'tcx>( }; (constraint, origin.to_constraint_category()) }) - .chain(outlives_obligations.map(|(ty, r, constraint_category)| { - (ty::OutlivesPredicate(ty.into(), r), constraint_category) + .chain(outlives_obligations.into_iter().map(|obl| { + ( + ty::OutlivesPredicate(obl.sup_type.into(), obl.sub_region), + obl.origin.to_constraint_category(), + ) })) .collect(); diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index d22529d56a468..1a24254d57fbe 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -213,13 +213,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< // inside of a `probe` whenever we have multiple choices inside of the solver. let region_obligations = self.0.inner.borrow().region_obligations().to_owned(); let region_constraints = self.0.with_region_constraints(|region_constraints| { - make_query_region_constraints( - self.tcx, - region_obligations - .iter() - .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())), - region_constraints, - ) + make_query_region_constraints(self.tcx, region_obligations, region_constraints) }); let mut seen = FxHashSet::default(); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index 18010603286d1..3b549244431d2 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -103,10 +103,7 @@ where let region_constraint_data = infcx.take_and_reset_region_constraints(); let region_constraints = query_response::make_query_region_constraints( infcx.tcx, - region_obligations - .iter() - .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())) - .map(|(ty, r, cc)| (infcx.resolve_vars_if_possible(ty), r, cc)), + region_obligations, ®ion_constraint_data, );