about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_infer/src/infer/outlives/env.rs41
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs11
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs1
-rw-r--r--compiler/rustc_typeck/src/check/regionck.rs47
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs11
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs11
-rw-r--r--compiler/rustc_typeck/src/outlives/outlives_bounds.rs30
7 files changed, 70 insertions, 82 deletions
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs
index 7841d59caca..7afb44517a3 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -52,12 +52,10 @@ pub struct OutlivesEnvironment<'tcx> {
     region_bound_pairs: RegionBoundPairs<'tcx>,
 }
 
-/// Builder of OutlivesEnvironment. Use this structure if you need to add more outlives
-/// bounds than `explicit_outlives_bounds(param_env)`.
-pub struct OutlivesEnvironmentBuilder<'tcx> {
-    pub param_env: ty::ParamEnv<'tcx>,
+/// Builder of OutlivesEnvironment.
+struct OutlivesEnvironmentBuilder<'tcx> {
+    param_env: ty::ParamEnv<'tcx>,
     region_relation: TransitiveRelationBuilder<Region<'tcx>>,
-
     region_bound_pairs: RegionBoundPairs<'tcx>,
 }
 
@@ -69,7 +67,7 @@ pub type RegionBoundPairs<'tcx> =
 
 impl<'tcx> OutlivesEnvironment<'tcx> {
     /// Create a builder using `ParamEnv` and add explicit outlives bounds into it.
-    pub fn builder(param_env: ty::ParamEnv<'tcx>) -> OutlivesEnvironmentBuilder<'tcx> {
+    fn builder(param_env: ty::ParamEnv<'tcx>) -> OutlivesEnvironmentBuilder<'tcx> {
         let mut builder = OutlivesEnvironmentBuilder {
             param_env,
             region_relation: Default::default(),
@@ -87,6 +85,17 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
         Self::builder(param_env).build()
     }
 
+    /// Create a new `OutlivesEnvironment` with extra outlives bounds.
+    pub fn with_bounds<'a>(
+        param_env: ty::ParamEnv<'tcx>,
+        infcx: Option<&InferCtxt<'a, 'tcx>>,
+        extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>,
+    ) -> Self {
+        let mut builder = Self::builder(param_env);
+        builder.add_outlives_bounds(infcx, extra_bounds);
+        builder.build()
+    }
+
     /// Borrows current value of the `free_region_map`.
     pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> {
         &self.free_region_map
@@ -108,26 +117,14 @@ impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
         }
     }
 
-    // Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
-    // (with the exception that `'static: 'x` is not notable)
-    fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
-        debug!("relate_regions(sub={:?}, sup={:?})", sub, sup);
-        if sub.is_free_or_static() && sup.is_free() {
-            self.region_relation.add(sub, sup)
-        }
-    }
-
     /// Processes outlives bounds that are known to hold, whether from implied or other sources.
     ///
     /// The `infcx` parameter is optional; if the implied bounds may
     /// contain inference variables, it must be supplied, in which
     /// case we will register "givens" on the inference context. (See
     /// `RegionConstraintData`.)
-    pub fn add_outlives_bounds<I>(
-        &mut self,
-        infcx: Option<&InferCtxt<'a, 'tcx>>,
-        outlives_bounds: I,
-    ) where
+    fn add_outlives_bounds<I>(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I)
+    where
         I: IntoIterator<Item = OutlivesBound<'tcx>>,
     {
         // Record relationships such as `T:'x` that don't go into the
@@ -159,7 +156,9 @@ impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
                         // system to be more general and to make use
                         // of *every* relationship that arises here,
                         // but presently we do not.)
-                        self.relate_regions(r_a, r_b);
+                        if r_a.is_free_or_static() && r_b.is_free() {
+                            self.region_relation.add(r_a, r_b)
+                        }
                     }
                 }
             }
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index d645084375f..5fde6f396e5 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -1,6 +1,6 @@
 use super::potentially_plural_count;
-use crate::check::regionck::OutlivesEnvironmentExt;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
+use crate::outlives::outlives_bounds::InferCtxtExt as _;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
 use rustc_hir as hir;
