Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b90709a
add higher ranked assumptions v2 flag
BoxyUwU Apr 28, 2026
a4649b4
new region constraint representation
BoxyUwU Apr 28, 2026
2bee929
compute and track assumptions on entered binders
BoxyUwU Apr 28, 2026
48a0966
produce new region constraints
BoxyUwU Apr 28, 2026
045c85f
destructure in root universe
BoxyUwU Apr 27, 2026
dd9d787
rewrite region constraints to smaller universes
BoxyUwU Apr 28, 2026
e2007e8
s/solve/solver typo
BoxyUwU May 1, 2026
2b11dd5
readd comments to enter_forall
BoxyUwU May 1, 2026
9d6f728
FIXME for fast paths
BoxyUwU May 1, 2026
c31f98a
incorrect binder handling FIXME
BoxyUwU May 1, 2026
c3e191b
better where clause
BoxyUwU May 1, 2026
7568093
AliasTyOutlivesViaEnv
BoxyUwU May 1, 2026
f68d07c
s/solve/solver typo
BoxyUwU May 1, 2026
b77217a
AliasTyOutlivesViaEnv
BoxyUwU May 1, 2026
5c5f53b
handle wf(?x) assumptions
BoxyUwU May 1, 2026
4d64eb3
use Assumptions::new
BoxyUwU May 1, 2026
4366098
unreused MaxUniverse visitor
BoxyUwU May 1, 2026
fe6a810
region_assumptions_from_term
BoxyUwU May 1, 2026
7284693
s/universe assumptions/placeholder assumptions
BoxyUwU May 1, 2026
522eb7b
match not iflet
BoxyUwU May 1, 2026
07f87d2
x fmt
BoxyUwU May 1, 2026
52153f0
make region constraints in responses be an enum of old/new style
BoxyUwU May 1, 2026
8be3f42
eagerly_handle_placeholders return type fix
BoxyUwU May 1, 2026
c2ce7bf
eval_ctxt/solver_region_constraints.rs
BoxyUwU May 1, 2026
038ae08
eval_ctxt/solver_region_constraints import nits
BoxyUwU May 1, 2026
42dbf64
erased regions are cause for alarm
BoxyUwU May 1, 2026
2135f41
simpler evaluation of solver region constraints
BoxyUwU May 1, 2026
4e5e197
better diagnostics (?)
BoxyUwU May 1, 2026
2c25e21
better externregionconstraint thingy
BoxyUwU May 1, 2026
d4b3518
diagnostics finish
BoxyUwU May 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/constraints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
formatter,
"({:?}: {:?}) due to {:?} ({:?}) ({:?})",
self.sup, self.sub, self.locations, self.variance_info, self.category,
"({:?}: {:?}) due to {:?} ({:?}) ({:?}) (span: {:?})",
self.sup, self.sub, self.locations, self.variance_info, self.category, self.span,
)
}
}
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
ConstraintCategory::OpaqueType => "opaque type ",
ConstraintCategory::ClosureUpvar(_) => "closure capture ",
ConstraintCategory::Usage => "this usage ",
ConstraintCategory::Predicate(_)
ConstraintCategory::SolverRegionConstraint(_)
| ConstraintCategory::Predicate(_)
| ConstraintCategory::Boring
| ConstraintCategory::BoringNoLocation
| ConstraintCategory::Internal
Expand Down Expand Up @@ -473,6 +474,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let errci = ErrorConstraintInfo { fr, outlived_fr, category, span: cause.span };

