about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs43
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs13
-rw-r--r--compiler/rustc_typeck/src/check/regionck.rs4
-rw-r--r--compiler/rustc_typeck/src/outlives/outlives_bounds.rs63
6 files changed, 71 insertions, 56 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 670b5549afc..813307356c4 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -334,8 +334,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
     /// either the return type of the MIR or one of its arguments. At
     /// the same time, compute and add any implied bounds that come
     /// from this local.
+    #[instrument(level = "debug", skip(self))]
     fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<QueryRegionConstraints<'tcx>>> {
-        debug!("add_implied_bounds(ty={:?})", ty);
         let TypeOpOutput { output: bounds, constraints, .. } = self
             .param_env
             .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 5671711397a..ec468f42852 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -547,25 +547,34 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx> {
         unsubstituted_region_constraints.iter().map(move |&constraint| {
             let predicate = substitute_value(self.tcx, result_subst, constraint);
-            let ty::OutlivesPredicate(k1, r2) = predicate.skip_binder();
+            self.query_outlives_constraint_to_obligation(predicate, cause.clone(), param_env)
+        })
+    }
 
-            let atom = match k1.unpack() {
-                GenericArgKind::Lifetime(r1) => {
-                    ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
-                }
-                GenericArgKind::Type(t1) => {
-                    ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t1, r2))
-                }
-                GenericArgKind::Const(..) => {
-                    // Consts cannot outlive one another, so we don't expect to
-                    // encounter this branch.
-                    span_bug!(cause.span, "unexpected const outlives {:?}", constraint);
-                }
-            };
-            let predicate = predicate.rebind(atom).to_predicate(self.tcx);
+    pub fn query_outlives_constraint_to_obligation(
+        &self,
+        predicate: QueryOutlivesConstraint<'tcx>,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Obligation<'tcx, ty::Predicate<'tcx>> {
+        let ty::OutlivesPredicate(k1, r2) = predicate.skip_binder();
 
-            Obligation::new(cause.clone(), param_env, predicate)
-        })
+        let atom = match k1.unpack() {
+            GenericArgKind::Lifetime(r1) => {
+                ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
+            }
+            GenericArgKind::Type(t1) => {
+                ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t1, r2))
+            }
+            GenericArgKind::Const(..) => {
+                // Consts cannot outlive one another, so we don't expect to
+                // encounter this branch.
+                span_bug!(cause.span, "unexpected const outlives {:?}", predicate);
+            }
+        };
+        let predicate = predicate.rebind(atom).to_predicate(self.tcx);
+
+        Obligation::new(cause, param_env, predicate)
     }
 
     /// Given two sets of values for the same set of canonical variables, unify them.
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 03d6c45a653..b9652e83e65 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -8,10 +8,10 @@ pub mod verify;
 use rustc_middle::traits::query::OutlivesBound;
 use rustc_middle::ty;
 
+#[instrument(level = "debug", skip(param_env))]
 pub fn explicit_outlives_bounds<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
 ) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
-    debug!("explicit_outlives_bounds()");
     param_env
         .caller_bounds()
         .into_iter()
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index 04c382d439d..46d6e973d4c 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,7 +1,7 @@
 use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
 use rustc_infer::traits::query::OutlivesBound;
-use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt};
 
 #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)]
 pub struct ImpliedOutlivesBounds<'tcx> {
