Skip to content

Commit b62e20d

Browse files
committed
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.
1 parent 669d609 commit b62e20d

File tree

5 files changed

+114
-78
lines changed

5 files changed

+114
-78
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
2727
use rustc_middle::mir::AssertKind;
2828
use rustc_middle::mir::*;
2929
use rustc_middle::traits::query::NoSolution;
30+
use rustc_middle::traits::ObligationCause;
3031
use rustc_middle::ty::adjustment::PointerCast;
3132
use rustc_middle::ty::cast::CastTy;
3233
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
@@ -1051,15 +1052,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10511052
ConstraintCategory::OpaqueType,
10521053
CustomTypeOp::new(
10531054
|ocx| {
1054-
for (key, hidden_ty) in renumbered_opaques {
1055-
ocx.register_infer_ok_obligations(
1056-
ocx.infcx.register_hidden_type_in_new_solver(
1057-
key,
1058-
param_env,
1059-
hidden_ty.ty,
1060-
)?,
1055+
let mut obligations = Vec::new();
1056+
for (opaque_type_key, hidden_ty) in renumbered_opaques {
1057+
let cause = ObligationCause::dummy();
1058+
ocx.infcx.insert_hidden_type(
1059+
opaque_type_key,
1060+
&cause,
1061+
param_env,
1062+
hidden_ty.ty,
1063+
true,
1064+
&mut obligations,
1065+
)?;
1066+
1067+
ocx.infcx.add_item_bounds_for_hidden_type(
1068+
opaque_type_key,
1069+
cause,
1070+
param_env,
1071+
hidden_ty.ty,
1072+
&mut obligations,
10611073
);
10621074
}
1075+
1076+
ocx.register_obligations(obligations);
10631077
Ok(())
10641078
},
10651079
"register pre-defined opaques",

compiler/rustc_infer/src/infer/opaque_types.rs

+47-36
Original file line numberDiff line numberDiff line change
@@ -524,65 +524,76 @@ impl<'tcx> InferCtxt<'tcx> {
524524
hidden_ty: Ty<'tcx>,
525525
a_is_expected: bool,
526526
) -> InferResult<'tcx, ()> {
527+
let mut obligations = Vec::new();
528+
529+
self.insert_hidden_type(
530+
opaque_type_key,
531+
&cause,
532+
param_env,
533+
hidden_ty,
534+
a_is_expected,
535+
&mut obligations,
536+
)?;
537+
538+
self.add_item_bounds_for_hidden_type(
539+
opaque_type_key,
540+
cause,
541+
param_env,
542+
hidden_ty,
543+
&mut obligations,
544+
);
545+
546+
Ok(InferOk { value: (), obligations })
547+
}
548+
549+
/// Insert a hidden type into the opaque type storage, equating it
550+
/// with any previous entries if necessary.
551+
///
552+
/// This **does not** add the item bounds of the opaque as nested
553+
/// obligations. That is only necessary when normalizing the opaque
554+
/// itself, not when getting the opaque type constraints from
555+
/// somewhere else.
556+
pub fn insert_hidden_type(
557+
&self,
558+
opaque_type_key: OpaqueTypeKey<'tcx>,
559+
cause: &ObligationCause<'tcx>,
560+
param_env: ty::ParamEnv<'tcx>,
561+
hidden_ty: Ty<'tcx>,
562+
a_is_expected: bool,
563+
obligations: &mut Vec<PredicateObligation<'tcx>>,
564+
) -> Result<(), TypeError<'tcx>> {
527565
// Ideally, we'd get the span where *this specific `ty` came
528566
// from*, but right now we just use the span from the overall
529567
// value being folded. In simple cases like `-> impl Foo`,
530568
// these are the same span, but not in cases like `-> (impl
531569
// Foo, impl Bar)`.
532570
let span = cause.span;
533-
let mut obligations = if self.intercrate {
571+
if self.intercrate {
534572
// During intercrate we do not define opaque types but instead always
535573
// force ambiguity unless the hidden type is known to not implement
536574
// our trait.
537-
vec![traits::Obligation::new(
575+
obligations.push(traits::Obligation::new(
538576
self.tcx,
539577
cause.clone(),
540578
param_env,
541579
ty::PredicateKind::Ambiguous,
542-
)]
580+
))
543581
} else {
544582
let prev = self
545583
.inner
546584
.borrow_mut()
547585
.opaque_types()
548586
.register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
549587
if let Some(prev) = prev {
550-
self.at(&cause, param_env)
551-
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
552-
.obligations
553-
} else {
554-
Vec::new()
588+
obligations.extend(
589+
self.at(&cause, param_env)
590+
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
591+
.obligations,
592+
);
555593
}
556594
};
557595

558-
self.add_item_bounds_for_hidden_type(
559-
opaque_type_key,
560-
cause,
561-
param_env,
562-
hidden_ty,
563-
&mut obligations,
564-
);
565-
566-
Ok(InferOk { value: (), obligations })
567-
}
568-
569-
/// Registers an opaque's hidden type -- only should be used when the opaque
570-
/// can be defined. For something more fallible -- checks the anchors, tries
571-
/// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`.
572-
pub fn register_hidden_type_in_new_solver(
573-
&self,
574-
opaque_type_key: OpaqueTypeKey<'tcx>,
575-
param_env: ty::ParamEnv<'tcx>,
576-
hidden_ty: Ty<'tcx>,
577-
) -> InferResult<'tcx, ()> {
578-
assert!(self.next_trait_solver());
579-
self.register_hidden_type(
580-
opaque_type_key,
581-
ObligationCause::dummy(),
582-
param_env,
583-
hidden_ty,
584-
true,
585-
)
596+
Ok(())
586597
}
587598

588599
pub fn add_item_bounds_for_hidden_type(

compiler/rustc_trait_selection/src/solve/eval_ctxt.rs

+42-27
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use rustc_middle::traits::solve::{
1515
};
1616
use rustc_middle::traits::DefiningAnchor;
1717
use rustc_middle::ty::{
18-
self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
19-
TypeVisitor,
18+
self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
19+
TypeVisitableExt, TypeVisitor,
2020
};
2121
use rustc_span::DUMMY_SP;
2222
use std::ops::ControlFlow;
@@ -191,16 +191,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
191191
.with_opaque_type_inference(canonical_input.value.anchor)
192192
.build_with_canonical(DUMMY_SP, &canonical_input);
193193

194-
for &(a, b) in &input.predefined_opaques_in_body.opaque_types {
195-
let InferOk { value: (), obligations } = infcx
196-
.register_hidden_type_in_new_solver(a, input.goal.param_env, b)
197-
.expect("expected opaque type instantiation to succeed");
198-
// We're only registering opaques already defined by the caller,
199-
// so we're not responsible for proving that they satisfy their
200-
// item bounds, unless we use them in a normalizes-to goal,
201-
// which is handled in `EvalCtxt::unify_existing_opaque_tys`.
202-
let _ = obligations;
203-
}
204194
let mut ecx = EvalCtxt {
205195
infcx,
206196
var_values,
@@ -211,6 +201,15 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
211201
tainted: Ok(()),
212202
};
213203

204+
for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
205+
ecx.insert_hidden_type(key, input.goal.param_env, ty)
206+
.expect("failed to prepopulate opaque types");
207+
}
208+
209+
if !ecx.nested_goals.is_empty() {
210+
panic!("prepopulating opaque types shouldn't add goals: {:?}", ecx.nested_goals);
211+
}
212+
214213
let result = ecx.compute_goal(input.goal);
215214

216215
// When creating a query response we clone the opaque type constraints
@@ -729,18 +728,42 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
729728
self.infcx.opaque_type_origin(def_id).is_some()
730729
}
731730