let mut diag = match (category, fr_is_local, outlived_fr_is_local) {
(ConstraintCategory::SolverRegionConstraint(span), _, _) => {
let mut d = self.dcx().struct_span_err(
span,
"unsatisfied lifetime constraint from -Zassumptions-on-binders :3",
);
d.note("meoow :c");
d
}
(ConstraintCategory::Return(kind), true, false) if self.is_closure_fn_mut(fr) => {
self.report_fnmut_error(&errci, kind)
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// This loop is cold and runs at the end, which is why we delay
// `OutlivesConstraint` construction until now.
loop {
let ctx = &context[p];
debug!(?ctx);
match context[p] {
Trace::FromGraph(c) => {
p = c.sup;
Expand Down Expand Up @@ -1793,6 +1795,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// the `'region: 'static` constraints introduced by placeholder outlives.
ConstraintCategory::Internal => 7,
ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 8,
ConstraintCategory::SolverRegionConstraint(_) => 9,
};

debug!("constraint {constraint:?} category: {category:?}, interest: {interest:?}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub(crate) struct UniversalRegionRelations<'tcx> {
/// Stores the outlives relations that are known to hold from the
/// implied bounds, in-scope where-clauses, and that sort of
/// thing.
outlives: TransitiveRelation<RegionVid>,
pub(crate) outlives: TransitiveRelation<RegionVid>,

/// This is the `<=` relation; that is, if `a: b`, then `b <= a`,
/// and we store that here. This is useful when figuring out how
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,23 @@ pub(crate) fn type_check<'tcx>(

let polonius_context = typeck.polonius_context;

let mut converter = constraint_conversion::ConstraintConversion::new(
typeck.infcx,
typeck.universal_regions,
typeck.region_bound_pairs,
typeck.known_type_outlives_obligations,
Locations::All(rustc_span::DUMMY_SP),
rustc_span::DUMMY_SP,
ConstraintCategory::Boring,
typeck.constraints,
);
typeck.infcx.destructure_solver_region_constraints_for_borrowck(
&mut converter,
typeck.known_type_outlives_obligations,
universal_region_relations.outlives.clone(),
infcx.tcx.def_span(infcx.root_def_id),
);

// In case type check encountered an error region, we suppress unhelpful extra
// errors in by clearing out all outlives bounds that we may end up checking.
if let Some(guar) = universal_region_relations.universal_regions.encountered_re_error() {
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ where

lint_redundant_lifetimes(tcx, body_def_id, &outlives_env);

let errors = infcx.resolve_regions_with_outlives_env(&outlives_env);
let errors = infcx.resolve_regions_with_outlives_env(&outlives_env, tcx.def_span(body_def_id));
if errors.is_empty() {
return Ok(());
}
Expand All @@ -211,7 +211,8 @@ where
// the implied bounds hack if this contains `bevy_ecs`'s `ParamSet` type.
false,
);
let errors_compat = infcx_compat.resolve_regions_with_outlives_env(&outlives_env);
let errors_compat =
infcx_compat.resolve_regions_with_outlives_env(&outlives_env, tcx.def_span(body_def_id));
if errors_compat.is_empty() {
// FIXME: Once we fix bevy, this would be the place to insert a warning
// to upgrade bevy.
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ impl<'tcx> InferCtxt<'tcx> {
reported_signature_mismatch: self.reported_signature_mismatch.clone(),
tainted_by_errors: self.tainted_by_errors.clone(),
universe: self.universe.clone(),
placeholder_assumptions_for_next_solver: self
.placeholder_assumptions_for_next_solver
.clone(),
next_trait_solver: self.next_trait_solver,
obligation_inspector: self.obligation_inspector.clone(),
}
Expand All @@ -106,6 +109,9 @@ impl<'tcx> InferCtxt<'tcx> {
reported_signature_mismatch: self.reported_signature_mismatch.clone(),
tainted_by_errors: self.tainted_by_errors.clone(),
universe: self.universe.clone(),
placeholder_assumptions_for_next_solver: self
.placeholder_assumptions_for_next_solver
.clone(),
next_trait_solver: self.next_trait_solver,
obligation_inspector: self.obligation_inspector.clone(),
};
Expand Down
50 changes: 50 additions & 0 deletions compiler/rustc_infer/src/infer/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.next_trait_solver
}

fn higher_ranked_assumptions_v2(&self) -> bool {
self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions_v2
}

fn typing_mode(&self) -> ty::TypingMode<'tcx> {
self.typing_mode()
}
Expand All @@ -34,6 +38,40 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.create_next_universe()
}

fn insert_placeholder_assumptions(
&self,
u: ty::UniverseIndex,
assumptions: Option<rustc_type_ir::region_constraint::Assumptions<TyCtxt<'tcx>>>,
) {
self.placeholder_assumptions_for_next_solver.borrow_mut().insert(u, assumptions);
}

fn get_placeholder_assumptions(
&self,
u: ty::UniverseIndex,
) -> Option<rustc_type_ir::region_constraint::Assumptions<TyCtxt<'tcx>>> {
self.placeholder_assumptions_for_next_solver.borrow().get(&u).unwrap().as_ref().cloned()
}

fn get_solver_region_constraint(
&self,
) -> rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>> {
self.inner.borrow().solver_region_constraint_storage.get_constraint()
}

fn overwrite_solver_region_constraint(
&self,
constraint: rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
) {
let mut inner = self.inner.borrow_mut();
use rustc_data_structures::undo_log::UndoLogs;

use crate::infer::UndoLog;
let old_constraint = inner.solver_region_constraint_storage.get_constraint();
inner.undo_log.push(UndoLog::OverwriteSolverRegionConstraint { old_constraint });
inner.solver_region_constraint_storage.overwrite_solver_region_constraint(constraint);
}

fn universe_of_ty(&self, vid: ty::TyVid) -> Option<ty::UniverseIndex> {
match self.try_resolve_ty_var(vid) {
Err(universe) => Some(universe),
Expand Down Expand Up @@ -272,6 +310,18 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
);
}

fn register_solver_region_constraint(
&self,
c: rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
) {
let mut inner = self.inner.borrow_mut();
use rustc_data_structures::undo_log::UndoLogs;

use crate::infer::UndoLog;
inner.undo_log.push(UndoLog::PushSolverRegionConstraint);
inner.solver_region_constraint_storage.push(c);
}

fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
self.register_type_outlives_constraint(ty, r, &ObligationCause::dummy_with_span(span));
}
Expand Down
73 changes: 73 additions & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ pub struct InferCtxtInner<'tcx> {
/// region constraints would've been added.
region_constraint_storage: Option<RegionConstraintStorage<'tcx>>,

/// Used by the next solver when `-Zhigher-ranked-assumptions=v2` is set.
solver_region_constraint_storage: SolverRegionConstraintStorage<'tcx>,

/// A set of constraints that regionck must validate.
///
/// Each constraint has the form `T:'a`, meaning "some type `T` must
Expand Down Expand Up @@ -170,6 +173,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
float_unification_storage: Default::default(),
float_origin_origin_storage: Default::default(),
region_constraint_storage: Some(Default::default()),
solver_region_constraint_storage: SolverRegionConstraintStorage::new(),
region_obligations: Default::default(),
region_assumptions: Default::default(),
hir_typeck_potentially_region_dependent_goals: Default::default(),
Expand Down Expand Up @@ -314,6 +318,16 @@ pub struct InferCtxt<'tcx> {
/// bound.
universe: Cell<ty::UniverseIndex>,

/// List of assumed wellformed types which we can derive implied
/// bounds on a `for<...>` from. Only used unstabley and by the
/// new solver.
placeholder_assumptions_for_next_solver: RefCell<
FxIndexMap<
ty::UniverseIndex,
Option<rustc_type_ir::region_constraint::Assumptions<TyCtxt<'tcx>>>,
>,
>,

next_trait_solver: bool,

pub obligation_inspector: Cell<Option<ObligationInspector<'tcx>>>,
Expand Down Expand Up @@ -396,6 +410,10 @@ pub enum SubregionOrigin<'tcx> {
},