@@ -401,9 +401,11 @@ fn compare_predicate_entailment<'tcx>(
 
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
-        let mut outlives_environment = OutlivesEnvironment::builder(param_env);
-        outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id);
-        let outlives_environment = outlives_environment.build();
+        let outlives_environment = OutlivesEnvironment::with_bounds(
+            param_env,
+            Some(infcx),
+            infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys),
+        );
         infcx.check_region_obligations_and_report_errors(
             impl_m.def_id.expect_local(),
             &outlives_environment,
@@ -1517,6 +1519,7 @@ pub fn check_type_bounds<'tcx>(
         let mut outlives_environment = OutlivesEnvironment::builder(param_env);
         outlives_environment.add_implied_bounds(&infcx, assumed_wf_types, impl_ty_hir_id);
         let outlives_environment = outlives_environment.build();
+
         infcx.check_region_obligations_and_report_errors(
             impl_ty.def_id.expect_local(),
             &outlives_environment,
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index dfbef544b1d..fb675212e3f 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -87,7 +87,6 @@ mod op;
 mod pat;
 mod place_op;
 mod region;
-pub mod regionck;
 pub mod rvalue_scopes;
 mod upvar;
 pub mod wfcheck;
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
deleted file mode 100644
index bcc1ea38c9d..00000000000
--- a/compiler/rustc_typeck/src/check/regionck.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use crate::outlives::outlives_bounds::InferCtxtExt as _;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_infer::infer::outlives::env::OutlivesEnvironmentBuilder;
-use rustc_infer::infer::InferCtxt;
-use rustc_middle::ty::Ty;
-
-pub(crate) trait OutlivesEnvironmentExt<'tcx> {
-    fn add_implied_bounds(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        fn_sig_tys: FxHashSet<Ty<'tcx>>,
-        body_id: hir::HirId,
-    );
-}
-
-impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironmentBuilder<'tcx> {
-    /// This method adds "implied bounds" into the outlives environment.
-    /// Implied bounds are outlives relationships that we can deduce
-    /// on the basis that certain types must be well-formed -- these are
-    /// either the types that appear in the function signature or else
-    /// the input types to an impl. For example, if you have a function
-    /// like
-    ///
-    /// ```
-    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
-    /// ```
-    ///
-    /// we can assume in the caller's body that `'b: 'a` and that `T:
-    /// 'b` (and hence, transitively, that `T: 'a`). This method would
-    /// add those assumptions into the outlives-environment.
-    ///
-    /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs`
-    #[instrument(level = "debug", skip(self, infcx))]
-    fn add_implied_bounds<'a>(
-        &mut self,
-        infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: FxHashSet<Ty<'tcx>>,
-        body_id: hir::HirId,
-    ) {
-        for ty in fn_sig_tys {
-            let ty = infcx.resolve_vars_if_possible(ty);
-            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty);
-            self.add_outlives_bounds(Some(infcx), implied_bounds)
-        }
-    }
-}
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 4f080c0cdfa..8396cb1ae0a 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -1,5 +1,5 @@
-use crate::check::regionck::OutlivesEnvironmentExt;
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
+use crate::outlives::outlives_bounds::InferCtxtExt as _;
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -107,6 +107,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
         let mut outlives_environment = OutlivesEnvironment::builder(param_env);
         outlives_environment.add_implied_bounds(infcx, assumed_wf_types, body_id);
         let outlives_environment = outlives_environment.build();
+
         infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
     })
 }
@@ -695,9 +696,11 @@ fn resolve_regions_with_wf_tys<'tcx>(
     // region constraints get added and solved there and we need to test each
     // call individually.
     tcx.infer_ctxt().enter(|infcx| {
-        let mut outlives_environment = OutlivesEnvironment::builder(param_env);
-        outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id);
-        let outlives_environment = outlives_environment.build();
+        let outlives_environment = OutlivesEnvironment::with_bounds(
+            param_env,
+            Some(&infcx),
+            infcx.implied_bounds_tys(param_env, id, wf_tys.iter().map(|ty| *ty)),
+        );
         let region_bound_pairs = outlives_environment.region_bound_pairs();
 
         add_constraints(&infcx, region_bound_pairs);
diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
index e841d79d940..72af5d79e09 100644
--- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
@@ -65,9 +65,9 @@
 //! cause use after frees with purely safe code in the same way as specializing
 //! on traits with methods can.
 
-use crate::check::regionck::OutlivesEnvironmentExt;
 use crate::constrained_generic_params as cgp;
 use crate::errors::SubstsOnOverriddenImpl;
+use crate::outlives::outlives_bounds::InferCtxtExt;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -147,10 +147,17 @@ fn get_impl_substs<'tcx>(
         let assumed_wf_types =
             ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
 
-        let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
+      let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
         let impl2_substs =
             translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
 
+
+
+
+
+
+
+
         let errors = ocx.select_all_or_error();
         if !errors.is_empty() {
             ocx.infcx.report_fulfillment_errors(&errors, None, false);
diff --git a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
index 229a6465084..769a3e7e11a 100644
--- a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
+++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
@@ -1,5 +1,6 @@
 use rustc_hir as hir;
-use rustc_middle::ty::{self, Ty};
+use rustc_hir::HirId;
+use rustc_middle::ty::{self, ParamEnv, Ty};
 use rustc_trait_selection::infer::InferCtxt;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput};
 use rustc_trait_selection::traits::query::NoSolution;
@@ -7,16 +8,23 @@ use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt
 
 pub use rustc_middle::traits::query::OutlivesBound;
 
-pub trait InferCtxtExt<'tcx> {
+pub trait InferCtxtExt<'a, 'tcx> {
     fn implied_outlives_bounds(
         &self,
         param_env: ty::ParamEnv<'tcx>,
         body_id: hir::HirId,
         ty: Ty<'tcx>,
     ) -> Vec<OutlivesBound<'tcx>>;
+
+    fn implied_bounds_tys(
+        &'a self,
+        param_env: ty::ParamEnv<'tcx>,
+        body_id: hir::HirId,
+        tys: impl IntoIterator<Item = Ty<'tcx>> + 'a,
+    ) -> Box<dyn Iterator<Item = OutlivesBound<'tcx>> + 'a>;
 }
 
-impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
     /// Implied bounds are region relationships that we deduce
     /// automatically. The idea is that (e.g.) a caller must check that a
     /// function's argument types are well-formed immediately before
@@ -87,4 +95,20 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
 
         output
     }
+
+    fn implied_bounds_tys(
+        &'a self,
+        param_env: ParamEnv<'tcx>,
+        body_id: HirId,
+        tys: impl IntoIterator<Item = Ty<'tcx>> + 'a,
+    ) -> Box<dyn Iterator<Item = OutlivesBound<'tcx>> + 'a> {
+        Box::new(
+            tys.into_iter()
+                .map(move |ty| {
+                    let ty = self.resolve_vars_if_possible(ty);
+                    self.implied_outlives_bounds(param_env, body_id, ty)
+                })
+                .flatten(),
+        )
+    }
 }