Skip to content

Commit

Permalink
Add InferCtxt::register_hidden_type_in_new_solver
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed May 25, 2023
1 parent 97c11ff commit 980da66
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 41 deletions.
1 change: 0 additions & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::*;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
Expand Down
23 changes: 23 additions & 0 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,29 @@ impl<'tcx> InferCtxt<'tcx> {
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(
&self,
OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>,
Expand Down
23 changes: 7 additions & 16 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
@@ -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::canonical::CanonicalVarValues;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
Expand Down Expand Up @@ -192,13 +192,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {

for &(a, b) in &input.predefined_opaques_in_body.opaque_types {
let InferOk { value: (), obligations } = infcx
.handle_opaque_type(
tcx.mk_opaque(a.def_id.to_def_id(), a.substs),
b,
true,
&ObligationCause::dummy(),
input.goal.param_env,
)
.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
Expand Down Expand Up @@ -727,19 +721,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
}
}

pub(super) fn can_define_opaque_ty(&mut self, def_id: DefId) -> bool {
let Some(def_id) = def_id.as_local() else { return false; };
pub(super) fn can_define_opaque_ty(&mut self, def_id: LocalDefId) -> bool {
self.infcx.opaque_type_origin(def_id).is_some()
}

pub(super) fn register_opaque_ty(
&mut self,
a: Ty<'tcx>,
a: ty::OpaqueTypeKey<'tcx>,
b: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Result<(), NoSolution> {
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()));
Ok(())
}
Expand All @@ -749,17 +742,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn unify_existing_opaque_tys(
&mut self,
param_env: ty::ParamEnv<'tcx>,
key: ty::AliasTy<'tcx>,
key: ty::OpaqueTypeKey<'tcx>,
ty: Ty<'tcx>,
) -> Vec<CanonicalResponse<'tcx>> {
let Some(def_id) = key.def_id.as_local() else { return vec![]; };

// FIXME: Super inefficient to be cloning this...
let opaques = self.infcx.clone_opaque_types_for_query_response();

let mut values = vec![];
for (candidate_key, candidate_ty) in opaques {
if candidate_key.def_id != def_id {
if candidate_key.def_id != key.def_id {
continue;
}
values.extend(self.probe(|ecx| {
Expand Down
31 changes: 10 additions & 21 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ 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,
};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty};
use rustc_span::DUMMY_SP;
use std::iter;
Expand Down Expand Up @@ -179,13 +179,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let Response { var_values, external_constraints, certainty } =
response.substitute(self.tcx(), &substitution);

let mut nested_goals =
self.unify_query_var_values(param_env, &original_values, var_values)?;
let nested_goals = self.unify_query_var_values(param_env, &original_values, var_values)?;

let ExternalConstraintsData { region_constraints, opaque_types } =
external_constraints.deref();
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))
}
Expand Down Expand Up @@ -310,24 +309,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
&mut self,
param_env: ty::ParamEnv<'tcx>,
opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)],
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
let mut nested_goals = vec![];
) -> Result<(), NoSolution> {
for &(a, b) in opaque_types {
nested_goals.extend(
self.infcx
.handle_opaque_type(
self.tcx().mk_opaque(a.def_id.to_def_id(), a.substs),
b,
true,
&ObligationCause::dummy(),
param_env,
)?
.into_obligations()
.into_iter()
.map(Goal::from),
);
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;
}

Ok(nested_goals)
Ok(())
}
}
10 changes: 7 additions & 3 deletions compiler/rustc_trait_selection/src/solve/opaques.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
match goal.param_env.reveal() {
Reveal::UserFacing => match self.solver_mode() {
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
// new opaque types but having the existing opaque type definitions.
// 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);
}
// FIXME: This may have issues when the substs contain aliases...
Expand All @@ -47,8 +52,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
}
}
// Otherwise, define a new opaque type
let opaque_ty = tcx.mk_opaque(opaque_ty.def_id, opaque_ty.substs);
self.register_opaque_ty(expected, opaque_ty, goal.param_env)?;
self.register_opaque_ty(opaque_ty, expected, goal.param_env)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
SolverMode::Coherence => {
Expand Down

0 comments on commit 980da66

Please sign in to comment.