about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs207
1 files changed, 97 insertions, 110 deletions
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index d5a8ca5ea78..7b4ad9fea13 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -2,20 +2,18 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::TraitEngineExt as _;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
 use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives;
 use rustc_trait_selection::traits::query::dropck_outlives::{
     DropckConstraint, DropckOutlivesResult,
 };
 use rustc_trait_selection::traits::query::normalize::AtExt;
 use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
-use rustc_trait_selection::traits::{
-    Normalized, ObligationCause, TraitEngine, TraitEngineExt as _,
-};
+use rustc_trait_selection::traits::{Normalized, ObligationCause};
 
 pub(crate) fn provide(p: &mut Providers) {
     *p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p };
@@ -27,120 +25,109 @@ fn dropck_outlives<'tcx>(
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution> {
     debug!("dropck_outlives(goal={:#?})", canonical_goal);
 
-    let (ref infcx, goal, canonical_inference_vars) =
-        tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
-    let tcx = infcx.tcx;
-    let ParamEnvAnd { param_env, value: for_ty } = goal;
-
-    let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
-
-    // A stack of types left to process. Each round, we pop
-    // something from the stack and invoke
-    // `dtorck_constraint_for_ty`. This may produce new types that
-    // have to be pushed on the stack. This continues until we have explored
-    // all the reachable types from the type `for_ty`.
-    //
-    // Example: Imagine that we have the following code:
-    //
-    // ```rust
-    // struct A {
-    //     value: B,
-    //     children: Vec<A>,
-    // }
-    //
-    // struct B {
-    //     value: u32
-    // }
-    //
-    // fn f() {
-    //   let a: A = ...;
-    //   ..
-    // } // here, `a` is dropped
-    // ```
-    //
-    // at the point where `a` is dropped, we need to figure out
-    // which types inside of `a` contain region data that may be
-    // accessed by any destructors in `a`. We begin by pushing `A`
-    // onto the stack, as that is the type of `a`. We will then
-    // invoke `dtorck_constraint_for_ty` which will expand `A`
-    // into the types of its fields `(B, Vec<A>)`. These will get
-    // pushed onto the stack. Eventually, expanding `Vec<A>` will
-    // lead to us trying to push `A` a second time -- to prevent
-    // infinite recursion, we notice that `A` was already pushed
-    // once and stop.
-    let mut ty_stack = vec![(for_ty, 0)];
-
-    // Set used to detect infinite recursion.
-    let mut ty_set = FxHashSet::default();
-
-    let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
-
-    let cause = ObligationCause::dummy();
-    let mut constraints = DropckConstraint::empty();
-    while let Some((ty, depth)) = ty_stack.pop() {
-        debug!(
-            "{} kinds, {} overflows, {} ty_stack",
-            result.kinds.len(),
-            result.overflows.len(),
-            ty_stack.len()
-        );
-        dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
-
-        // "outlives" represent types/regions that may be touched
-        // by a destructor.
-        result.kinds.append(&mut constraints.outlives);
-        result.overflows.append(&mut constraints.overflows);
-
-        // If we have even one overflow, we should stop trying to evaluate further --
-        // chances are, the subsequent overflows for this evaluation won't provide useful
-        // information and will just decrease the speed at which we can emit these errors
-        // (since we'll be printing for just that much longer for the often enormous types
-        // that result here).
-        if !result.overflows.is_empty() {
-            break;
-        }
+    tcx.infer_ctxt().enter_canonical_trait_query(&canonical_goal, |ocx, goal| {
+        let tcx = ocx.infcx.tcx;
+        let ParamEnvAnd { param_env, value: for_ty } = goal;
+
+        let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
+
+        // A stack of types left to process. Each round, we pop
+        // something from the stack and invoke
+        // `dtorck_constraint_for_ty`. This may produce new types that
+        // have to be pushed on the stack. This continues until we have explored
+        // all the reachable types from the type `for_ty`.
+        //
+        // Example: Imagine that we have the following code:
+        //
+        // ```rust
+        // struct A {
+        //     value: B,
+        //     children: Vec<A>,
+        // }
+        //
+        // struct B {
+        //     value: u32
+        // }
+        //
+        // fn f() {
+        //   let a: A = ...;
+        //   ..
+        // } // here, `a` is dropped
+        // ```
+        //
+        // at the point where `a` is dropped, we need to figure out
+        // which types inside of `a` contain region data that may be
+        // accessed by any destructors in `a`. We begin by pushing `A`
+        // onto the stack, as that is the type of `a`. We will then
+        // invoke `dtorck_constraint_for_ty` which will expand `A`
+        // into the types of its fields `(B, Vec<A>)`. These will get
+        // pushed onto the stack. Eventually, expanding `Vec<A>` will
+        // lead to us trying to push `A` a second time -- to prevent
+        // infinite recursion, we notice that `A` was already pushed
+        // once and stop.
+        let mut ty_stack = vec![(for_ty, 0)];
+
+        // Set used to detect infinite recursion.
+        let mut ty_set = FxHashSet::default();
+
+        let cause = ObligationCause::dummy();
+        let mut constraints = DropckConstraint::empty();
+        while let Some((ty, depth)) = ty_stack.pop() {
+            debug!(
+                "{} kinds, {} overflows, {} ty_stack",
+                result.kinds.len(),
+                result.overflows.len(),
+                ty_stack.len()
+            );
+            dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
+
+            // "outlives" represent types/regions that may be touched
+            // by a destructor.
+            result.kinds.append(&mut constraints.outlives);
+            result.overflows.append(&mut constraints.overflows);
+
+            // If we have even one overflow, we should stop trying to evaluate further --
+            // chances are, the subsequent overflows for this evaluation won't provide useful
+            // information and will just decrease the speed at which we can emit these errors
+            // (since we'll be printing for just that much longer for the often enormous types
+            // that result here).
+            if !result.overflows.is_empty() {
+                break;
+            }
 
-        // dtorck types are "types that will get dropped but which
-        // do not themselves define a destructor", more or less. We have
-        // to push them onto the stack to be expanded.
-        for ty in constraints.dtorck_types.drain(..) {
-            match infcx.at(&cause, param_env).normalize(ty) {
-                Ok(Normalized { value: ty, obligations }) => {
-                    fulfill_cx.register_predicate_obligations(infcx, obligations);
-
-                    debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
-
-                    match ty.kind() {
-                        // All parameters live for the duration of the
-                        // function.
-                        ty::Param(..) => {}
-
-                        // A projection that we couldn't resolve - it
-                        // might have a destructor.
-                        ty::Projection(..) | ty::Opaque(..) => {
-                            result.kinds.push(ty.into());
-                        }
+            // dtorck types are "types that will get dropped but which
+            // do not themselves define a destructor", more or less. We have
+            // to push them onto the stack to be expanded.
+            for ty in constraints.dtorck_types.drain(..) {
+                let Normalized { value: ty, obligations } =
+                    ocx.infcx.at(&cause, param_env).normalize(ty)?;
+                ocx.register_obligations(obligations);
+
+                debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+
+                match ty.kind() {
+                    // All parameters live for the duration of the
+                    // function.
+                    ty::Param(..) => {}
+
+                    // A projection that we couldn't resolve - it
+                    // might have a destructor.
+                    ty::Projection(..) | ty::Opaque(..) => {
+                        result.kinds.push(ty.into());
+                    }
 
-                        _ => {
-                            if ty_set.insert(ty) {
-                                ty_stack.push((ty, depth + 1));
-                            }
+                    _ => {
+                        if ty_set.insert(ty) {
+                            ty_stack.push((ty, depth + 1));
                         }
                     }
                 }
-
-                // We don't actually expect to fail to normalize.
-                // That implies a WF error somewhere else.
-                Err(NoSolution) => {
-                    return Err(NoSolution);
-                }
             }
         }
-    }
-
-    debug!("dropck_outlives: result = {:#?}", result);
 
-    infcx.make_canonicalized_query_response(canonical_inference_vars, result, &mut *fulfill_cx)
+        debug!("dropck_outlives: result = {:#?}", result);
+        Ok(result)
+    })
 }
 
 /// Returns a set of constraints that needs to be satisfied in