Make ObligationEmittingRelation deal with Goals only

This commit is contained in:
Michael Goulet 2024-06-07 10:05:47 -04:00
parent 4038010436
commit 44a6f72a72
7 changed files with 119 additions and 60 deletions

View file

@ -3,7 +3,8 @@ use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::relate::{ObligationEmittingRelation, StructurallyRelateAliases}; use rustc_infer::infer::relate::{ObligationEmittingRelation, StructurallyRelateAliases};
use rustc_infer::infer::relate::{Relate, RelateResult, TypeRelation}; use rustc_infer::infer::relate::{Relate, RelateResult, TypeRelation};
use rustc_infer::infer::NllRegionVariableOrigin; use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::traits::{Obligation, PredicateObligation}; use rustc_infer::traits::solve::Goal;
use rustc_infer::traits::Obligation;
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::ConstraintCategory;
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
@ -154,8 +155,13 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
), ),
}; };
let cause = ObligationCause::dummy_with_span(self.span()); let cause = ObligationCause::dummy_with_span(self.span());
let obligations = infcx.handle_opaque_type(a, b, &cause, self.param_env())?.obligations; self.register_obligations(
self.register_obligations(obligations); infcx
.handle_opaque_type(a, b, &cause, self.param_env())?
.obligations
.into_iter()
.map(Goal::from),
);
Ok(()) Ok(())
} }
@ -550,22 +556,32 @@ impl<'bccx, 'tcx> ObligationEmittingRelation<'tcx> for NllTypeRelating<'_, 'bccx
&mut self, &mut self,
obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>, obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
) { ) {
let tcx = self.tcx();
let param_env = self.param_env();
self.register_obligations( self.register_obligations(
obligations obligations.into_iter().map(|to_pred| Goal::new(tcx, param_env, to_pred)),
.into_iter()
.map(|to_pred| {
Obligation::new(self.tcx(), ObligationCause::dummy(), self.param_env(), to_pred)
})
.collect(),
); );
} }
fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) { fn register_obligations(
&mut self,
obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
) {
let _: Result<_, ErrorGuaranteed> = self.type_checker.fully_perform_op( let _: Result<_, ErrorGuaranteed> = self.type_checker.fully_perform_op(
self.locations, self.locations,
self.category, self.category,
InstantiateOpaqueType { InstantiateOpaqueType {
obligations, obligations: obligations
.into_iter()
.map(|goal| {
Obligation::new(
self.tcx(),
ObligationCause::dummy_with_span(self.span()),
goal.param_env,
goal.predicate,
)
})
.collect(),
// These fields are filled in during execution of the operation // These fields are filled in during execution of the operation
base_universe: None, base_universe: None,
region_constraints: None, region_constraints: None,

View file

@ -31,6 +31,8 @@ use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::{Const, ImplSubject}; use rustc_middle::ty::{Const, ImplSubject};
use crate::traits::Obligation;
/// Whether we should define opaque types or just treat them opaquely. /// Whether we should define opaque types or just treat them opaquely.
/// ///
/// Currently only used to prevent predicate matching from matching anything /// Currently only used to prevent predicate matching from matching anything
@ -119,10 +121,8 @@ impl<'a, 'tcx> At<'a, 'tcx> {
self.param_env, self.param_env,
define_opaque_types, define_opaque_types,
); );
fields fields.sup().relate(expected, actual)?;
.sup() Ok(InferOk { value: (), obligations: fields.into_obligations() })
.relate(expected, actual)
.map(|_| InferOk { value: (), obligations: fields.obligations })
} }
/// Makes `expected <: actual`. /// Makes `expected <: actual`.
@ -141,10 +141,8 @@ impl<'a, 'tcx> At<'a, 'tcx> {
self.param_env, self.param_env,
define_opaque_types, define_opaque_types,
); );
fields fields.sub().relate(expected, actual)?;
.sub() Ok(InferOk { value: (), obligations: fields.into_obligations() })
.relate(expected, actual)
.map(|_| InferOk { value: (), obligations: fields.obligations })
} }
/// Makes `expected == actual`. /// Makes `expected == actual`.
@ -163,10 +161,22 @@ impl<'a, 'tcx> At<'a, 'tcx> {
self.param_env, self.param_env,
define_opaque_types, define_opaque_types,
); );
fields fields.equate(StructurallyRelateAliases::No).relate(expected, actual)?;
.equate(StructurallyRelateAliases::No) Ok(InferOk {
.relate(expected, actual) value: (),
.map(|_| InferOk { value: (), obligations: fields.obligations }) obligations: fields
.obligations
.into_iter()
.map(|goal| {
Obligation::new(
self.infcx.tcx,
fields.trace.cause.clone(),
goal.param_env,
goal.predicate,
)
})
.collect(),
})
} }
/// Equates `expected` and `found` while structurally relating aliases. /// Equates `expected` and `found` while structurally relating aliases.
@ -187,10 +197,8 @@ impl<'a, 'tcx> At<'a, 'tcx> {
self.param_env, self.param_env,
DefineOpaqueTypes::Yes, DefineOpaqueTypes::Yes,
); );
fields fields.equate(StructurallyRelateAliases::Yes).relate(expected, actual)?;
.equate(StructurallyRelateAliases::Yes) Ok(InferOk { value: (), obligations: fields.into_obligations() })
.relate(expected, actual)
.map(|_| InferOk { value: (), obligations: fields.obligations })
} }
pub fn relate<T>( pub fn relate<T>(
@ -237,10 +245,8 @@ impl<'a, 'tcx> At<'a, 'tcx> {
self.param_env, self.param_env,
define_opaque_types, define_opaque_types,
); );
fields let value = fields.lub().relate(expected, actual)?;
.lub() Ok(InferOk { value, obligations: fields.into_obligations() })
.relate(expected, actual)
.map(|value| InferOk { value, obligations: fields.obligations })
} }
/// Computes the greatest-lower-bound, or mutual subtype, of two /// Computes the greatest-lower-bound, or mutual subtype, of two
@ -261,10 +267,8 @@ impl<'a, 'tcx> At<'a, 'tcx> {
self.param_env, self.param_env,
define_opaque_types, define_opaque_types,
); );
fields let value = fields.glb().relate(expected, actual)?;
.glb() Ok(InferOk { value, obligations: fields.into_obligations() })
.relate(expected, actual)
.map(|value| InferOk { value, obligations: fields.obligations })
} }
} }

