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.
This commit is contained in:
parent
669d609dfd
commit
b62e20d2fd
5 changed files with 121 additions and 85 deletions
|
@ -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)
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue