From f867742be8a19ca253b0d7d1c9a4ab54b7ff02c5 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 8 Feb 2024 13:19:20 +0000 Subject: [PATCH] reviews + rebase --- compiler/rustc_infer/src/infer/mod.rs | 2 - .../src/infer/relate/higher_ranked.rs | 15 +-- compiler/rustc_infer/src/infer/relate/nll.rs | 89 ++++++++--------- .../src/solve/assembly/structural_traits.rs | 4 +- .../src/solve/eval_ctxt/mod.rs | 1 - .../src/solve/eval_ctxt/select.rs | 1 - .../src/solve/trait_goals.rs | 1 - .../src/traits/error_reporting/suggestions.rs | 1 - .../error_reporting/type_err_ctxt_ext.rs | 1 - .../src/traits/select/candidate_assembly.rs | 97 +++++++++---------- compiler/rustc_type_ir/src/region_kind.rs | 3 +- 11 files changed, 101 insertions(+), 114 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f7969e31dee8..2d87f01ff104 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1032,7 +1032,6 @@ pub fn subtype_predicate( _ => {} } - // 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)) }) @@ -1043,7 +1042,6 @@ pub fn region_outlives_predicate( 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) diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index ff01f620e668..90be80f67b4d 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -49,7 +49,6 @@ pub fn higher_ranked_sub( 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:?}"); @@ -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)] @@ -111,14 +110,14 @@ pub fn enter_forall_and_leak_universe(&self, binder: ty::Binder<'tcx, T>) -> } /// 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 created 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))] @@ -126,6 +125,10 @@ pub fn enter_forall(&self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) where T: TypeFoldable> + 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 outlives 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) diff --git a/compiler/rustc_infer/src/infer/relate/nll.rs b/compiler/rustc_infer/src/infer/relate/nll.rs index 2760356bcdf3..5e2d2af9b858 100644 --- a/compiler/rustc_infer/src/infer/relate/nll.rs +++ b/compiler/rustc_infer/src/infer/relate/nll.rs @@ -261,54 +261,6 @@ fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty< Ok(a) } - #[instrument(skip(self), level = "debug")] - fn enter_forall_and_leak_universe(&mut self, binder: ty::Binder<'tcx, T>) -> T - where - T: ty::TypeFoldable> + Copy, - { - if let Some(inner) = binder.no_bound_vars() { - return inner; - } - - let mut next_region = { - let nll_delegate = &mut self.delegate; - let mut lazy_universe = None; - - move |br: ty::BoundRegion| { - // The first time this closure is called, create a - // new universe for the placeholders we will make - // from here out. - let universe = lazy_universe.unwrap_or_else(|| { - let universe = nll_delegate.create_next_universe(); - lazy_universe = Some(universe); - universe - }); - - let placeholder = ty::PlaceholderRegion { universe, bound: br }; - debug!(?placeholder); - let placeholder_reg = nll_delegate.next_placeholder_region(placeholder); - debug!(?placeholder_reg); - - placeholder_reg - } - }; - - let delegate = FnMutDelegate { - regions: &mut next_region, - types: &mut |_bound_ty: ty::BoundTy| { - unreachable!("we only replace regions in nll_relate, not types") - }, - consts: &mut |_bound_var: ty::BoundVar, _ty| { - unreachable!("we only replace regions in nll_relate, not consts") - }, - }; - - let replaced = self.infcx.tcx.replace_bound_vars_uncached(binder, delegate); - debug!(?replaced); - - replaced - } - fn enter_forall( &mut self, binder: ty::Binder<'tcx, T>, @@ -317,7 +269,46 @@ fn enter_forall( where T: ty::TypeFoldable> + Copy, { - let value = self.enter_forall_and_leak_universe(binder); + let value = if let Some(inner) = binder.no_bound_vars() { + inner + } else { + let mut next_region = { + let nll_delegate = &mut self.delegate; + let mut lazy_universe = None; + + move |br: ty::BoundRegion| { + // The first time this closure is called, create a + // new universe for the placeholders we will make + // from here out. + let universe = lazy_universe.unwrap_or_else(|| { + let universe = nll_delegate.create_next_universe(); + lazy_universe = Some(universe); + universe + }); + + let placeholder = ty::PlaceholderRegion { universe, bound: br }; + debug!(?placeholder); + let placeholder_reg = nll_delegate.next_placeholder_region(placeholder); + debug!(?placeholder_reg); + + placeholder_reg + } + }; + + let delegate = FnMutDelegate { + regions: &mut next_region, + types: &mut |_bound_ty: ty::BoundTy| { + unreachable!("we only replace regions in nll_relate, not types") + }, + consts: &mut |_bound_var: ty::BoundVar, _ty| { + unreachable!("we only replace regions in nll_relate, not consts") + }, + }; + + self.infcx.tcx.replace_bound_vars_uncached(binder, delegate) + }; + + debug!(?value); f(self, value) } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index daa4977a1e0e..8dec04e2c4f2 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -59,7 +59,9 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]), - ty::CoroutineClosure(_, args) => Ok(vec![args.as_coroutine_closure().tupled_upvars_ty()]), + ty::CoroutineClosure(_, args) => { + Ok(vec![ty::Binder::dummy(args.as_coroutine_closure().tupled_upvars_ty())]) + } ty::Coroutine(_, args) => { let coroutine_args = args.as_coroutine(); diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index a1c55091c267..803379af005f 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -480,7 +480,6 @@ fn compute_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) -> QueryResult 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) }) } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 2706b5c8e0d2..69b699304326 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -31,7 +31,6 @@ fn select_in_new_trait_solver( ) -> 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); diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 53307da1d9be..044832224e5c 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -1060,7 +1060,6 @@ fn probe_and_evaluate_goal_for_constituent_tys( 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)) }) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 046b2718dba8..5410a74199cf 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -4621,7 +4621,6 @@ fn explain_hrtb_projection( 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(), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 0f253981930c..6d787a0ea6e9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2049,7 +2049,6 @@ fn report_similar_impl_candidates( 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) { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index a1894de311ef..d056dd51f507 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -728,64 +728,63 @@ fn assemble_candidates_from_object_ty( 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; - } - - 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 { + ); + candidates.vec.push(BuiltinObjectCandidate); return; } - } else { - // Only auto trait bounds exist. + + 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; + } + } + 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, - }; + _ => return, + }; - debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); + 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`, - // but `Foo` is declared as `trait Foo: Bar`. - 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() + // 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`, + // but `Foo` is declared as `trait Foo: Bar`. + 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); + }) }) } diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index a85e86f41ac5..777c649fabd6 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -163,8 +163,7 @@ pub enum RegionKind { /// 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.