View file

@ -28,6 +28,7 @@ use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
use crate::traits::{Obligation, PredicateObligation}; use crate::traits::{Obligation, PredicateObligation};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::infer::unify_key::EffectVarValue;
use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
use rustc_middle::ty::{IntType, UintType}; use rustc_middle::ty::{IntType, UintType};
@ -38,7 +39,7 @@ pub struct CombineFields<'infcx, 'tcx> {
pub infcx: &'infcx InferCtxt<'tcx>, pub infcx: &'infcx InferCtxt<'tcx>,
pub trace: TypeTrace<'tcx>, pub trace: TypeTrace<'tcx>,
pub param_env: ty::ParamEnv<'tcx>, pub param_env: ty::ParamEnv<'tcx>,
pub obligations: Vec<PredicateObligation<'tcx>>, pub obligations: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
pub define_opaque_types: DefineOpaqueTypes, pub define_opaque_types: DefineOpaqueTypes,
} }
@ -51,6 +52,20 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
) -> Self { ) -> Self {
Self { infcx, trace, param_env, define_opaque_types, obligations: vec![] } Self { infcx, trace, param_env, define_opaque_types, obligations: vec![] }
} }
pub(crate) fn into_obligations(self) -> Vec<PredicateObligation<'tcx>> {
self.obligations
.into_iter()
.map(|goal| {
Obligation::new(
self.infcx.tcx,
self.trace.cause.clone(),
goal.param_env,
goal.predicate,
)
})
.collect()
}
} }
impl<'tcx> InferCtxt<'tcx> { impl<'tcx> InferCtxt<'tcx> {
@ -290,7 +305,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
Glb::new(self) Glb::new(self)
} }
pub fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) { pub fn register_obligations(
&mut self,
obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
) {
self.obligations.extend(obligations); self.obligations.extend(obligations);
} }
@ -298,9 +316,11 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
&mut self, &mut self,
obligations: impl IntoIterator<Item: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>, obligations: impl IntoIterator<Item: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
) { ) {
self.obligations.extend(obligations.into_iter().map(|to_pred| { self.obligations.extend(
Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, to_pred) obligations
})) .into_iter()
.map(|to_pred| Goal::new(self.infcx.tcx, self.param_env, to_pred)),
)
} }
} }
@ -315,7 +335,10 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<TyCtxt<'tcx>> {
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases; fn structurally_relate_aliases(&self) -> StructurallyRelateAliases;
/// Register obligations that must hold in order for this relation to hold /// Register obligations that must hold in order for this relation to hold
fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>); fn register_obligations(
&mut self,
obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
);
/// Register predicates that must hold in order for this relation to hold. Uses /// Register predicates that must hold in order for this relation to hold. Uses
/// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should /// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should

View file

@ -1,6 +1,7 @@
//! Greatest lower bound. See [`lattice`]. //! Greatest lower bound. See [`lattice`].
use super::{Relate, RelateResult, TypeRelation}; use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::Span; use rustc_span::Span;
@ -8,7 +9,7 @@ use super::combine::{CombineFields, ObligationEmittingRelation};
use super::lattice::{self, LatticeDir}; use super::lattice::{self, LatticeDir};
use super::StructurallyRelateAliases; use super::StructurallyRelateAliases;
use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin}; use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
use crate::traits::{ObligationCause, PredicateObligation}; use crate::traits::ObligationCause;
/// "Greatest lower bound" (common subtype) /// "Greatest lower bound" (common subtype)
pub struct Glb<'combine, 'infcx, 'tcx> { pub struct Glb<'combine, 'infcx, 'tcx> {
@ -147,7 +148,10 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> {
self.fields.register_predicates(obligations); self.fields.register_predicates(obligations);
} }
fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) { fn register_obligations(
&mut self,
obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
) {
self.fields.register_obligations(obligations); self.fields.register_obligations(obligations);
} }

