Skip to content

Commit

Permalink
reviews + rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
BoxyUwU committed Feb 6, 2024
1 parent baa0ebc commit 9544ee1
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 64 deletions.
2 changes: 0 additions & 2 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,6 @@ impl<'tcx> InferCtxt<'tcx> {
_ => {}
}

// FIXME(tree_universes): leaking placeholders
self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b))
})
Expand All @@ -1042,7 +1041,6 @@ impl<'tcx> InferCtxt<'tcx> {
cause: &traits::ObligationCause<'tcx>,
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
) {
// FIXME(tree_universes): leaking placeholders
self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| {
let origin = SubregionOrigin::from_obligation_cause(cause, || {
RelateRegionParamBound(cause.span)
Expand Down
15 changes: 9 additions & 6 deletions compiler/rustc_infer/src/infer/relate/higher_ranked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
debug!("b_prime={:?}", sup_prime);

// Compare types now that bound regions have been replaced.
// FIXME(tree_universes): leaked universes
let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime);
if result.is_ok() {
debug!("OK result={result:?}");
Expand All @@ -70,7 +69,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// This is the first step of checking subtyping when higher-ranked things are involved.
/// For more details visit the relevant sections of the [rustc dev guide].
///
/// `enter_forall` should be preferred over this method.
/// fn `enter_forall` should be preferred over this method.
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
#[instrument(level = "debug", skip(self), ret)]
Expand Down Expand Up @@ -111,21 +110,25 @@ impl<'tcx> InferCtxt<'tcx> {
}

/// Replaces all bound variables (lifetimes, types, and constants) bound by
/// `binder` with placeholder variables in a new universe. This means that the
/// new placeholders can only be named by inference variables created after
/// this method has been called.
/// `binder` with placeholder variables in a new universe and then calls the
/// closure `f` with the instantiated value. The new placeholders can only be
/// named by inference variables inside of the closure `f` or afterwards.
///
/// This is the first step of checking subtyping when higher-ranked things are involved.
/// For more details visit the relevant sections of the [rustc dev guide].
///
/// This method should be preferred over `enter_forall_and_leak_universe`.
/// This method should be preferred over `fn enter_forall_and_leak_universe`.
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
#[instrument(level = "debug", skip(self, f))]
pub fn enter_forall<T, U>(&self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U) -> U
where
T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
// FIXME: currently we do nothing to prevent placeholders with the new universe being
// used after exiting `f`. For example region subtyping can result in outlive constraints
// that name placeholders created in this function. Nested goals from type relations can
// also contain placeholders created by this function.
let value = self.enter_forall_and_leak_universe(forall);
debug!("?value");
f(value)
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
self.infcx.enter_forall(kind, |kind| {
let goal = goal.with(self.tcx(), ty::Binder::dummy(kind));
self.add_goal(GoalSource::Misc, goal);
// FIXME(tree_universes): leaking universes
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
) -> SelectionResult<'tcx, Selection<'tcx>> {
assert!(self.next_trait_solver());

// FIXME(tree_universes): leaking universes?
self.enter_forall(obligation.predicate, |pred| {
let trait_goal = Goal::new(self.tcx, obligation.param_env, pred);

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
constituent_tys(ecx, goal.predicate.self_ty())?
.into_iter()
.map(|ty| {
// FIXME(tree_universes): leaking universes
ecx.enter_forall(ty, |ty| {
goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty))
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4621,7 +4621,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let ocx = ObligationCtxt::new(self);
self.enter_forall(pred, |pred| {
let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred);
// FIXME(tree_universes): universe leakage
ocx.register_obligation(Obligation::new(
self.tcx,
ObligationCause::dummy(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2042,7 +2042,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
for (obligation_arg, impl_arg) in
std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
{
// FIXME(tree_universes): universe leakage
if let Err(terr) =
ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -665,64 +665,63 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

self.infcx.probe(|_snapshot| {
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
self.infcx.enter_forall_and_leak_universe(poly_trait_predicate);

let self_ty = placeholder_trait_predicate.self_ty();
let principal_trait_ref = match self_ty.kind() {
ty::Dynamic(data, ..) => {
if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
debug!(
"assemble_candidates_from_object_ty: matched builtin bound, \
self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| {
let self_ty = placeholder_trait_predicate.self_ty();
let principal_trait_ref = match self_ty.kind() {
ty::Dynamic(data, ..) => {
if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
debug!(
"assemble_candidates_from_object_ty: matched builtin bound, \
pushing candidate"
);
candidates.vec.push(BuiltinObjectCandidate);
return;
}
);
candidates.vec.push(BuiltinObjectCandidate);
return;
}

if let Some(principal) = data.principal() {
if !self.infcx.tcx.features().object_safe_for_dispatch {
principal.with_self_ty(self.tcx(), self_ty)
} else if self.tcx().check_is_object_safe(principal.def_id()) {
principal.with_self_ty(self.tcx(), self_ty)
if let Some(principal) = data.principal() {
if !self.infcx.tcx.features().object_safe_for_dispatch {
principal.with_self_ty(self.tcx(), self_ty)
} else if self.tcx().check_is_object_safe(principal.def_id()) {
principal.with_self_ty(self.tcx(), self_ty)
} else {
return;
}
} else {
// Only auto trait bounds exist.
return;
}
} else {
// Only auto trait bounds exist.
}
ty::Infer(ty::TyVar(_)) => {
debug!("assemble_candidates_from_object_ty: ambiguous");
candidates.ambiguous = true; // could wind up being an object type
return;
}
}
ty::Infer(ty::TyVar(_)) => {
debug!("assemble_candidates_from_object_ty: ambiguous");
candidates.ambiguous = true; // could wind up being an object type
return;
}
_ => return,
};

debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");

// Count only those upcast versions that match the trait-ref
// we are looking for. Specifically, do not only check for the
// correct trait, but also the correct type parameters.
// For example, we may be trying to upcast `Foo` to `Bar<i32>`,
// but `Foo` is declared as `trait Foo: Bar<u32>`.
let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
.enumerate()
.filter(|&(_, upcast_trait_ref)| {
self.infcx.probe(|_| {
self.match_normalize_trait_ref(
obligation,
upcast_trait_ref,
placeholder_trait_predicate.trait_ref,
)
.is_ok()
_ => return,
};

debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");

// Count only those upcast versions that match the trait-ref
// we are looking for. Specifically, do not only check for the
// correct trait, but also the correct type parameters.
// For example, we may be trying to upcast `Foo` to `Bar<i32>`,
// but `Foo` is declared as `trait Foo: Bar<u32>`.
let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
.enumerate()
.filter(|&(_, upcast_trait_ref)| {
self.infcx.probe(|_| {
self.match_normalize_trait_ref(
obligation,
upcast_trait_ref,
placeholder_trait_predicate.trait_ref,
)
.is_ok()
})
})
})
.map(|(idx, _)| ObjectCandidate(idx));
.map(|(idx, _)| ObjectCandidate(idx));

candidates.vec.extend(candidate_supertraits);
candidates.vec.extend(candidate_supertraits);
})
})
}

Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_type_ir/src/region_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,7 @@ pub enum RegionKind<I: Interner> {
/// A placeholder region -- the higher-ranked version of `ReLateParam`.
/// Should not exist outside of type inference.
///
/// Used when instantiating a `forall` binder via
/// `infcx.enter_forall` and `infcx.enter_forall_and_leak_universe`.
/// Used when instantiating a `forall` binder via `infcx.enter_forall`.
RePlaceholder(I::PlaceholderRegion),

/// Erased region, used by trait selection, in MIR and during codegen.
Expand Down

0 comments on commit 9544ee1

Please sign in to comment.