From 807cd85dfaab718dc29be6d94dc545db01035ed1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 14 Dec 2023 15:59:51 +0000 Subject: Add higher_ranked to relate submodule --- .../rustc_infer/src/infer/higher_ranked/mod.rs | 136 --------------------- compiler/rustc_infer/src/infer/mod.rs | 1 - .../rustc_infer/src/infer/relate/higher_ranked.rs | 136 +++++++++++++++++++++ compiler/rustc_infer/src/infer/relate/mod.rs | 11 +- .../occurs-check/associated-type.next.stderr | 16 +-- 5 files changed, 150 insertions(+), 150 deletions(-) delete mode 100644 compiler/rustc_infer/src/infer/higher_ranked/mod.rs create mode 100644 compiler/rustc_infer/src/infer/relate/higher_ranked.rs diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs deleted file mode 100644 index 0de988efaee..00000000000 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ /dev/null @@ -1,136 +0,0 @@ -//! Helper routines for higher-ranked things. See the `doc` module at -//! the end of the file for details. - -use super::{HigherRankedType, InferCtxt}; -use crate::infer::relate::combine::CombineFields; -use crate::infer::CombinedSnapshot; -use rustc_middle::ty::fold::FnMutDelegate; -use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; -use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable}; - -impl<'a, 'tcx> CombineFields<'a, 'tcx> { - /// Checks whether `for<..> sub <: for<..> sup` holds. - /// - /// For this to hold, **all** instantiations of the super type - /// have to be a super type of **at least one** instantiation of - /// the subtype. - /// - /// This is implemented by first entering a new universe. - /// We then replace all bound variables in `sup` with placeholders, - /// and all bound variables in `sub` with inference vars. - /// We can then just relate the two resulting types as normal. - /// - /// Note: this is a subtle algorithm. For a full explanation, please see - /// the [rustc dev guide][rd] - /// - /// [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html - #[instrument(skip(self), level = "debug")] - pub fn higher_ranked_sub( - &mut self, - sub: Binder<'tcx, T>, - sup: Binder<'tcx, T>, - sub_is_expected: bool, - ) -> RelateResult<'tcx, ()> - where - T: Relate<'tcx>, - { - let span = self.trace.cause.span; - // First, we instantiate each bound region in the supertype with a - // fresh placeholder region. Note that this automatically creates - // a new universe if needed. - let sup_prime = self.infcx.instantiate_binder_with_placeholders(sup); - - // Next, we instantiate each bound region in the subtype - // with a fresh region variable. These region variables -- - // but no other preexisting region variables -- can name - // the placeholders. - let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub); - - debug!("a_prime={:?}", sub_prime); - debug!("b_prime={:?}", sup_prime); - - // Compare types now that bound regions have been replaced. - let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime)?; - - debug!("OK result={result:?}"); - // NOTE: returning the result here would be dangerous as it contains - // placeholders which **must not** be named afterwards. - Ok(()) - } -} - -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. - /// - /// 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]. - /// - /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html - #[instrument(level = "debug", skip(self), ret)] - pub fn instantiate_binder_with_placeholders(&self, binder: ty::Binder<'tcx, T>) -> T - where - T: TypeFoldable> + Copy, - { - if let Some(inner) = binder.no_bound_vars() { - return inner; - } - - let next_universe = self.create_next_universe(); - - let delegate = FnMutDelegate { - regions: &mut |br: ty::BoundRegion| { - ty::Region::new_placeholder( - self.tcx, - ty::PlaceholderRegion { universe: next_universe, bound: br }, - ) - }, - types: &mut |bound_ty: ty::BoundTy| { - Ty::new_placeholder( - self.tcx, - ty::PlaceholderType { universe: next_universe, bound: bound_ty }, - ) - }, - consts: &mut |bound_var: ty::BoundVar, ty| { - ty::Const::new_placeholder( - self.tcx, - ty::PlaceholderConst { universe: next_universe, bound: bound_var }, - ty, - ) - }, - }; - - debug!(?next_universe); - self.tcx.replace_bound_vars_uncached(binder, delegate) - } - - /// See [RegionConstraintCollector::leak_check][1]. We only check placeholder - /// leaking into `outer_universe`, i.e. placeholders which cannot be named by that - /// universe. - /// - /// [1]: crate::infer::region_constraints::RegionConstraintCollector::leak_check - pub fn leak_check( - &self, - outer_universe: ty::UniverseIndex, - only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>, - ) -> RelateResult<'tcx, ()> { - // If the user gave `-Zno-leak-check`, or we have been - // configured to skip the leak check, then skip the leak check - // completely. The leak check is deprecated. Any legitimate - // subtyping errors that it would have caught will now be - // caught later on, during region checking. However, we - // continue to use it for a transition period. - if self.tcx.sess.opts.unstable_opts.no_leak_check || self.skip_leak_check { - return Ok(()); - } - - self.inner.borrow_mut().unwrap_region_constraints().leak_check( - self.tcx, - outer_universe, - self.universe(), - only_consider_snapshot, - ) - } -} diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 5aa9c82b3ca..88e4787848c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -59,7 +59,6 @@ pub mod error_reporting; pub mod free_regions; mod freshen; mod fudge; -mod higher_ranked; mod lexical_region_resolve; pub mod nll_relate; pub mod opaque_types; diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs new file mode 100644 index 00000000000..440df8c8936 --- /dev/null +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -0,0 +1,136 @@ +//! Helper routines for higher-ranked things. See the `doc` module at +//! the end of the file for details. + +use super::combine::CombineFields; +use crate::infer::CombinedSnapshot; +use crate::infer::{HigherRankedType, InferCtxt}; +use rustc_middle::ty::fold::FnMutDelegate; +use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable}; + +impl<'a, 'tcx> CombineFields<'a, 'tcx> { + /// Checks whether `for<..> sub <: for<..> sup` holds. + /// + /// For this to hold, **all** instantiations of the super type + /// have to be a super type of **at least one** instantiation of + /// the subtype. + /// + /// This is implemented by first entering a new universe. + /// We then replace all bound variables in `sup` with placeholders, + /// and all bound variables in `sub` with inference vars. + /// We can then just relate the two resulting types as normal. + /// + /// Note: this is a subtle algorithm. For a full explanation, please see + /// the [rustc dev guide][rd] + /// + /// [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html + #[instrument(skip(self), level = "debug")] + pub fn higher_ranked_sub( + &mut self, + sub: Binder<'tcx, T>, + sup: Binder<'tcx, T>, + sub_is_expected: bool, + ) -> RelateResult<'tcx, ()> + where + T: Relate<'tcx>, + { + let span = self.trace.cause.span; + // First, we instantiate each bound region in the supertype with a + // fresh placeholder region. Note that this automatically creates + // a new universe if needed. + let sup_prime = self.infcx.instantiate_binder_with_placeholders(sup); + + // Next, we instantiate each bound region in the subtype + // with a fresh region variable. These region variables -- + // but no other preexisting region variables -- can name + // the placeholders. + let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub); + + debug!("a_prime={:?}", sub_prime); + debug!("b_prime={:?}", sup_prime); + + // Compare types now that bound regions have been replaced. + let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime)?; + + debug!("OK result={result:?}"); + // NOTE: returning the result here would be dangerous as it contains + // placeholders which **must not** be named afterwards. + Ok(()) + } +} + +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. + /// + /// 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]. + /// + /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html + #[instrument(level = "debug", skip(self), ret)] + pub fn instantiate_binder_with_placeholders(&self, binder: ty::Binder<'tcx, T>) -> T + where + T: TypeFoldable> + Copy, + { + if let Some(inner) = binder.no_bound_vars() { + return inner; + } + + let next_universe = self.create_next_universe(); + + let delegate = FnMutDelegate { + regions: &mut |br: ty::BoundRegion| { + ty::Region::new_placeholder( + self.tcx, + ty::PlaceholderRegion { universe: next_universe, bound: br }, + ) + }, + types: &mut |bound_ty: ty::BoundTy| { + Ty::new_placeholder( + self.tcx, + ty::PlaceholderType { universe: next_universe, bound: bound_ty }, + ) + }, + consts: &mut |bound_var: ty::BoundVar, ty| { + ty::Const::new_placeholder( + self.tcx, + ty::PlaceholderConst { universe: next_universe, bound: bound_var }, + ty, + ) + }, + }; + + debug!(?next_universe); + self.tcx.replace_bound_vars_uncached(binder, delegate) + } + + /// See [RegionConstraintCollector::leak_check][1]. We only check placeholder + /// leaking into `outer_universe`, i.e. placeholders which cannot be named by that + /// universe. + /// + /// [1]: crate::infer::region_constraints::RegionConstraintCollector::leak_check + pub fn leak_check( + &self, + outer_universe: ty::UniverseIndex, + only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>, + ) -> RelateResult<'tcx, ()> { + // If the user gave `-Zno-leak-check`, or we have been + // configured to skip the leak check, then skip the leak check + // completely. The leak check is deprecated. Any legitimate + // subtyping errors that it would have caught will now be + // caught later on, during region checking. However, we + // continue to use it for a transition period. + if self.tcx.sess.opts.unstable_opts.no_leak_check || self.skip_leak_check { + return Ok(()); + } + + self.inner.borrow_mut().unwrap_region_constraints().leak_check( + self.tcx, + outer_universe, + self.universe(), + only_consider_snapshot, + ) + } +} diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs index e431734996f..37cbc2de27e 100644 --- a/compiler/rustc_infer/src/infer/relate/mod.rs +++ b/compiler/rustc_infer/src/infer/relate/mod.rs @@ -3,9 +3,10 @@ //! and heuristics in the compiler). pub(super) mod combine; -pub(super) mod equate; +mod equate; pub(super) mod generalize; -pub(super) mod glb; -pub(super) mod lattice; -pub(super) mod lub; -pub(super) mod sub; +mod glb; +mod higher_ranked; +mod lattice; +mod lub; +mod sub; diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 69f541cba05..f64e8b39798 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -1,11 +1,11 @@ -WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:31:1 | -- cgit 1.4.1-3-g733a5