AscribeUserTypeProvePredicate(Span),

// FIXME(-Zhigher-ranked-assumptions-v2): this is a temporary hack until we support
// proper diagnostics for solver region constraints.
SolverRegionConstraint(Span),
}

// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
Expand All @@ -407,6 +425,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
match self {
Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(),
Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span),
Self::SolverRegionConstraint(span) => ConstraintCategory::SolverRegionConstraint(*span),
_ => ConstraintCategory::BoringNoLocation,
}
}
Expand Down Expand Up @@ -606,6 +625,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
reported_signature_mismatch: Default::default(),
tainted_by_errors: Cell::new(None),
universe: Cell::new(ty::UniverseIndex::ROOT),
placeholder_assumptions_for_next_solver: RefCell::new(Default::default()),
next_trait_solver,
obligation_inspector: Cell::new(None),
}
Expand Down Expand Up @@ -1632,6 +1652,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
SubregionOrigin::CompareImplItemObligation { span, .. } => span,
SubregionOrigin::AscribeUserTypeProvePredicate(span) => span,
SubregionOrigin::CheckAssociatedTypeBounds { ref parent, .. } => parent.span(),
SubregionOrigin::SolverRegionConstraint(a) => a,
}
}

Expand Down Expand Up @@ -1721,3 +1742,55 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
}