View file

@ -21,7 +21,8 @@ use super::combine::ObligationEmittingRelation;
use crate::infer::{DefineOpaqueTypes, InferCtxt}; use crate::infer::{DefineOpaqueTypes, InferCtxt};
use crate::traits::ObligationCause; use crate::traits::ObligationCause;
use super::RelateResult; use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::TyVar; use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
@ -109,7 +110,11 @@ where
&& !this.infcx().next_trait_solver() => && !this.infcx().next_trait_solver() =>
{ {
this.register_obligations( this.register_obligations(
infcx.handle_opaque_type(a, b, this.cause(), this.param_env())?.obligations, infcx
.handle_opaque_type(a, b, this.cause(), this.param_env())?
.obligations
.into_iter()
.map(Goal::from),
); );
Ok(a) Ok(a)
} }

View file

@ -4,9 +4,10 @@ use super::combine::{CombineFields, ObligationEmittingRelation};
use super::lattice::{self, LatticeDir}; use super::lattice::{self, LatticeDir};
use super::StructurallyRelateAliases; use super::StructurallyRelateAliases;
use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin}; use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
use crate::traits::{ObligationCause, PredicateObligation}; use crate::traits::ObligationCause;
use super::{Relate, RelateResult, TypeRelation}; use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::Span; use rustc_span::Span;
@ -147,7 +148,10 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
self.fields.register_predicates(obligations); self.fields.register_predicates(obligations);
} }
fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) { fn register_obligations(
&mut self,
obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
) {
self.fields.register_obligations(obligations) self.fields.register_obligations(obligations)
} }

View file

@ -1,11 +1,10 @@
use super::combine::CombineFields; use super::combine::CombineFields;
use crate::infer::relate::{ObligationEmittingRelation, StructurallyRelateAliases};
use crate::infer::BoundRegionConversionTime::HigherRankedType; use crate::infer::BoundRegionConversionTime::HigherRankedType;
use crate::infer::{DefineOpaqueTypes, SubregionOrigin}; use crate::infer::{DefineOpaqueTypes, SubregionOrigin};
use crate::traits::{Obligation, PredicateObligation}; use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::relate::{
use super::{ relate_args_invariantly, relate_args_with_variances, Relate, RelateResult, TypeRelation,
relate_args_invariantly, relate_args_with_variances, ObligationEmittingRelation, Relate,
RelateResult, StructurallyRelateAliases, TypeRelation,
}; };
use rustc_middle::ty::TyVar; use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
@ -88,9 +87,8 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
ty::Covariant => { ty::Covariant => {
// can't make progress on `A <: B` if both A and B are // can't make progress on `A <: B` if both A and B are
// type variables, so record an obligation. // type variables, so record an obligation.
self.fields.obligations.push(Obligation::new( self.fields.obligations.push(Goal::new(
self.tcx(), self.tcx(),
self.fields.trace.cause.clone(),
self.fields.param_env, self.fields.param_env,
ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
a_is_expected: true, a_is_expected: true,
@ -102,9 +100,8 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
ty::Contravariant => { ty::Contravariant => {
// can't make progress on `B <: A` if both A and B are // can't make progress on `B <: A` if both A and B are
// type variables, so record an obligation. // type variables, so record an obligation.
self.fields.obligations.push(Obligation::new( self.fields.obligations.push(Goal::new(
self.tcx(), self.tcx(),
self.fields.trace.cause.clone(),
self.fields.param_env, self.fields.param_env,
ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
a_is_expected: false, a_is_expected: false,
@ -153,10 +150,13 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
&& def_id.is_local() && def_id.is_local()
&& !infcx.next_trait_solver() => && !infcx.next_trait_solver() =>
{ {
// FIXME: Don't shuttle between Goal and Obligation
self.fields.obligations.extend( self.fields.obligations.extend(
infcx infcx
.handle_opaque_type(a, b, &self.fields.trace.cause, self.param_env())? .handle_opaque_type(a, b, &self.fields.trace.cause, self.param_env())?
.obligations, .obligations
.into_iter()
.map(Goal::from),
); );
} }
@ -318,7 +318,10 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
self.fields.register_predicates(obligations); self.fields.register_predicates(obligations);
} }
fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) { fn register_obligations(
&mut self,
obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
) {
self.fields.register_obligations(obligations); self.fields.register_obligations(obligations);
} }