Add InferCtxt::register_hidden_type_in_new_solver
This commit is contained in:
parent
97c11ffb22
commit
980da667fe
@ -26,7 +26,6 @@
|
|||||||
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::AssertKind;
|
use rustc_middle::mir::AssertKind;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::traits::ObligationCause;
|
|
||||||
use rustc_middle::ty::adjustment::PointerCast;
|
use rustc_middle::ty::adjustment::PointerCast;
|
||||||
use rustc_middle::ty::cast::CastTy;
|
use rustc_middle::ty::cast::CastTy;
|
||||||
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
|
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
|
||||||
|
@ -557,6 +557,29 @@ fn register_hidden_type(
|
|||||||
Ok(InferOk { value: (), 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.tcx.trait_solver_next());
|
||||||
|
let origin = self
|
||||||
|
.opaque_type_origin(opaque_type_key.def_id)
|
||||||
|
.expect("should be called for defining usages only");
|
||||||
|
self.register_hidden_type(
|
||||||
|
opaque_type_key,
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
param_env,
|
||||||
|
hidden_ty,
|
||||||
|
origin,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_item_bounds_for_hidden_type(
|
pub fn add_item_bounds_for_hidden_type(
|
||||||
&self,
|
&self,
|
||||||
OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>,
|
OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_infer::infer::at::ToTrace;
|
use rustc_infer::infer::at::ToTrace;
|
||||||
use rustc_infer::infer::canonical::CanonicalVarValues;
|
use rustc_infer::infer::canonical::CanonicalVarValues;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
@ -192,13 +192,7 @@ fn evaluate_canonical_goal(
|
|||||||
|
|
||||||
for &(a, b) in &input.predefined_opaques_in_body.opaque_types {
|
for &(a, b) in &input.predefined_opaques_in_body.opaque_types {
|
||||||
let InferOk { value: (), obligations } = infcx
|
let InferOk { value: (), obligations } = infcx
|
||||||
.handle_opaque_type(
|
.register_hidden_type_in_new_solver(a, input.goal.param_env, b)
|
||||||
tcx.mk_opaque(a.def_id.to_def_id(), a.substs),
|
|
||||||
b,
|
|
||||||
true,
|
|
||||||
&ObligationCause::dummy(),
|
|
||||||
input.goal.param_env,
|
|
||||||
)
|
|
||||||
.expect("expected opaque type instantiation to succeed");
|
.expect("expected opaque type instantiation to succeed");
|
||||||
// We're only registering opaques already defined by the caller,
|
// We're only registering opaques already defined by the caller,
|
||||||
// so we're not responsible for proving that they satisfy their
|
// so we're not responsible for proving that they satisfy their
|
||||||
@ -727,19 +721,18 @@ pub(super) fn is_transmutable(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn can_define_opaque_ty(&mut self, def_id: DefId) -> bool {
|
pub(super) fn can_define_opaque_ty(&mut self, def_id: LocalDefId) -> bool {
|
||||||
let Some(def_id) = def_id.as_local() else { return false; };
|
|
||||||
self.infcx.opaque_type_origin(def_id).is_some()
|
self.infcx.opaque_type_origin(def_id).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn register_opaque_ty(
|
pub(super) fn register_opaque_ty(
|
||||||
&mut self,
|
&mut self,
|
||||||
a: Ty<'tcx>,
|
a: ty::OpaqueTypeKey<'tcx>,
|
||||||
b: Ty<'tcx>,
|
b: Ty<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
let InferOk { value: (), obligations } =
|
let InferOk { value: (), obligations } =
|
||||||
self.infcx.handle_opaque_type(a, b, true, &ObligationCause::dummy(), param_env)?;
|
self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?;
|
||||||
self.add_goals(obligations.into_iter().map(|obligation| obligation.into()));
|
self.add_goals(obligations.into_iter().map(|obligation| obligation.into()));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -749,17 +742,15 @@ pub(super) fn register_opaque_ty(
|
|||||||
pub(super) fn unify_existing_opaque_tys(
|
pub(super) fn unify_existing_opaque_tys(
|
||||||
&mut self,
|
&mut self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
key: ty::AliasTy<'tcx>,
|
key: ty::OpaqueTypeKey<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Vec<CanonicalResponse<'tcx>> {
|
) -> Vec<CanonicalResponse<'tcx>> {
|
||||||
let Some(def_id) = key.def_id.as_local() else { return vec![]; };
|
|
||||||
|
|
||||||
// FIXME: Super inefficient to be cloning this...
|
// FIXME: Super inefficient to be cloning this...
|
||||||
let opaques = self.infcx.clone_opaque_types_for_query_response();
|
let opaques = self.infcx.clone_opaque_types_for_query_response();
|
||||||
|
|
||||||
let mut values = vec![];
|
let mut values = vec![];
|
||||||
for (candidate_key, candidate_ty) in opaques {
|
for (candidate_key, candidate_ty) in opaques {
|
||||||
if candidate_key.def_id != def_id {
|
if candidate_key.def_id != key.def_id {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
values.extend(self.probe(|ecx| {
|
values.extend(self.probe(|ecx| {
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
|
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
|
||||||
use rustc_infer::infer::canonical::CanonicalVarValues;
|
use rustc_infer::infer::canonical::CanonicalVarValues;
|
||||||
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
|
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
|
||||||
|
use rustc_infer::infer::InferOk;
|
||||||
use rustc_middle::traits::query::NoSolution;
|
use rustc_middle::traits::query::NoSolution;
|
||||||
use rustc_middle::traits::solve::{
|
use rustc_middle::traits::solve::{
|
||||||
ExternalConstraints, ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
|
ExternalConstraints, ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
|
||||||
};
|
};
|
||||||
use rustc_middle::traits::ObligationCause;
|
|
||||||
use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty};
|
use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty};
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
@ -179,13 +179,12 @@ pub(super) fn instantiate_and_apply_query_response(
|
|||||||
let Response { var_values, external_constraints, certainty } =
|
let Response { var_values, external_constraints, certainty } =
|
||||||
response.substitute(self.tcx(), &substitution);
|
response.substitute(self.tcx(), &substitution);
|
||||||
|
|
||||||
let mut nested_goals =
|
let nested_goals = self.unify_query_var_values(param_env, &original_values, var_values)?;
|
||||||
self.unify_query_var_values(param_env, &original_values, var_values)?;
|
|
||||||
|
|
||||||
let ExternalConstraintsData { region_constraints, opaque_types } =
|
let ExternalConstraintsData { region_constraints, opaque_types } =
|
||||||
external_constraints.deref();
|
external_constraints.deref();
|
||||||
self.register_region_constraints(region_constraints);
|
self.register_region_constraints(region_constraints);
|
||||||
nested_goals.extend(self.register_opaque_types(param_env, opaque_types)?);
|
self.register_opaque_types(param_env, opaque_types)?;
|
||||||
|
|
||||||
Ok((certainty, nested_goals))
|
Ok((certainty, nested_goals))
|
||||||
}
|
}
|
||||||
@ -310,24 +309,14 @@ fn register_opaque_types(
|
|||||||
&mut self,
|
&mut self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)],
|
opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)],
|
||||||
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
let mut nested_goals = vec![];
|
|
||||||
for &(a, b) in opaque_types {
|
for &(a, b) in opaque_types {
|
||||||
nested_goals.extend(
|
let InferOk { value: (), obligations } =
|
||||||
self.infcx
|
self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?;
|
||||||
.handle_opaque_type(
|
// It's sound to drop these obligations, since the normalizes-to goal
|
||||||
self.tcx().mk_opaque(a.def_id.to_def_id(), a.substs),
|
// is responsible for proving these obligations.
|
||||||
b,
|
let _ = obligations;
|
||||||
true,
|
|
||||||
&ObligationCause::dummy(),
|
|
||||||
param_env,
|
|
||||||
)?
|
|
||||||
.into_obligations()
|
|
||||||
.into_iter()
|
|
||||||
.map(Goal::from),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
Ok(nested_goals)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,15 @@ pub(super) fn normalize_opaque_type(
|
|||||||
match goal.param_env.reveal() {
|
match goal.param_env.reveal() {
|
||||||
Reveal::UserFacing => match self.solver_mode() {
|
Reveal::UserFacing => match self.solver_mode() {
|
||||||
SolverMode::Normal => {
|
SolverMode::Normal => {
|
||||||
|
let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else {
|
||||||
|
return Err(NoSolution);
|
||||||
|
};
|
||||||
|
let opaque_ty =
|
||||||
|
ty::OpaqueTypeKey { def_id: opaque_ty_def_id, substs: opaque_ty.substs };
|
||||||
// FIXME: at some point we should call queries without defining
|
// FIXME: at some point we should call queries without defining
|
||||||
// new opaque types but having the existing opaque type definitions.
|
// new opaque types but having the existing opaque type definitions.
|
||||||
// This will require moving this below "Prefer opaques registered already".
|
// This will require moving this below "Prefer opaques registered already".
|
||||||
if !self.can_define_opaque_ty(opaque_ty.def_id) {
|
if !self.can_define_opaque_ty(opaque_ty_def_id) {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
// FIXME: This may have issues when the substs contain aliases...
|
// FIXME: This may have issues when the substs contain aliases...
|
||||||
@ -47,8 +52,7 @@ pub(super) fn normalize_opaque_type(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Otherwise, define a new opaque type
|
// Otherwise, define a new opaque type
|
||||||
let opaque_ty = tcx.mk_opaque(opaque_ty.def_id, opaque_ty.substs);
|
self.register_opaque_ty(opaque_ty, expected, goal.param_env)?;
|
||||||
self.register_opaque_ty(expected, opaque_ty, goal.param_env)?;
|
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
}
|
}
|
||||||
SolverMode::Coherence => {
|
SolverMode::Coherence => {
|
||||||
|
Loading…
Reference in New Issue
Block a user