type SolverRegionConstraint<'tcx> =
rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>;

#[derive(Clone, Debug)]
struct SolverRegionConstraintStorage<'tcx>(SolverRegionConstraint<'tcx>);

impl<'tcx> SolverRegionConstraintStorage<'tcx> {
fn new() -> Self {
SolverRegionConstraintStorage(SolverRegionConstraint::And(Box::new([])))
}

fn get_constraint(&self) -> SolverRegionConstraint<'tcx> {
self.0.clone()
}

fn pop(&mut self) -> Option<SolverRegionConstraint<'tcx>> {
match &mut self.0 {
SolverRegionConstraint::And(and) => {
let mut and = core::mem::take(and).into_iter().collect::<Vec<_>>();
let popped = and.pop()?;
self.0 = SolverRegionConstraint::And(and.into_boxed_slice());
Some(popped)
}
_ => unreachable!(),
}
}

#[instrument(level = "debug")]
fn push(&mut self, constraint: SolverRegionConstraint<'tcx>) {
match &mut self.0 {
SolverRegionConstraint::And(and) => {
let and = core::mem::take(and)
.into_iter()
.chain([constraint])
.collect::<Vec<_>>()
.into_boxed_slice();
self.0 = SolverRegionConstraint::And(and);
}
_ => unreachable!(),
}
}

#[instrument(level = "debug", skip(self))]
fn overwrite_solver_region_constraint(&mut self, constraint: SolverRegionConstraint<'tcx>) {
if !constraint.is_and() {
self.0 = SolverRegionConstraint::And(vec![constraint].into_boxed_slice())
} else {
self.0 = constraint;
}
}
}
4 changes: 3 additions & 1 deletion compiler/rustc_infer/src/infer/outlives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::iter;
use rustc_data_structures::undo_log::UndoLogs;
use rustc_middle::traits::query::{NoSolution, OutlivesBound};
use rustc_middle::ty;
use rustc_span::Span;
use tracing::instrument;

use self::env::OutlivesEnvironment;
Expand Down Expand Up @@ -49,8 +50,9 @@ impl<'tcx> InferCtxt<'tcx> {
ty::PolyTypeOutlivesPredicate<'tcx>,
SubregionOrigin<'tcx>,
) -> Result<ty::PolyTypeOutlivesPredicate<'tcx>, NoSolution>,
span: Span,
) -> Vec<RegionResolutionError<'tcx>> {
match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) {
match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty, span) {
Ok(()) => {}
Err((clause, origin)) => {
return vec![RegionResolutionError::CannotNormalize(clause, origin)];
Expand Down
Loading