@@ -13,9 +13,16 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
 
     fn try_fast_path(
         _tcx: TyCtxt<'tcx>,
-        _key: &ParamEnvAnd<'tcx, Self>,
+        key: &ParamEnvAnd<'tcx, Self>,
     ) -> Option<Self::QueryResponse> {
-        None
+        // Don't go into the query for things that can't possibly have lifetimes.
+        match key.value.ty.kind() {
+            ty::Tuple(elems) if elems.is_empty() => Some(vec![]),
+            ty::Never | ty::Str | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
+                Some(vec![])
+            }
+            _ => None,
+        }
     }
 
     fn perform_query(
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
index e4be4603558..65b38b3f2e7 100644
--- a/compiler/rustc_typeck/src/check/regionck.rs
+++ b/compiler/rustc_typeck/src/check/regionck.rs
@@ -129,6 +129,7 @@ impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
     /// 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>,
@@ -136,11 +137,8 @@ impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
         body_id: hir::HirId,
         span: Span,
     ) {
-        debug!("add_implied_bounds()");
-
         for ty in fn_sig_tys {
             let ty = infcx.resolve_vars_if_possible(ty);
-            debug!("add_implied_bounds: ty = {}", ty);
             let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
             self.add_outlives_bounds(Some(infcx), implied_bounds)
         }
diff --git a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
index 87f844fafe6..3bf697e7682 100644
--- a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
+++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
@@ -1,9 +1,8 @@
 use rustc_hir as hir;
-use rustc_infer::traits::TraitEngineExt as _;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::source_map::Span;
-use rustc_trait_selection::infer::canonical::OriginalQueryValues;
 use rustc_trait_selection::infer::InferCtxt;
+use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput};
 use rustc_trait_selection::traits::query::NoSolution;
 use rustc_trait_selection::traits::{FulfillmentContext, ObligationCause, TraitEngine};
 
@@ -41,6 +40,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
     /// - `ty`, the type that we are supposed to assume is WF.
     /// - `span`, a span to use when normalizing, hopefully not important,
     ///   might be useful if a `bug!` occurs.
+    #[instrument(level = "debug", skip(self, param_env, body_id, span))]
     fn implied_outlives_bounds(
         &self,
         param_env: ty::ParamEnv<'tcx>,
@@ -48,11 +48,10 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
         ty: Ty<'tcx>,
         span: Span,
     ) -> Vec<OutlivesBound<'tcx>> {
-        debug!("implied_outlives_bounds(ty = {:?})", ty);
-
-        let mut orig_values = OriginalQueryValues::default();
-        let key = self.canonicalize_query(param_env.and(ty), &mut orig_values);
-        let result = match self.tcx.implied_outlives_bounds(key) {
+        let result = param_env
+            .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
+            .fully_perform(self);
+        let result = match result {
             Ok(r) => r,
             Err(NoSolution) => {
                 self.tcx.sess.delay_span_bug(
@@ -62,32 +61,34 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
                 return vec![];
             }
         };
-        assert!(result.value.is_proven());
 
-        let result = self.instantiate_query_response_and_region_obligations(
-            &ObligationCause::misc(span, body_id),
-            param_env,
-            &orig_values,
-            result,
-        );
-        debug!("implied_outlives_bounds for {:?}: {:#?}", ty, result);
-        let Ok(result) = result else {
-            self.tcx.sess.delay_span_bug(span, "implied_outlives_bounds failed to instantiate");
-            return vec![];
-        };
+        let TypeOpOutput { output, constraints, .. } = result;
 
-        // Instantiation may have produced new inference variables and constraints on those
-        // variables. Process these constraints.
-        let mut fulfill_cx = FulfillmentContext::new();
-        fulfill_cx.register_predicate_obligations(self, result.obligations);
-        let errors = fulfill_cx.select_all_or_error(self);
-        if !errors.is_empty() {
-            self.tcx.sess.delay_span_bug(
-                span,
-                "implied_outlives_bounds failed to solve obligations from instantiation",
-            );
-        }
+        if let Some(constraints) = constraints {
+            // Instantiation may have produced new inference variables and constraints on those
+            // variables. Process these constraints.
+            let mut fulfill_cx = FulfillmentContext::new();
+            let cause = ObligationCause::misc(span, body_id);
+            for &constraint in &constraints.outlives {
+                let obligation = self.query_outlives_constraint_to_obligation(
+                    constraint,
+                    cause.clone(),
+                    param_env,
+                );
+                fulfill_cx.register_predicate_obligation(self, obligation);
+            }
+            if !constraints.member_constraints.is_empty() {
+                span_bug!(span, "{:#?}", constraints.member_constraints);
+            }
+            let errors = fulfill_cx.select_all_or_error(self);
+            if !errors.is_empty() {
+                self.tcx.sess.delay_span_bug(
+                    span,
+                    "implied_outlives_bounds failed to solve obligations from instantiation",
+                );
+            }
+        };
 
-        result.value
+        output
     }
 }