732-
pub(super) fn register_opaque_ty(
731+
pub(super) fn insert_hidden_type(
733732
&mut self,
734-
a: ty::OpaqueTypeKey<'tcx>,
735-
b: Ty<'tcx>,
733+
opaque_type_key: OpaqueTypeKey<'tcx>,
736734
param_env: ty::ParamEnv<'tcx>,
735+
hidden_ty: Ty<'tcx>,
737736
) -> Result<(), NoSolution> {
738-
let InferOk { value: (), obligations } =
739-
self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?;
740-
self.add_goals(obligations.into_iter().map(|obligation| obligation.into()));
737+
let mut obligations = Vec::new();
738+
self.infcx.insert_hidden_type(
739+
opaque_type_key,
740+
&ObligationCause::dummy(),
741+
param_env,
742+
hidden_ty,
743+
true,
744+
&mut obligations,
745+
)?;
746+
self.add_goals(obligations.into_iter().map(|o| o.into()));
741747
Ok(())
742748
}
743749

750+
pub(super) fn add_item_bounds_for_hidden_type(
751+
&mut self,
752+
opaque_type_key: OpaqueTypeKey<'tcx>,
753+
param_env: ty::ParamEnv<'tcx>,
754+
hidden_ty: Ty<'tcx>,
755+
) {
756+
let mut obligations = Vec::new();
757+
self.infcx.add_item_bounds_for_hidden_type(
758+
opaque_type_key,
759+
ObligationCause::dummy(),
760+
param_env,
761+
hidden_ty,
762+
&mut obligations,
763+
);
764+
self.add_goals(obligations.into_iter().map(|o| o.into()));
765+
}
766+
744767
// Do something for each opaque/hidden pair defined with `def_id` in the
745768
// current inference context.
746769
pub(super) fn unify_existing_opaque_tys(
@@ -762,15 +785,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
762785
ecx.eq(param_env, a, b)?;
763786
}
764787
ecx.eq(param_env, candidate_ty, ty)?;
765-
let mut obl = vec![];
766-
ecx.infcx.add_item_bounds_for_hidden_type(
767-
candidate_key,
768-
ObligationCause::dummy(),
769-
param_env,
770-
candidate_ty,
771-
&mut obl,
772-
);
773-
ecx.add_goals(obl.into_iter().map(Into::into));
788+
ecx.add_item_bounds_for_hidden_type(candidate_key, param_env, candidate_ty);
774789
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
775790
}));
776791
}

compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use rustc_index::IndexVec;
1515
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
1616
use rustc_infer::infer::canonical::CanonicalVarValues;
1717
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
18-
use rustc_infer::infer::InferOk;
1918
use rustc_middle::traits::query::NoSolution;
2019
use rustc_middle::traits::solve::{
2120
ExternalConstraints, ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
@@ -317,12 +316,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
317316
param_env: ty::ParamEnv<'tcx>,
318317
opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)],
319318
) -> Result<(), NoSolution> {
320-
for &(a, b) in opaque_types {
321-
let InferOk { value: (), obligations } =
322-
self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?;
323-
// It's sound to drop these obligations, since the normalizes-to goal
324-
// is responsible for proving these obligations.
325-
let _ = obligations;
319+
for &(key, ty) in opaque_types {
320+
self.insert_hidden_type(key, param_env, ty)?;
326321
}
327322
Ok(())
328323
}

compiler/rustc_trait_selection/src/solve/opaques.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
5050
}
5151
}
5252
// Otherwise, define a new opaque type
53-
self.register_opaque_ty(opaque_ty, expected, goal.param_env)?;
53+
self.insert_hidden_type(opaque_ty, goal.param_env, expected)?;
54+
self.add_item_bounds_for_hidden_type(opaque_ty, goal.param_env, expected);
5455
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
5556
}
5657
(Reveal::UserFacing, SolverMode::Coherence) => {

0 commit comments

Comments
 (0)