diff options
| author | Boxy <supbscripter@gmail.com> | 2024-02-08 13:19:20 +0000 |
|---|---|---|
| committer | Boxy <supbscripter@gmail.com> | 2024-02-08 13:19:25 +0000 |
| commit | f867742be8a19ca253b0d7d1c9a4ab54b7ff02c5 (patch) | |
| tree | e22b6b50d8d00d2319aeeca635e6d727dd7d0cc8 | |
| parent | b181a1262326795a438e0d9118fd71b7bc94c3ae (diff) | |
| download | rust-f867742be8a19ca253b0d7d1c9a4ab54b7ff02c5.tar.gz rust-f867742be8a19ca253b0d7d1c9a4ab54b7ff02c5.zip | |
reviews + rebase
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 f7969e31dee..2d87f01ff10 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1032,7 +1032,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)) }) @@ -1043,7 +1042,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) diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index ff01f620e66..90be80f67b4 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 @@ 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:?}"); @@ -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 @@ 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 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 @@ impl<'tcx> InferCtxt<'tcx> { 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 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 2760356bcdf..5e2d2af9b85 100644 --- a/compiler/rustc_infer/src/infer/relate/nll.rs +++ b/compiler/rustc_infer/src/infer/relate/nll.rs @@ -261,54 +261,6 @@ where Ok(a) } - #[instrument(skip(self), level = "debug")] - fn enter_forall_and_leak_universe<T>(&mut self, binder: ty::Binder<'tcx, T>) -> T - where - T: ty::TypeFoldable<TyCtxt<'tcx>> + 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<T, U>( &mut self, binder: ty::Binder<'tcx, T>, @@ -317,7 +269,46 @@ where where T: ty::TypeFoldable<TyCtxt<'tcx>> + 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 daa4977a1e0..8dec04e2c4f 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 a1c55091c26..803379af005 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 @@ 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) }) } 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 2706b5c8e0d..69b69930432 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 @@ 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); diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 53307da1d9b..044832224e5 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 @@ 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)) }) 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 046b2718dba..5410a74199c 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 @@ 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(), 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 0f253981930..6d787a0ea6e 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 @@ 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) { 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 a1894de311e..d056dd51f50 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 @@ 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); + }) }) } diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index a85e86f41ac..777c649fabd 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<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. |
