From 322843278639cbccb397ab6deb9b12d25d9ff12c Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Tue, 16 Jun 2026 15:37:46 -0300 Subject: [PATCH 1/4] Capture binder region constraints while relating --- .../src/canonical/mod.rs | 13 +- .../src/solve/eval_ctxt/mod.rs | 108 +++++++++- .../src/relate/solver_relating.rs | 185 +++++++++++++++++- ...principal-upcast-region-eq-issue-157859.rs | 19 ++ ...cipal-upcast-region-eq-issue-157859.stderr | 13 ++ .../trait-upcast-projection-region-eq.rs | 23 +++ .../trait-upcast-projection-region-eq.stderr | 13 ++ 7 files changed, 361 insertions(+), 13 deletions(-) create mode 100644 tests/ui/assumptions_on_binders/principal-upcast-region-eq-issue-157859.rs create mode 100644 tests/ui/assumptions_on_binders/principal-upcast-region-eq-issue-157859.stderr create mode 100644 tests/ui/assumptions_on_binders/trait-upcast-projection-region-eq.rs create mode 100644 tests/ui/assumptions_on_binders/trait-upcast-projection-region-eq.stderr diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 80b4d3be172ef..f3419c5bbafd1 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -265,8 +265,17 @@ fn unify_query_var_values( assert_eq!(original_values.len(), var_values.len()); for (&orig, response) in iter::zip(original_values, var_values.var_values.iter()) { - let goals = - delegate.eq_structurally_relating_aliases(param_env, orig, response, span).unwrap(); + let goals = if delegate.cx().assumptions_on_binders() { + let (goals, region_constraints) = delegate + .eq_structurally_relating_aliases_with_region_constraints( + param_env, orig, response, span, + ) + .unwrap(); + delegate.register_solver_region_constraint(region_constraints); + goals + } else { + delegate.eq_structurally_relating_aliases(param_env, orig, response, span).unwrap() + }; assert!(goals.is_empty()); } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index fe573025c87f4..c75ce81694893 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1251,6 +1251,78 @@ where self.relate(param_env, lhs, ty::Variance::Invariant, rhs) } + /// This should be used when relating a rigid alias with another type. + /// + /// Normally we emit a nested `AliasRelate` when equating an inference + /// variable and an alias. This causes us to instead constrain the inference + /// variable to the alias without emitting a nested alias relate goals. + #[instrument(level = "trace", skip(self, param_env), ret)] + pub(super) fn relate_rigid_alias_non_alias( + &mut self, + param_env: I::ParamEnv, + alias: ty::AliasTerm, + variance: ty::Variance, + term: I::Term, + ) -> Result<(), NoSolutionOrRerunNonErased> { + // NOTE: this check is purely an optimization, the structural eq would + // always fail if the term is not an inference variable. + if term.is_infer() { + let cx = self.cx(); + // We need to relate `alias` to `term` treating only the outermost + // constructor as rigid, relating any contained generic arguments as + // normal. We do this by first structurally equating the `term` + // with the alias constructor instantiated with unconstrained infer vars, + // and then relate this with the whole `alias`. + // + // Alternatively we could modify `Equate` for this case by adding another + // variant to `StructurallyRelateAliases`. + let def_id = match alias.kind { + ty::AliasTermKind::ProjectionTy { def_id } => def_id.into(), + ty::AliasTermKind::InherentTy { def_id } => def_id.into(), + ty::AliasTermKind::OpaqueTy { def_id } => def_id.into(), + ty::AliasTermKind::FreeTy { def_id } => def_id.into(), + ty::AliasTermKind::AnonConst { def_id } => def_id.into(), + ty::AliasTermKind::ProjectionConst { def_id } => def_id.into(), + ty::AliasTermKind::FreeConst { def_id } => def_id.into(), + ty::AliasTermKind::InherentConst { def_id } => def_id.into(), + }; + let identity_args = self.fresh_args_for_item(def_id); + let rigid_ctor = alias.with_args(cx, identity_args); + let ctor_term = rigid_ctor.to_term(cx); + self.eq_structurally_relating_aliases(param_env, term, ctor_term)?; + self.relate(param_env, alias, variance, rigid_ctor) + } else { + Err(NoSolution.into()) + } + } + + /// This should only be used when we're either instantiating a previously + /// unconstrained "return value" or when we're sure that all aliases in + /// the types are rigid. + #[instrument(level = "trace", skip(self, param_env), ret)] + pub(super) fn eq_structurally_relating_aliases>( + &mut self, + param_env: I::ParamEnv, + lhs: T, + rhs: T, + ) -> Result<(), NoSolutionOrRerunNonErased> { + let result = if self.cx().assumptions_on_binders() { + let (goals, region_constraints) = + self.delegate.eq_structurally_relating_aliases_with_region_constraints( + param_env, + lhs, + rhs, + self.origin_span, + )?; + self.register_solver_region_constraint(region_constraints); + goals + } else { + self.delegate.eq_structurally_relating_aliases(param_env, lhs, rhs, self.origin_span)? + }; + assert_eq!(result, vec![]); + Ok(()) + } + #[instrument(level = "trace", skip(self, param_env), ret)] pub(super) fn sub>( &mut self, @@ -1269,7 +1341,19 @@ where variance: ty::Variance, rhs: T, ) -> Result<(), NoSolutionOrRerunNonErased> { - let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?; + let goals = if self.cx().assumptions_on_binders() { + let (goals, region_constraints) = self.delegate.relate_with_region_constraints( + param_env, + lhs, + variance, + rhs, + self.origin_span, + )?; + self.register_solver_region_constraint(region_constraints); + goals + } else { + self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)? + }; for &goal in goals.iter() { let source = match goal.predicate.kind().skip_binder() { ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => { @@ -1291,12 +1375,30 @@ where /// goals correctly. #[instrument(level = "trace", skip(self, param_env), ret)] pub(super) fn eq_and_get_goals>( - &self, + &mut self, param_env: I::ParamEnv, lhs: T, rhs: T, ) -> Result>, NoSolution> { - Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?) + if self.cx().assumptions_on_binders() { + let (goals, region_constraints) = self.delegate.relate_with_region_constraints( + param_env, + lhs, + ty::Variance::Invariant, + rhs, + self.origin_span, + )?; + self.register_solver_region_constraint(region_constraints); + Ok(goals) + } else { + Ok(self.delegate.relate( + param_env, + lhs, + ty::Variance::Invariant, + rhs, + self.origin_span, + )?) + } } pub(super) fn instantiate_binder_with_infer + Copy>( diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 96e30f06473cf..1de307fcd1bf4 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -2,6 +2,7 @@ use tracing::{debug, instrument}; use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combine_tys}; use crate::data_structures::DelayedSet; +use crate::region_constraint::RegionConstraint; use crate::relate::combine::combine_ty_args; pub use crate::relate::*; use crate::solve::{Goal, VisibleForLeakCheck}; @@ -30,6 +31,70 @@ pub trait RelateExt: InferCtxtLike { Vec::Predicate>>, TypeError, >; + + fn eq_structurally_relating_aliases_with_region_constraints>( + &self, + param_env: ::ParamEnv, + lhs: T, + rhs: T, + span: ::Span, + ) -> Result< + ( + Vec::Predicate>>, + RegionConstraint, + ), + TypeError, + >; + + fn relate_with_region_constraints>( + &self, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + span: ::Span, + ) -> Result< + ( + Vec::Predicate>>, + RegionConstraint, + ), + TypeError, + >; +} + +fn relate_with_options( + infcx: &Infcx, + structurally_relate_aliases: StructurallyRelateAliases, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + span: ::Span, + collect_region_constraints: bool, +) -> Result< + ( + Vec::Predicate>>, + Option>, + ), + TypeError, +> +where + Infcx: InferCtxtLike, + T: Relate, +{ + let mut relate = SolverRelating::build( + infcx, + structurally_relate_aliases, + variance, + param_env, + span, + collect_region_constraints.then(Vec::new), + ); + relate.relate(lhs, rhs)?; + Ok(( + relate.goals, + relate.region_constraints.map(|c| RegionConstraint::And(c.into_boxed_slice())), + )) } impl RelateExt for Infcx { @@ -44,10 +109,17 @@ impl RelateExt for Infcx { Vec::Predicate>>, TypeError, > { - let mut relate = - SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env, span); - relate.relate(lhs, rhs)?; - Ok(relate.goals) + let (goals, _) = relate_with_options( + self, + StructurallyRelateAliases::No, + param_env, + lhs, + variance, + rhs, + span, + false, + )?; + Ok(goals) } fn eq_structurally_relating_aliases>( @@ -60,15 +132,70 @@ impl RelateExt for Infcx { Vec::Predicate>>, TypeError, > { - let mut relate = SolverRelating::new( + let (goals, _) = relate_with_options( self, StructurallyRelateAliases::Yes, + param_env, + lhs, ty::Invariant, + rhs, + span, + false, + )?; + Ok(goals) + } + + fn eq_structurally_relating_aliases_with_region_constraints>( + &self, + param_env: ::ParamEnv, + lhs: T, + rhs: T, + span: ::Span, + ) -> Result< + ( + Vec::Predicate>>, + RegionConstraint, + ), + TypeError, + > { + let (goals, region_constraints) = relate_with_options( + self, + StructurallyRelateAliases::Yes, param_env, + lhs, + ty::Invariant, + rhs, span, - ); - relate.relate(lhs, rhs)?; - Ok(relate.goals) + true, + )?; + Ok((goals, region_constraints.unwrap())) + } + + fn relate_with_region_constraints>( + &self, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + span: ::Span, + ) -> Result< + ( + Vec::Predicate>>, + RegionConstraint, + ), + TypeError, + > { + let (goals, region_constraints) = relate_with_options( + self, + StructurallyRelateAliases::No, + param_env, + lhs, + variance, + rhs, + span, + true, + )?; + Ok((goals, region_constraints.unwrap())) } } @@ -82,6 +209,7 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> { // Mutable fields. ambient_variance: ty::Variance, goals: Vec>, + region_constraints: Option>>, /// The cache only tracks the `ambient_variance` as it's the /// only field which is mutable and which meaningfully changes /// the result when relating types. @@ -118,6 +246,17 @@ where ambient_variance: ty::Variance, param_env: I::ParamEnv, span: I::Span, + ) -> Self { + Self::build(infcx, structurally_relate_aliases, ambient_variance, param_env, span, None) + } + + fn build( + infcx: &'infcx Infcx, + structurally_relate_aliases: StructurallyRelateAliases, + ambient_variance: ty::Variance, + param_env: I::ParamEnv, + span: I::Span, + region_constraints: Option>>, ) -> Self { SolverRelating { infcx, @@ -126,6 +265,7 @@ where ambient_variance, param_env, goals: vec![], + region_constraints, cache: Default::default(), } } @@ -265,6 +405,35 @@ where } } + let resolve_region = |r: I::Region| match r.kind() { + ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid), + _ => r, + }; + let a = resolve_region(a); + let b = resolve_region(b); + + if let Some(region_constraints) = &mut self.region_constraints { + if a == b { + return Ok(a); + } else { + match self.ambient_variance { + ty::Covariant => { + region_constraints.push(RegionConstraint::RegionOutlives(a, b)); + } + ty::Contravariant => { + region_constraints.push(RegionConstraint::RegionOutlives(b, a)); + } + ty::Invariant => { + region_constraints.push(RegionConstraint::RegionOutlives(a, b)); + region_constraints.push(RegionConstraint::RegionOutlives(b, a)); + } + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + } + } + } + Ok(a) } diff --git a/tests/ui/assumptions_on_binders/principal-upcast-region-eq-issue-157859.rs b/tests/ui/assumptions_on_binders/principal-upcast-region-eq-issue-157859.rs new file mode 100644 index 0000000000000..52b90750e01a9 --- /dev/null +++ b/tests/ui/assumptions_on_binders/principal-upcast-region-eq-issue-157859.rs @@ -0,0 +1,19 @@ +//@compile-flags: -Zassumptions-on-binders -Znext-solver=globally +//@ dont-require-annotations: ERROR + +trait Super { + fn a(&self) { + let a: &dyn Sub = &(); + let b: &dyn Super fn(&'a ())> = a; + } +} + +impl Super for () {} + +trait Sub: Super {} + +impl Sub for () {} + +fn main() { + let a: &dyn Sub = &(); +} diff --git a/tests/ui/assumptions_on_binders/principal-upcast-region-eq-issue-157859.stderr b/tests/ui/assumptions_on_binders/principal-upcast-region-eq-issue-157859.stderr new file mode 100644 index 0000000000000..5ed8cb2dce80a --- /dev/null +++ b/tests/ui/assumptions_on_binders/principal-upcast-region-eq-issue-157859.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `&dyn Sub: CoerceUnsized<&dyn Super fn(&'a ())>>` is not satisfied + --> $DIR/principal-upcast-region-eq-issue-157859.rs:7:49 + | +LL | let b: &dyn Super fn(&'a ())> = a; + | ^ the nightly-only, unstable trait `Unsize fn(&'a ())>>` is not implemented for `dyn Sub` + | + = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information + = note: required for `&dyn Sub` to implement `CoerceUnsized<&dyn Super fn(&'a ())>>` + = note: required for the cast from `&dyn Sub` to `&dyn Super fn(&'a ())>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/assumptions_on_binders/trait-upcast-projection-region-eq.rs b/tests/ui/assumptions_on_binders/trait-upcast-projection-region-eq.rs new file mode 100644 index 0000000000000..d32cdd33e6e8f --- /dev/null +++ b/tests/ui/assumptions_on_binders/trait-upcast-projection-region-eq.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally + +trait Super { + type Assoc; + + fn a(&self) { + let a: &dyn Sub = &(); + let b: &dyn Super fn(&'a ())> = a; + //~^ ERROR the trait bound `&dyn Sub: CoerceUnsized<&dyn Super fn(&'a ())>>` is not satisfied + } +} + +impl Super for () { + type Assoc = fn(&'static ()); +} + +trait Sub: Super {} + +impl Sub for () {} + +fn main() { + let a: &dyn Sub = &(); +} diff --git a/tests/ui/assumptions_on_binders/trait-upcast-projection-region-eq.stderr b/tests/ui/assumptions_on_binders/trait-upcast-projection-region-eq.stderr new file mode 100644 index 0000000000000..fb55bab0ad20c --- /dev/null +++ b/tests/ui/assumptions_on_binders/trait-upcast-projection-region-eq.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `&dyn Sub: CoerceUnsized<&dyn Super fn(&'a ())>>` is not satisfied + --> $DIR/trait-upcast-projection-region-eq.rs:8:57 + | +LL | let b: &dyn Super fn(&'a ())> = a; + | ^ the nightly-only, unstable trait `Unsize fn(&'a ())>>` is not implemented for `dyn Sub` + | + = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information + = note: required for `&dyn Sub` to implement `CoerceUnsized<&dyn Super fn(&'a ())>>` + = note: required for the cast from `&dyn Sub` to `&dyn Super fn(&'a ())>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 40512574d3701e08519a3f83f125c842ee55fc02 Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Sat, 20 Jun 2026 14:52:59 -0300 Subject: [PATCH 2/4] Register solver region constraints while relating --- .../src/canonical/mod.rs | 13 +- .../src/solve/eval_ctxt/mod.rs | 55 +---- .../src/relate/solver_relating.rs | 224 ++++-------------- 3 files changed, 54 insertions(+), 238 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index f3419c5bbafd1..80b4d3be172ef 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -265,17 +265,8 @@ fn unify_query_var_values( assert_eq!(original_values.len(), var_values.len()); for (&orig, response) in iter::zip(original_values, var_values.var_values.iter()) { - let goals = if delegate.cx().assumptions_on_binders() { - let (goals, region_constraints) = delegate - .eq_structurally_relating_aliases_with_region_constraints( - param_env, orig, response, span, - ) - .unwrap(); - delegate.register_solver_region_constraint(region_constraints); - goals - } else { - delegate.eq_structurally_relating_aliases(param_env, orig, response, span).unwrap() - }; + let goals = + delegate.eq_structurally_relating_aliases(param_env, orig, response, span).unwrap(); assert!(goals.is_empty()); } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c75ce81694893..f9d5c28689835 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1306,19 +1306,12 @@ where lhs: T, rhs: T, ) -> Result<(), NoSolutionOrRerunNonErased> { - let result = if self.cx().assumptions_on_binders() { - let (goals, region_constraints) = - self.delegate.eq_structurally_relating_aliases_with_region_constraints( - param_env, - lhs, - rhs, - self.origin_span, - )?; - self.register_solver_region_constraint(region_constraints); - goals - } else { - self.delegate.eq_structurally_relating_aliases(param_env, lhs, rhs, self.origin_span)? - }; + let result = self.delegate.eq_structurally_relating_aliases( + param_env, + lhs, + rhs, + self.origin_span, + )?; assert_eq!(result, vec![]); Ok(()) } @@ -1341,19 +1334,7 @@ where variance: ty::Variance, rhs: T, ) -> Result<(), NoSolutionOrRerunNonErased> { - let goals = if self.cx().assumptions_on_binders() { - let (goals, region_constraints) = self.delegate.relate_with_region_constraints( - param_env, - lhs, - variance, - rhs, - self.origin_span, - )?; - self.register_solver_region_constraint(region_constraints); - goals - } else { - self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)? - }; + let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?; for &goal in goals.iter() { let source = match goal.predicate.kind().skip_binder() { ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => { @@ -1375,30 +1356,12 @@ where /// goals correctly. #[instrument(level = "trace", skip(self, param_env), ret)] pub(super) fn eq_and_get_goals>( - &mut self, + &self, param_env: I::ParamEnv, lhs: T, rhs: T, ) -> Result>, NoSolution> { - if self.cx().assumptions_on_binders() { - let (goals, region_constraints) = self.delegate.relate_with_region_constraints( - param_env, - lhs, - ty::Variance::Invariant, - rhs, - self.origin_span, - )?; - self.register_solver_region_constraint(region_constraints); - Ok(goals) - } else { - Ok(self.delegate.relate( - param_env, - lhs, - ty::Variance::Invariant, - rhs, - self.origin_span, - )?) - } + Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?) } pub(super) fn instantiate_binder_with_infer + Copy>( diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 1de307fcd1bf4..f55331974d7e2 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -31,70 +31,6 @@ pub trait RelateExt: InferCtxtLike { Vec::Predicate>>, TypeError, >; - - fn eq_structurally_relating_aliases_with_region_constraints>( - &self, - param_env: ::ParamEnv, - lhs: T, - rhs: T, - span: ::Span, - ) -> Result< - ( - Vec::Predicate>>, - RegionConstraint, - ), - TypeError, - >; - - fn relate_with_region_constraints>( - &self, - param_env: ::ParamEnv, - lhs: T, - variance: ty::Variance, - rhs: T, - span: ::Span, - ) -> Result< - ( - Vec::Predicate>>, - RegionConstraint, - ), - TypeError, - >; -} - -fn relate_with_options( - infcx: &Infcx, - structurally_relate_aliases: StructurallyRelateAliases, - param_env: ::ParamEnv, - lhs: T, - variance: ty::Variance, - rhs: T, - span: ::Span, - collect_region_constraints: bool, -) -> Result< - ( - Vec::Predicate>>, - Option>, - ), - TypeError, -> -where - Infcx: InferCtxtLike, - T: Relate, -{ - let mut relate = SolverRelating::build( - infcx, - structurally_relate_aliases, - variance, - param_env, - span, - collect_region_constraints.then(Vec::new), - ); - relate.relate(lhs, rhs)?; - Ok(( - relate.goals, - relate.region_constraints.map(|c| RegionConstraint::And(c.into_boxed_slice())), - )) } impl RelateExt for Infcx { @@ -109,17 +45,10 @@ impl RelateExt for Infcx { Vec::Predicate>>, TypeError, > { - let (goals, _) = relate_with_options( - self, - StructurallyRelateAliases::No, - param_env, - lhs, - variance, - rhs, - span, - false, - )?; - Ok(goals) + let mut relate = + SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env, span); + relate.relate(lhs, rhs)?; + Ok(relate.goals) } fn eq_structurally_relating_aliases>( @@ -132,70 +61,15 @@ impl RelateExt for Infcx { Vec::Predicate>>, TypeError, > { - let (goals, _) = relate_with_options( + let mut relate = SolverRelating::new( self, StructurallyRelateAliases::Yes, - param_env, - lhs, ty::Invariant, - rhs, - span, - false, - )?; - Ok(goals) - } - - fn eq_structurally_relating_aliases_with_region_constraints>( - &self, - param_env: ::ParamEnv, - lhs: T, - rhs: T, - span: ::Span, - ) -> Result< - ( - Vec::Predicate>>, - RegionConstraint, - ), - TypeError, - > { - let (goals, region_constraints) = relate_with_options( - self, - StructurallyRelateAliases::Yes, - param_env, - lhs, - ty::Invariant, - rhs, - span, - true, - )?; - Ok((goals, region_constraints.unwrap())) - } - - fn relate_with_region_constraints>( - &self, - param_env: ::ParamEnv, - lhs: T, - variance: ty::Variance, - rhs: T, - span: ::Span, - ) -> Result< - ( - Vec::Predicate>>, - RegionConstraint, - ), - TypeError, - > { - let (goals, region_constraints) = relate_with_options( - self, - StructurallyRelateAliases::No, param_env, - lhs, - variance, - rhs, span, - true, - )?; - Ok((goals, region_constraints.unwrap())) + ); + relate.relate(lhs, rhs)?; + Ok(relate.goals) } } @@ -209,7 +83,6 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> { // Mutable fields. ambient_variance: ty::Variance, goals: Vec>, - region_constraints: Option>>, /// The cache only tracks the `ambient_variance` as it's the /// only field which is mutable and which meaningfully changes /// the result when relating types. @@ -246,17 +119,6 @@ where ambient_variance: ty::Variance, param_env: I::ParamEnv, span: I::Span, - ) -> Self { - Self::build(infcx, structurally_relate_aliases, ambient_variance, param_env, span, None) - } - - fn build( - infcx: &'infcx Infcx, - structurally_relate_aliases: StructurallyRelateAliases, - ambient_variance: ty::Variance, - param_env: I::ParamEnv, - span: I::Span, - region_constraints: Option>>, ) -> Self { SolverRelating { infcx, @@ -265,7 +127,6 @@ where ambient_variance, param_env, goals: vec![], - region_constraints, cache: Default::default(), } } @@ -394,42 +255,43 @@ where #[instrument(skip(self), level = "trace")] fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult { - match self.ambient_variance { - // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) - ty::Covariant => self.infcx.sub_regions(b, a, VisibleForLeakCheck::Yes, self.span), - // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) - ty::Contravariant => self.infcx.sub_regions(a, b, VisibleForLeakCheck::Yes, self.span), - ty::Invariant => self.infcx.equate_regions(a, b, VisibleForLeakCheck::Yes, self.span), - ty::Bivariant => { - unreachable!("Expected bivariance to be handled in relate_with_variance") - } - } - - let resolve_region = |r: I::Region| match r.kind() { - ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid), - _ => r, - }; - let a = resolve_region(a); - let b = resolve_region(b); - - if let Some(region_constraints) = &mut self.region_constraints { + if self.cx().assumptions_on_binders() { if a == b { return Ok(a); - } else { - match self.ambient_variance { - ty::Covariant => { - region_constraints.push(RegionConstraint::RegionOutlives(a, b)); - } - ty::Contravariant => { - region_constraints.push(RegionConstraint::RegionOutlives(b, a)); - } - ty::Invariant => { - region_constraints.push(RegionConstraint::RegionOutlives(a, b)); - region_constraints.push(RegionConstraint::RegionOutlives(b, a)); - } - ty::Bivariant => { - unreachable!("Expected bivariance to be handled in relate_with_variance") - } + } + + match self.ambient_variance { + ty::Covariant => { + self.infcx + .register_solver_region_constraint(RegionConstraint::RegionOutlives(a, b)); + } + ty::Contravariant => { + self.infcx + .register_solver_region_constraint(RegionConstraint::RegionOutlives(b, a)); + } + ty::Invariant => { + self.infcx + .register_solver_region_constraint(RegionConstraint::RegionOutlives(a, b)); + self.infcx + .register_solver_region_constraint(RegionConstraint::RegionOutlives(b, a)); + } + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + } + } else { + match self.ambient_variance { + // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) + ty::Covariant => self.infcx.sub_regions(b, a, VisibleForLeakCheck::Yes, self.span), + // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) + ty::Contravariant => { + self.infcx.sub_regions(a, b, VisibleForLeakCheck::Yes, self.span) + } + ty::Invariant => { + self.infcx.equate_regions(a, b, VisibleForLeakCheck::Yes, self.span) + } + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") } } } From c5f2ffdc5420c1549aec881b1a1b9199c1c096ed Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Sat, 20 Jun 2026 21:31:50 -0300 Subject: [PATCH 3/4] Keep binder region constraints local while relating --- .../src/solve/eval_ctxt/mod.rs | 55 ++++- .../src/relate/solver_relating.rs | 224 ++++++++++++++---- 2 files changed, 227 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index f9d5c28689835..c75ce81694893 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1306,12 +1306,19 @@ where lhs: T, rhs: T, ) -> Result<(), NoSolutionOrRerunNonErased> { - let result = self.delegate.eq_structurally_relating_aliases( - param_env, - lhs, - rhs, - self.origin_span, - )?; + let result = if self.cx().assumptions_on_binders() { + let (goals, region_constraints) = + self.delegate.eq_structurally_relating_aliases_with_region_constraints( + param_env, + lhs, + rhs, + self.origin_span, + )?; + self.register_solver_region_constraint(region_constraints); + goals + } else { + self.delegate.eq_structurally_relating_aliases(param_env, lhs, rhs, self.origin_span)? + }; assert_eq!(result, vec![]); Ok(()) } @@ -1334,7 +1341,19 @@ where variance: ty::Variance, rhs: T, ) -> Result<(), NoSolutionOrRerunNonErased> { - let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?; + let goals = if self.cx().assumptions_on_binders() { + let (goals, region_constraints) = self.delegate.relate_with_region_constraints( + param_env, + lhs, + variance, + rhs, + self.origin_span, + )?; + self.register_solver_region_constraint(region_constraints); + goals + } else { + self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)? + }; for &goal in goals.iter() { let source = match goal.predicate.kind().skip_binder() { ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => { @@ -1356,12 +1375,30 @@ where /// goals correctly. #[instrument(level = "trace", skip(self, param_env), ret)] pub(super) fn eq_and_get_goals>( - &self, + &mut self, param_env: I::ParamEnv, lhs: T, rhs: T, ) -> Result>, NoSolution> { - Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?) + if self.cx().assumptions_on_binders() { + let (goals, region_constraints) = self.delegate.relate_with_region_constraints( + param_env, + lhs, + ty::Variance::Invariant, + rhs, + self.origin_span, + )?; + self.register_solver_region_constraint(region_constraints); + Ok(goals) + } else { + Ok(self.delegate.relate( + param_env, + lhs, + ty::Variance::Invariant, + rhs, + self.origin_span, + )?) + } } pub(super) fn instantiate_binder_with_infer + Copy>( diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index f55331974d7e2..1de307fcd1bf4 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -31,6 +31,70 @@ pub trait RelateExt: InferCtxtLike { Vec::Predicate>>, TypeError, >; + + fn eq_structurally_relating_aliases_with_region_constraints>( + &self, + param_env: ::ParamEnv, + lhs: T, + rhs: T, + span: ::Span, + ) -> Result< + ( + Vec::Predicate>>, + RegionConstraint, + ), + TypeError, + >; + + fn relate_with_region_constraints>( + &self, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + span: ::Span, + ) -> Result< + ( + Vec::Predicate>>, + RegionConstraint, + ), + TypeError, + >; +} + +fn relate_with_options( + infcx: &Infcx, + structurally_relate_aliases: StructurallyRelateAliases, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + span: ::Span, + collect_region_constraints: bool, +) -> Result< + ( + Vec::Predicate>>, + Option>, + ), + TypeError, +> +where + Infcx: InferCtxtLike, + T: Relate, +{ + let mut relate = SolverRelating::build( + infcx, + structurally_relate_aliases, + variance, + param_env, + span, + collect_region_constraints.then(Vec::new), + ); + relate.relate(lhs, rhs)?; + Ok(( + relate.goals, + relate.region_constraints.map(|c| RegionConstraint::And(c.into_boxed_slice())), + )) } impl RelateExt for Infcx { @@ -45,10 +109,17 @@ impl RelateExt for Infcx { Vec::Predicate>>, TypeError, > { - let mut relate = - SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env, span); - relate.relate(lhs, rhs)?; - Ok(relate.goals) + let (goals, _) = relate_with_options( + self, + StructurallyRelateAliases::No, + param_env, + lhs, + variance, + rhs, + span, + false, + )?; + Ok(goals) } fn eq_structurally_relating_aliases>( @@ -61,15 +132,70 @@ impl RelateExt for Infcx { Vec::Predicate>>, TypeError, > { - let mut relate = SolverRelating::new( + let (goals, _) = relate_with_options( self, StructurallyRelateAliases::Yes, + param_env, + lhs, ty::Invariant, + rhs, + span, + false, + )?; + Ok(goals) + } + + fn eq_structurally_relating_aliases_with_region_constraints>( + &self, + param_env: ::ParamEnv, + lhs: T, + rhs: T, + span: ::Span, + ) -> Result< + ( + Vec::Predicate>>, + RegionConstraint, + ), + TypeError, + > { + let (goals, region_constraints) = relate_with_options( + self, + StructurallyRelateAliases::Yes, param_env, + lhs, + ty::Invariant, + rhs, span, - ); - relate.relate(lhs, rhs)?; - Ok(relate.goals) + true, + )?; + Ok((goals, region_constraints.unwrap())) + } + + fn relate_with_region_constraints>( + &self, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + span: ::Span, + ) -> Result< + ( + Vec::Predicate>>, + RegionConstraint, + ), + TypeError, + > { + let (goals, region_constraints) = relate_with_options( + self, + StructurallyRelateAliases::No, + param_env, + lhs, + variance, + rhs, + span, + true, + )?; + Ok((goals, region_constraints.unwrap())) } } @@ -83,6 +209,7 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> { // Mutable fields. ambient_variance: ty::Variance, goals: Vec>, + region_constraints: Option>>, /// The cache only tracks the `ambient_variance` as it's the /// only field which is mutable and which meaningfully changes /// the result when relating types. @@ -119,6 +246,17 @@ where ambient_variance: ty::Variance, param_env: I::ParamEnv, span: I::Span, + ) -> Self { + Self::build(infcx, structurally_relate_aliases, ambient_variance, param_env, span, None) + } + + fn build( + infcx: &'infcx Infcx, + structurally_relate_aliases: StructurallyRelateAliases, + ambient_variance: ty::Variance, + param_env: I::ParamEnv, + span: I::Span, + region_constraints: Option>>, ) -> Self { SolverRelating { infcx, @@ -127,6 +265,7 @@ where ambient_variance, param_env, goals: vec![], + region_constraints, cache: Default::default(), } } @@ -255,43 +394,42 @@ where #[instrument(skip(self), level = "trace")] fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult { - if self.cx().assumptions_on_binders() { - if a == b { - return Ok(a); + match self.ambient_variance { + // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) + ty::Covariant => self.infcx.sub_regions(b, a, VisibleForLeakCheck::Yes, self.span), + // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) + ty::Contravariant => self.infcx.sub_regions(a, b, VisibleForLeakCheck::Yes, self.span), + ty::Invariant => self.infcx.equate_regions(a, b, VisibleForLeakCheck::Yes, self.span), + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") } + } - match self.ambient_variance { - ty::Covariant => { - self.infcx - .register_solver_region_constraint(RegionConstraint::RegionOutlives(a, b)); - } - ty::Contravariant => { - self.infcx - .register_solver_region_constraint(RegionConstraint::RegionOutlives(b, a)); - } - ty::Invariant => { - self.infcx - .register_solver_region_constraint(RegionConstraint::RegionOutlives(a, b)); - self.infcx - .register_solver_region_constraint(RegionConstraint::RegionOutlives(b, a)); - } - ty::Bivariant => { - unreachable!("Expected bivariance to be handled in relate_with_variance") - } - } - } else { - match self.ambient_variance { - // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) - ty::Covariant => self.infcx.sub_regions(b, a, VisibleForLeakCheck::Yes, self.span), - // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) - ty::Contravariant => { - self.infcx.sub_regions(a, b, VisibleForLeakCheck::Yes, self.span) - } - ty::Invariant => { - self.infcx.equate_regions(a, b, VisibleForLeakCheck::Yes, self.span) - } - ty::Bivariant => { - unreachable!("Expected bivariance to be handled in relate_with_variance") + let resolve_region = |r: I::Region| match r.kind() { + ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid), + _ => r, + }; + let a = resolve_region(a); + let b = resolve_region(b); + + if let Some(region_constraints) = &mut self.region_constraints { + if a == b { + return Ok(a); + } else { + match self.ambient_variance { + ty::Covariant => { + region_constraints.push(RegionConstraint::RegionOutlives(a, b)); + } + ty::Contravariant => { + region_constraints.push(RegionConstraint::RegionOutlives(b, a)); + } + ty::Invariant => { + region_constraints.push(RegionConstraint::RegionOutlives(a, b)); + region_constraints.push(RegionConstraint::RegionOutlives(b, a)); + } + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } } } } From 83c56538e996912b9647e9f749c1004ce99df6a4 Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Tue, 23 Jun 2026 14:10:30 -0300 Subject: [PATCH 4/4] Reproduce direct solver region registration failures --- .../src/solve/eval_ctxt/mod.rs | 108 +-------- .../src/relate/solver_relating.rs | 224 ++++-------------- 2 files changed, 46 insertions(+), 286 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c75ce81694893..fe573025c87f4 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1251,78 +1251,6 @@ where self.relate(param_env, lhs, ty::Variance::Invariant, rhs) } - /// This should be used when relating a rigid alias with another type. - /// - /// Normally we emit a nested `AliasRelate` when equating an inference - /// variable and an alias. This causes us to instead constrain the inference - /// variable to the alias without emitting a nested alias relate goals. - #[instrument(level = "trace", skip(self, param_env), ret)] - pub(super) fn relate_rigid_alias_non_alias( - &mut self, - param_env: I::ParamEnv, - alias: ty::AliasTerm, - variance: ty::Variance, - term: I::Term, - ) -> Result<(), NoSolutionOrRerunNonErased> { - // NOTE: this check is purely an optimization, the structural eq would - // always fail if the term is not an inference variable. - if term.is_infer() { - let cx = self.cx(); - // We need to relate `alias` to `term` treating only the outermost - // constructor as rigid, relating any contained generic arguments as - // normal. We do this by first structurally equating the `term` - // with the alias constructor instantiated with unconstrained infer vars, - // and then relate this with the whole `alias`. - // - // Alternatively we could modify `Equate` for this case by adding another - // variant to `StructurallyRelateAliases`. - let def_id = match alias.kind { - ty::AliasTermKind::ProjectionTy { def_id } => def_id.into(), - ty::AliasTermKind::InherentTy { def_id } => def_id.into(), - ty::AliasTermKind::OpaqueTy { def_id } => def_id.into(), - ty::AliasTermKind::FreeTy { def_id } => def_id.into(), - ty::AliasTermKind::AnonConst { def_id } => def_id.into(), - ty::AliasTermKind::ProjectionConst { def_id } => def_id.into(), - ty::AliasTermKind::FreeConst { def_id } => def_id.into(), - ty::AliasTermKind::InherentConst { def_id } => def_id.into(), - }; - let identity_args = self.fresh_args_for_item(def_id); - let rigid_ctor = alias.with_args(cx, identity_args); - let ctor_term = rigid_ctor.to_term(cx); - self.eq_structurally_relating_aliases(param_env, term, ctor_term)?; - self.relate(param_env, alias, variance, rigid_ctor) - } else { - Err(NoSolution.into()) - } - } - - /// This should only be used when we're either instantiating a previously - /// unconstrained "return value" or when we're sure that all aliases in - /// the types are rigid. - #[instrument(level = "trace", skip(self, param_env), ret)] - pub(super) fn eq_structurally_relating_aliases>( - &mut self, - param_env: I::ParamEnv, - lhs: T, - rhs: T, - ) -> Result<(), NoSolutionOrRerunNonErased> { - let result = if self.cx().assumptions_on_binders() { - let (goals, region_constraints) = - self.delegate.eq_structurally_relating_aliases_with_region_constraints( - param_env, - lhs, - rhs, - self.origin_span, - )?; - self.register_solver_region_constraint(region_constraints); - goals - } else { - self.delegate.eq_structurally_relating_aliases(param_env, lhs, rhs, self.origin_span)? - }; - assert_eq!(result, vec![]); - Ok(()) - } - #[instrument(level = "trace", skip(self, param_env), ret)] pub(super) fn sub>( &mut self, @@ -1341,19 +1269,7 @@ where variance: ty::Variance, rhs: T, ) -> Result<(), NoSolutionOrRerunNonErased> { - let goals = if self.cx().assumptions_on_binders() { - let (goals, region_constraints) = self.delegate.relate_with_region_constraints( - param_env, - lhs, - variance, - rhs, - self.origin_span, - )?; - self.register_solver_region_constraint(region_constraints); - goals - } else { - self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)? - }; + let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?; for &goal in goals.iter() { let source = match goal.predicate.kind().skip_binder() { ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => { @@ -1375,30 +1291,12 @@ where /// goals correctly. #[instrument(level = "trace", skip(self, param_env), ret)] pub(super) fn eq_and_get_goals>( - &mut self, + &self, param_env: I::ParamEnv, lhs: T, rhs: T, ) -> Result>, NoSolution> { - if self.cx().assumptions_on_binders() { - let (goals, region_constraints) = self.delegate.relate_with_region_constraints( - param_env, - lhs, - ty::Variance::Invariant, - rhs, - self.origin_span, - )?; - self.register_solver_region_constraint(region_constraints); - Ok(goals) - } else { - Ok(self.delegate.relate( - param_env, - lhs, - ty::Variance::Invariant, - rhs, - self.origin_span, - )?) - } + Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?) } pub(super) fn instantiate_binder_with_infer + Copy>( diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 1de307fcd1bf4..f55331974d7e2 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -31,70 +31,6 @@ pub trait RelateExt: InferCtxtLike { Vec::Predicate>>, TypeError, >; - - fn eq_structurally_relating_aliases_with_region_constraints>( - &self, - param_env: ::ParamEnv, - lhs: T, - rhs: T, - span: ::Span, - ) -> Result< - ( - Vec::Predicate>>, - RegionConstraint, - ), - TypeError, - >; - - fn relate_with_region_constraints>( - &self, - param_env: ::ParamEnv, - lhs: T, - variance: ty::Variance, - rhs: T, - span: ::Span, - ) -> Result< - ( - Vec::Predicate>>, - RegionConstraint, - ), - TypeError, - >; -} - -fn relate_with_options( - infcx: &Infcx, - structurally_relate_aliases: StructurallyRelateAliases, - param_env: ::ParamEnv, - lhs: T, - variance: ty::Variance, - rhs: T, - span: ::Span, - collect_region_constraints: bool, -) -> Result< - ( - Vec::Predicate>>, - Option>, - ), - TypeError, -> -where - Infcx: InferCtxtLike, - T: Relate, -{ - let mut relate = SolverRelating::build( - infcx, - structurally_relate_aliases, - variance, - param_env, - span, - collect_region_constraints.then(Vec::new), - ); - relate.relate(lhs, rhs)?; - Ok(( - relate.goals, - relate.region_constraints.map(|c| RegionConstraint::And(c.into_boxed_slice())), - )) } impl RelateExt for Infcx { @@ -109,17 +45,10 @@ impl RelateExt for Infcx { Vec::Predicate>>, TypeError, > { - let (goals, _) = relate_with_options( - self, - StructurallyRelateAliases::No, - param_env, - lhs, - variance, - rhs, - span, - false, - )?; - Ok(goals) + let mut relate = + SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env, span); + relate.relate(lhs, rhs)?; + Ok(relate.goals) } fn eq_structurally_relating_aliases>( @@ -132,70 +61,15 @@ impl RelateExt for Infcx { Vec::Predicate>>, TypeError, > { - let (goals, _) = relate_with_options( + let mut relate = SolverRelating::new( self, StructurallyRelateAliases::Yes, - param_env, - lhs, ty::Invariant, - rhs, - span, - false, - )?; - Ok(goals) - } - - fn eq_structurally_relating_aliases_with_region_constraints>( - &self, - param_env: ::ParamEnv, - lhs: T, - rhs: T, - span: ::Span, - ) -> Result< - ( - Vec::Predicate>>, - RegionConstraint, - ), - TypeError, - > { - let (goals, region_constraints) = relate_with_options( - self, - StructurallyRelateAliases::Yes, - param_env, - lhs, - ty::Invariant, - rhs, - span, - true, - )?; - Ok((goals, region_constraints.unwrap())) - } - - fn relate_with_region_constraints>( - &self, - param_env: ::ParamEnv, - lhs: T, - variance: ty::Variance, - rhs: T, - span: ::Span, - ) -> Result< - ( - Vec::Predicate>>, - RegionConstraint, - ), - TypeError, - > { - let (goals, region_constraints) = relate_with_options( - self, - StructurallyRelateAliases::No, param_env, - lhs, - variance, - rhs, span, - true, - )?; - Ok((goals, region_constraints.unwrap())) + ); + relate.relate(lhs, rhs)?; + Ok(relate.goals) } } @@ -209,7 +83,6 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> { // Mutable fields. ambient_variance: ty::Variance, goals: Vec>, - region_constraints: Option>>, /// The cache only tracks the `ambient_variance` as it's the /// only field which is mutable and which meaningfully changes /// the result when relating types. @@ -246,17 +119,6 @@ where ambient_variance: ty::Variance, param_env: I::ParamEnv, span: I::Span, - ) -> Self { - Self::build(infcx, structurally_relate_aliases, ambient_variance, param_env, span, None) - } - - fn build( - infcx: &'infcx Infcx, - structurally_relate_aliases: StructurallyRelateAliases, - ambient_variance: ty::Variance, - param_env: I::ParamEnv, - span: I::Span, - region_constraints: Option>>, ) -> Self { SolverRelating { infcx, @@ -265,7 +127,6 @@ where ambient_variance, param_env, goals: vec![], - region_constraints, cache: Default::default(), } } @@ -394,42 +255,43 @@ where #[instrument(skip(self), level = "trace")] fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult { - match self.ambient_variance { - // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) - ty::Covariant => self.infcx.sub_regions(b, a, VisibleForLeakCheck::Yes, self.span), - // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) - ty::Contravariant => self.infcx.sub_regions(a, b, VisibleForLeakCheck::Yes, self.span), - ty::Invariant => self.infcx.equate_regions(a, b, VisibleForLeakCheck::Yes, self.span), - ty::Bivariant => { - unreachable!("Expected bivariance to be handled in relate_with_variance") - } - } - - let resolve_region = |r: I::Region| match r.kind() { - ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid), - _ => r, - }; - let a = resolve_region(a); - let b = resolve_region(b); - - if let Some(region_constraints) = &mut self.region_constraints { + if self.cx().assumptions_on_binders() { if a == b { return Ok(a); - } else { - match self.ambient_variance { - ty::Covariant => { - region_constraints.push(RegionConstraint::RegionOutlives(a, b)); - } - ty::Contravariant => { - region_constraints.push(RegionConstraint::RegionOutlives(b, a)); - } - ty::Invariant => { - region_constraints.push(RegionConstraint::RegionOutlives(a, b)); - region_constraints.push(RegionConstraint::RegionOutlives(b, a)); - } - ty::Bivariant => { - unreachable!("Expected bivariance to be handled in relate_with_variance") - } + } + + match self.ambient_variance { + ty::Covariant => { + self.infcx + .register_solver_region_constraint(RegionConstraint::RegionOutlives(a, b)); + } + ty::Contravariant => { + self.infcx + .register_solver_region_constraint(RegionConstraint::RegionOutlives(b, a)); + } + ty::Invariant => { + self.infcx + .register_solver_region_constraint(RegionConstraint::RegionOutlives(a, b)); + self.infcx + .register_solver_region_constraint(RegionConstraint::RegionOutlives(b, a)); + } + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + } + } else { + match self.ambient_variance { + // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) + ty::Covariant => self.infcx.sub_regions(b, a, VisibleForLeakCheck::Yes, self.span), + // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) + ty::Contravariant => { + self.infcx.sub_regions(a, b, VisibleForLeakCheck::Yes, self.span) + } + ty::Invariant => { + self.infcx.equate_regions(a, b, VisibleForLeakCheck::Yes, self.span) + } + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") } } }