diff options
| author | lcnr <rust@lcnr.de> | 2023-06-09 16:41:11 +0200 |
|---|---|---|
| committer | lcnr <rust@lcnr.de> | 2023-06-09 16:41:11 +0200 |
| commit | b62e20d2fd5fd186a662c5621a41b717fcc313e0 (patch) | |
| tree | d9a2feb6226bb035cc3ffc5a051043b298f93b08 | |
| parent | 669d609dfda2f61f2b358c9e9061f76ebd852e7e (diff) | |
| download | rust-b62e20d2fd5fd186a662c5621a41b717fcc313e0.tar.gz rust-b62e20d2fd5fd186a662c5621a41b717fcc313e0.zip | |
split opaque type handling in new solver
be more explicit in where we only add new hidden types and where we also have to deal with item bounds.
5 files changed, 114 insertions, 78 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 63a2a24fd43..6697e1aff7d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -27,6 +27,7 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::AssertKind; use rustc_middle::mir::*; use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::subst::{SubstsRef, UserSubsts}; @@ -1051,15 +1052,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::OpaqueType, CustomTypeOp::new( |ocx| { - for (key, hidden_ty) in renumbered_opaques { - ocx.register_infer_ok_obligations( - ocx.infcx.register_hidden_type_in_new_solver( - key, - param_env, - hidden_ty.ty, - )?, + let mut obligations = Vec::new(); + for (opaque_type_key, hidden_ty) in renumbered_opaques { + let cause = ObligationCause::dummy(); + ocx.infcx.insert_hidden_type( + opaque_type_key, + &cause, + param_env, + hidden_ty.ty, + true, + &mut obligations, + )?; + + ocx.infcx.add_item_bounds_for_hidden_type( + opaque_type_key, + cause, + param_env, + hidden_ty.ty, + &mut obligations, ); } + + ocx.register_obligations(obligations); Ok(()) }, "register pre-defined opaques", diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 44efd334a16..6b8293f90f1 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -524,22 +524,60 @@ impl<'tcx> InferCtxt<'tcx> { hidden_ty: Ty<'tcx>, a_is_expected: bool, ) -> InferResult<'tcx, ()> { + let mut obligations = Vec::new(); + + self.insert_hidden_type( + opaque_type_key, + &cause, + param_env, + hidden_ty, + a_is_expected, + &mut obligations, + )?; + + self.add_item_bounds_for_hidden_type( + opaque_type_key, + cause, + param_env, + hidden_ty, + &mut obligations, + ); + + Ok(InferOk { value: (), obligations }) + } + + /// Insert a hidden type into the opaque type storage, equating it + /// with any previous entries if necessary. + /// + /// This **does not** add the item bounds of the opaque as nested + /// obligations. That is only necessary when normalizing the opaque + /// itself, not when getting the opaque type constraints from + /// somewhere else. + pub fn insert_hidden_type( + &self, + opaque_type_key: OpaqueTypeKey<'tcx>, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + hidden_ty: Ty<'tcx>, + a_is_expected: bool, + obligations: &mut Vec<PredicateObligation<'tcx>>, + ) -> Result<(), TypeError<'tcx>> { // Ideally, we'd get the span where *this specific `ty` came // from*, but right now we just use the span from the overall // value being folded. In simple cases like `-> impl Foo`, // these are the same span, but not in cases like `-> (impl // Foo, impl Bar)`. let span = cause.span; - let mut obligations = if self.intercrate { + if self.intercrate { // During intercrate we do not define opaque types but instead always // force ambiguity unless the hidden type is known to not implement // our trait. - vec![traits::Obligation::new( + obligations.push(traits::Obligation::new( self.tcx, cause.clone(), param_env, ty::PredicateKind::Ambiguous, - )] + )) } else { let prev = self .inner @@ -547,42 +585,15 @@ impl<'tcx> InferCtxt<'tcx> { .opaque_types() .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span }); if let Some(prev) = prev { - self.at(&cause, param_env) - .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? - .obligations - } else { - Vec::new() + obligations.extend( + self.at(&cause, param_env) + .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? + .obligations, + ); } }; - self.add_item_bounds_for_hidden_type( - opaque_type_key, - cause, - param_env, - hidden_ty, - &mut obligations, - ); - - Ok(InferOk { value: (), obligations }) - } - - /// Registers an opaque's hidden type -- only should be used when the opaque - /// can be defined. For something more fallible -- checks the anchors, tries - /// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`. - pub fn register_hidden_type_in_new_solver( - &self, - opaque_type_key: OpaqueTypeKey<'tcx>, - param_env: ty::ParamEnv<'tcx>, - hidden_ty: Ty<'tcx>, - ) -> InferResult<'tcx, ()> { - assert!(self.next_trait_solver()); - self.register_hidden_type( - opaque_type_key, - ObligationCause::dummy(), - param_env, - hidden_ty, - true, - ) + Ok(()) } pub fn add_item_bounds_for_hidden_type( diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 3001d9f1b1f..e01187bcd3c 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -15,8 +15,8 @@ use rustc_middle::traits::solve::{ }; use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, - TypeVisitor, + self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, }; use rustc_span::DUMMY_SP; use std::ops::ControlFlow; @@ -191,16 +191,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { .with_opaque_type_inference(canonical_input.value.anchor) .build_with_canonical(DUMMY_SP, &canonical_input); - for &(a, b) in &input.predefined_opaques_in_body.opaque_types { - let InferOk { value: (), obligations } = infcx - .register_hidden_type_in_new_solver(a, input.goal.param_env, b) - .expect("expected opaque type instantiation to succeed"); - // We're only registering opaques already defined by the caller, - // so we're not responsible for proving that they satisfy their - // item bounds, unless we use them in a normalizes-to goal, - // which is handled in `EvalCtxt::unify_existing_opaque_tys`. - let _ = obligations; - } let mut ecx = EvalCtxt { infcx, var_values, @@ -211,6 +201,15 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { tainted: Ok(()), }; + for &(key, ty) in &input.predefined_opaques_in_body.opaque_types { + ecx.insert_hidden_type(key, input.goal.param_env, ty) + .expect("failed to prepopulate opaque types"); + } + + if !ecx.nested_goals.is_empty() { + panic!("prepopulating opaque types shouldn't add goals: {:?}", ecx.nested_goals); + } + let result = ecx.compute_goal(input.goal); // When creating a query response we clone the opaque type constraints @@ -729,18 +728,42 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.infcx.opaque_type_origin(def_id).is_some() } - pub(super) fn register_opaque_ty( + pub(super) fn insert_hidden_type( &mut self, - a: ty::OpaqueTypeKey<'tcx>, - b: Ty<'tcx>, + opaque_type_key: OpaqueTypeKey<'tcx>, param_env: ty::ParamEnv<'tcx>, + hidden_ty: Ty<'tcx>, ) -> Result<(), NoSolution> { - let InferOk { value: (), obligations } = - self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?; - self.add_goals(obligations.into_iter().map(|obligation| obligation.into())); + let mut obligations = Vec::new(); + self.infcx.insert_hidden_type( + opaque_type_key, + &ObligationCause::dummy(), + param_env, + hidden_ty, + true, + &mut obligations, + )?; + self.add_goals(obligations.into_iter().map(|o| o.into())); Ok(()) } + pub(super) fn add_item_bounds_for_hidden_type( + &mut self, + opaque_type_key: OpaqueTypeKey<'tcx>, + param_env: ty::ParamEnv<'tcx>, + hidden_ty: Ty<'tcx>, + ) { + let mut obligations = Vec::new(); + self.infcx.add_item_bounds_for_hidden_type( + opaque_type_key, + ObligationCause::dummy(), + param_env, + hidden_ty, + &mut obligations, + ); + self.add_goals(obligations.into_iter().map(|o| o.into())); + } + // Do something for each opaque/hidden pair defined with `def_id` in the // current inference context. pub(super) fn unify_existing_opaque_tys( @@ -762,15 +785,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ecx.eq(param_env, a, b)?; } ecx.eq(param_env, candidate_ty, ty)?; - let mut obl = vec![]; - ecx.infcx.add_item_bounds_for_hidden_type( - candidate_key, - ObligationCause::dummy(), - param_env, - candidate_ty, - &mut obl, - ); - ecx.add_goals(obl.into_iter().map(Into::into)); + ecx.add_item_bounds_for_hidden_type(candidate_key, param_env, candidate_ty); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) })); } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index bca2343e424..db673410008 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -15,7 +15,6 @@ use rustc_index::IndexVec; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints}; -use rustc_infer::infer::InferOk; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{ ExternalConstraints, ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput, @@ -317,12 +316,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { param_env: ty::ParamEnv<'tcx>, opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)], ) -> Result<(), NoSolution> { - for &(a, b) in opaque_types { - let InferOk { value: (), obligations } = - self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?; - // It's sound to drop these obligations, since the normalizes-to goal - // is responsible for proving these obligations. - let _ = obligations; + for &(key, ty) in opaque_types { + self.insert_hidden_type(key, param_env, ty)?; } Ok(()) } diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs index a5de4ddee82..538c16c8ce2 100644 --- a/compiler/rustc_trait_selection/src/solve/opaques.rs +++ b/compiler/rustc_trait_selection/src/solve/opaques.rs @@ -50,7 +50,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } // Otherwise, define a new opaque type - self.register_opaque_ty(opaque_ty, expected, goal.param_env)?; + self.insert_hidden_type(opaque_ty, goal.param_env, expected)?; + self.add_item_bounds_for_hidden_type(opaque_ty, goal.param_env, expected); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } (Reveal::UserFacing, SolverMode::Coherence) => { |
