]> git.lizzy.rs Git - rust.git/commitdiff
Move traits::query datatypes to traits::types.
authorCamille GILLOT <gillot.camille@gmail.com>
Wed, 22 Jan 2020 08:04:50 +0000 (09:04 +0100)
committerCamille GILLOT <gillot.camille@gmail.com>
Wed, 5 Feb 2020 07:45:09 +0000 (08:45 +0100)
13 files changed:
src/librustc/traits/query/dropck_outlives.rs
src/librustc/traits/query/method_autoderef.rs
src/librustc/traits/query/mod.rs
src/librustc/traits/query/normalize.rs
src/librustc/traits/query/outlives_bounds.rs
src/librustc/traits/query/type_op/ascribe_user_type.rs
src/librustc/traits/query/type_op/eq.rs
src/librustc/traits/query/type_op/mod.rs
src/librustc/traits/query/type_op/normalize.rs
src/librustc/traits/query/type_op/prove_predicate.rs
src/librustc/traits/query/type_op/subtype.rs
src/librustc/traits/types/mod.rs
src/librustc/traits/types/query.rs [new file with mode: 0644]

index 2e5ef5adcd30ed96b5329993e54b65728e3c67ed..a1d7a2836e42d3c032f5a165bea61a95e2b2c6d7 100644 (file)
@@ -1,10 +1,11 @@
 use crate::infer::at::At;
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::InferOk;
-use crate::ty::subst::GenericArg;
-use crate::ty::{self, Ty, TyCtxt};
-use rustc_span::source_map::Span;
-use std::iter::FromIterator;
+
+use rustc::ty::subst::GenericArg;
+use rustc::ty::{self, Ty, TyCtxt};
+
+pub use rustc::traits::query::{DropckOutlivesResult, DtorckConstraint};
 
 impl<'cx, 'tcx> At<'cx, 'tcx> {
     /// Given a type `ty` of some value being dropped, computes a set
@@ -65,76 +66,6 @@ pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<GenericArg<'tcx
     }
 }
 
-#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
-pub struct DropckOutlivesResult<'tcx> {
-    pub kinds: Vec<GenericArg<'tcx>>,
-    pub overflows: Vec<Ty<'tcx>>,
-}
-
-impl<'tcx> DropckOutlivesResult<'tcx> {
-    pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
-        if let Some(overflow_ty) = self.overflows.iter().next() {
-            rustc_errors::struct_span_err!(
-                tcx.sess,
-                span,
-                E0320,
-                "overflow while adding drop-check rules for {}",
-                ty,
-            )
-            .note(&format!("overflowed on {}", overflow_ty))
-            .emit();
-        }
-    }
-
-    pub fn into_kinds_reporting_overflows(
-        self,
-        tcx: TyCtxt<'tcx>,
-        span: Span,
-        ty: Ty<'tcx>,
-    ) -> Vec<GenericArg<'tcx>> {
-        self.report_overflows(tcx, span, ty);
-        let DropckOutlivesResult { kinds, overflows: _ } = self;
-        kinds
-    }
-}
-
-/// A set of constraints that need to be satisfied in order for
-/// a type to be valid for destruction.
-#[derive(Clone, Debug, HashStable)]
-pub struct DtorckConstraint<'tcx> {
-    /// Types that are required to be alive in order for this
-    /// type to be valid for destruction.
-    pub outlives: Vec<ty::subst::GenericArg<'tcx>>,
-
-    /// Types that could not be resolved: projections and params.
-    pub dtorck_types: Vec<Ty<'tcx>>,
-
-    /// If, during the computation of the dtorck constraint, we
-    /// overflow, that gets recorded here. The caller is expected to
-    /// report an error.
-    pub overflows: Vec<Ty<'tcx>>,
-}
-
-impl<'tcx> DtorckConstraint<'tcx> {
-    pub fn empty() -> DtorckConstraint<'tcx> {
-        DtorckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] }
-    }
-}
-
-impl<'tcx> FromIterator<DtorckConstraint<'tcx>> for DtorckConstraint<'tcx> {
-    fn from_iter<I: IntoIterator<Item = DtorckConstraint<'tcx>>>(iter: I) -> Self {
-        let mut result = Self::empty();
-
-        for DtorckConstraint { outlives, dtorck_types, overflows } in iter {
-            result.outlives.extend(outlives);
-            result.dtorck_types.extend(dtorck_types);
-            result.overflows.extend(overflows);
-        }
-
-        result
-    }
-}
-
 /// This returns true if the type `ty` is "trivial" for
 /// dropck-outlives -- that is, if it doesn't require any types to
 /// outlive. This is similar but not *quite* the same as the
index 4ef775750ec3778144c0cde60877a994f717df7d..80748c5ef388efe15f3109b5f6990e9e6517896c 100644 (file)
@@ -1,33 +1 @@
-use crate::infer::canonical::{Canonical, QueryResponse};
-use crate::ty::Ty;
-use rustc_data_structures::sync::Lrc;
-
-#[derive(Debug, HashStable)]
-pub struct CandidateStep<'tcx> {
-    pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
-    pub autoderefs: usize,
-    /// `true` if the type results from a dereference of a raw pointer.
-    /// when assembling candidates, we include these steps, but not when
-    /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
-    /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
-    /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
-    pub from_unsafe_deref: bool,
-    pub unsize: bool,
-}
-
-#[derive(Clone, Debug, HashStable)]
-pub struct MethodAutoderefStepsResult<'tcx> {
-    /// The valid autoderef steps that could be find.
-    pub steps: Lrc<Vec<CandidateStep<'tcx>>>,
-    /// If Some(T), a type autoderef reported an error on.
-    pub opt_bad_ty: Option<Lrc<MethodAutoderefBadTy<'tcx>>>,
-    /// If `true`, `steps` has been truncated due to reaching the
-    /// recursion limit.
-    pub reached_recursion_limit: bool,
-}
-
-#[derive(Debug, HashStable)]
-pub struct MethodAutoderefBadTy<'tcx> {
-    pub reached_raw_pointer: bool,
-    pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
-}
+pub use rustc::traits::query::{CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult};
index 440268aab8fb399629903853ea01b7d7ffaaff63..20a873dc4c6b6692e69730db871580fb0be8ef3f 100644 (file)
@@ -5,10 +5,6 @@
 //! The providers for the queries defined here can be found in
 //! `librustc_traits`.
 
-use crate::infer::canonical::Canonical;
-use crate::ty::error::TypeError;
-use crate::ty::{self, Ty};
-
 pub mod dropck_outlives;
 pub mod evaluate_obligation;
 pub mod method_autoderef;
 pub mod outlives_bounds;
 pub mod type_op;
 
-pub type CanonicalProjectionGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
-
-pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
-
-pub type CanonicalPredicateGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
-
-pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ascribe_user_type::AscribeUserType<'tcx>>>;
-
-pub type CanonicalTypeOpEqGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::eq::Eq<'tcx>>>;
-
-pub type CanonicalTypeOpSubtypeGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::subtype::Subtype<'tcx>>>;
-
-pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>;
-
-pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::normalize::Normalize<T>>>;
-
-#[derive(Clone, Debug, HashStable)]
-pub struct NoSolution;
-
-pub type Fallible<T> = Result<T, NoSolution>;
-
-impl<'tcx> From<TypeError<'tcx>> for NoSolution {
-    fn from(_: TypeError<'tcx>) -> NoSolution {
-        NoSolution
-    }
-}
+pub use rustc::traits::types::query::*;
index 20d7b5563774ef77baed2c3b9ba39a09244b6827..737b4fc6bb9dc4a2b994106337af6226db8b6ce2 100644 (file)
@@ -13,6 +13,8 @@
 
 use super::NoSolution;
 
+pub use rustc::traits::query::NormalizationResult;
+
 impl<'cx, 'tcx> At<'cx, 'tcx> {
     /// Normalize `value` in the context of the inference context,
     /// yielding a resulting type, or an error if `value` cannot be
@@ -59,13 +61,6 @@ pub fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
     }
 }
 
-/// Result from the `normalize_projection_ty` query.
-#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
-pub struct NormalizationResult<'tcx> {
-    /// Result of normalization.
-    pub normalized_ty: Ty<'tcx>,
-}
-
 struct QueryNormalizer<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
     cause: &'cx ObligationCause<'tcx>,
index 07e57e847b13d262b726e569b8e5ef71eba9d766..594faffa5f3aa3b9ea4f3b8bd34824af03f0a3f8 100644 (file)
@@ -6,43 +6,7 @@
 use rustc_hir as hir;
 use rustc_span::source_map::Span;
 
-use crate::ich::StableHashingContext;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use std::mem;
-
-/// Outlives bounds are relationships between generic parameters,
-/// whether they both be regions (`'a: 'b`) or whether types are
-/// involved (`T: 'a`). These relationships can be extracted from the
-/// full set of predicates we understand or also from types (in which
-/// case they are called implied bounds). They are fed to the
-/// `OutlivesEnv` which in turn is supplied to the region checker and
-/// other parts of the inference system.
-#[derive(Clone, Debug, TypeFoldable, Lift)]
-pub enum OutlivesBound<'tcx> {
-    RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
-    RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
-    RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
-}
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OutlivesBound<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        match *self {
-            OutlivesBound::RegionSubRegion(ref a, ref b) => {
-                a.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher);
-            }
-            OutlivesBound::RegionSubParam(ref a, ref b) => {
-                a.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher);
-            }
-            OutlivesBound::RegionSubProjection(ref a, ref b) => {
-                a.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
+pub use rustc::traits::query::OutlivesBound;
 
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// Implied bounds are region relationships that we deduce
index 46b656eb945481f7fa256c6fffac7b6b99886a0a..b14b79f090778fbb230369539b1e41848b92368c 100644 (file)
@@ -1,21 +1,8 @@
 use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
-use crate::ty::subst::UserSubsts;
-use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
-use rustc_hir::def_id::DefId;
+use rustc::ty::{ParamEnvAnd, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
-pub struct AscribeUserType<'tcx> {
-    pub mir_ty: Ty<'tcx>,
-    pub def_id: DefId,
-    pub user_substs: UserSubsts<'tcx>,
-}
-
-impl<'tcx> AscribeUserType<'tcx> {
-    pub fn new(mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>) -> Self {
-        Self { mir_ty, def_id, user_substs }
-    }
-}
+pub use rustc::traits::query::type_op::AscribeUserType;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
     type QueryResponse = ();
index 267722362c5c79eca79ca8038fb99b0bfed95af9..1de13430d4623707fe551e1e21b427baea789c81 100644 (file)
@@ -1,18 +1,8 @@
 use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
-use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
+use crate::ty::{ParamEnvAnd, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
-pub struct Eq<'tcx> {
-    pub a: Ty<'tcx>,
-    pub b: Ty<'tcx>,
-}
-
-impl<'tcx> Eq<'tcx> {
-    pub fn new(a: Ty<'tcx>, b: Ty<'tcx>) -> Self {
-        Self { a, b }
-    }
-}
+pub use rustc::traits::query::type_op::Eq;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> {
     type QueryResponse = ();
index adf63e4d60c99ccfd2a3e50618187ce3c18297e9..2d03d77cf6645fd4517eaff69f11394ca54fbc2a 100644 (file)
@@ -19,6 +19,8 @@
 use self::prove_predicate::ProvePredicate;
 pub mod subtype;
 
+pub use crate::traits::types::query::type_op::*;
+
 /// "Type ops" are used in NLL to perform some particular action and
 /// extract out the resulting region constraints (or an error if it
 /// cannot be completed).
index 8a028eecd5b622a7e90024f43cff8916e00ac085..b1e0e29620df6b132ec7cb20a00422868d495ffb 100644 (file)
@@ -4,19 +4,7 @@
 use crate::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt};
 use std::fmt;
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
-pub struct Normalize<T> {
-    pub value: T,
-}
-
-impl<'tcx, T> Normalize<T>
-where
-    T: fmt::Debug + TypeFoldable<'tcx>,
-{
-    pub fn new(value: T) -> Self {
-        Self { value }
-    }
-}
+pub use rustc::traits::query::type_op::Normalize;
 
 impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<T>
 where
index 15870ec95d8d28b168a13d78a0b15ac2d3026ba0..92cfb82e27e953a97afce53868dec46d5daf247a 100644 (file)
@@ -2,16 +2,7 @@
 use crate::traits::query::Fallible;
 use crate::ty::{ParamEnvAnd, Predicate, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
-pub struct ProvePredicate<'tcx> {
-    pub predicate: Predicate<'tcx>,
-}
-
-impl<'tcx> ProvePredicate<'tcx> {
-    pub fn new(predicate: Predicate<'tcx>) -> Self {
-        ProvePredicate { predicate }
-    }
-}
+pub use rustc::traits::query::type_op::ProvePredicate;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
     type QueryResponse = ();
index c70508a20a182341d34aba5dd7e12b5a0cc2b385..2877a74aaff01bc689713d0979a7d013805fa627 100644 (file)
@@ -1,18 +1,8 @@
 use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
-use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
+use crate::ty::{ParamEnvAnd, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
-pub struct Subtype<'tcx> {
-    pub sub: Ty<'tcx>,
-    pub sup: Ty<'tcx>,
-}
-
-impl<'tcx> Subtype<'tcx> {
-    pub fn new(sub: Ty<'tcx>, sup: Ty<'tcx>) -> Self {
-        Self { sub, sup }
-    }
-}
+pub use rustc::traits::query::type_op::Subtype;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> {
     type QueryResponse = ();
index 05fd02d6aa6cfa6d132f3c1677162c2c6ee14e9d..c795248802672f4e1ffe7642bb79292caad08d1c 100644 (file)
@@ -2,6 +2,7 @@
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
 
+pub mod query;
 pub mod select;
 
 use crate::mir::interpret::ErrorHandled;
diff --git a/src/librustc/traits/types/query.rs b/src/librustc/traits/types/query.rs
new file mode 100644 (file)
index 0000000..c905518
--- /dev/null
@@ -0,0 +1,332 @@
+//! Experimental types for the trait query interface. The methods
+//! defined in this module are all based on **canonicalization**,
+//! which makes a canonical query by replacing unbound inference
+//! variables and regions, so that results can be reused more broadly.
+//! The providers for the queries defined here can be found in
+//! `librustc_traits`.
+
+use crate::ich::StableHashingContext;
+use crate::infer::canonical::{Canonical, QueryResponse};
+use crate::ty::error::TypeError;
+use crate::ty::subst::GenericArg;
+use crate::ty::{self, Ty, TyCtxt};
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::struct_span_err;
+use rustc_span::source_map::Span;
+use std::iter::FromIterator;
+use std::mem;
+
+pub mod type_op {
+    use crate::ty::fold::TypeFoldable;
+    use crate::ty::subst::UserSubsts;
+    use crate::ty::{Predicate, Ty};
+    use rustc_hir::def_id::DefId;
+    use std::fmt;
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
+    pub struct AscribeUserType<'tcx> {
+        pub mir_ty: Ty<'tcx>,
+        pub def_id: DefId,
+        pub user_substs: UserSubsts<'tcx>,
+    }
+
+    impl<'tcx> AscribeUserType<'tcx> {
+        pub fn new(mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>) -> Self {
+            Self { mir_ty, def_id, user_substs }
+        }
+    }
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
+    pub struct Eq<'tcx> {
+        pub a: Ty<'tcx>,
+        pub b: Ty<'tcx>,
+    }
+
+    impl<'tcx> Eq<'tcx> {
+        pub fn new(a: Ty<'tcx>, b: Ty<'tcx>) -> Self {
+            Self { a, b }
+        }
+    }
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
+    pub struct Subtype<'tcx> {
+        pub sub: Ty<'tcx>,
+        pub sup: Ty<'tcx>,
+    }
+
+    impl<'tcx> Subtype<'tcx> {
+        pub fn new(sub: Ty<'tcx>, sup: Ty<'tcx>) -> Self {
+            Self { sub, sup }
+        }
+    }
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
+    pub struct ProvePredicate<'tcx> {
+        pub predicate: Predicate<'tcx>,
+    }
+
+    impl<'tcx> ProvePredicate<'tcx> {
+        pub fn new(predicate: Predicate<'tcx>) -> Self {
+            ProvePredicate { predicate }
+        }
+    }
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
+    pub struct Normalize<T> {
+        pub value: T,
+    }
+
+    impl<'tcx, T> Normalize<T>
+    where
+        T: fmt::Debug + TypeFoldable<'tcx>,
+    {
+        pub fn new(value: T) -> Self {
+            Self { value }
+        }
+    }
+}
+
+pub type CanonicalProjectionGoal<'tcx> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
+
+pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
+
+pub type CanonicalPredicateGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
+
+pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>;
+
+pub type CanonicalTypeOpEqGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Eq<'tcx>>>;
+
+pub type CanonicalTypeOpSubtypeGoal<'tcx> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Subtype<'tcx>>>;
+
+pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>;
+
+pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
+
+#[derive(Clone, Debug, HashStable)]
+pub struct NoSolution;
+
+pub type Fallible<T> = Result<T, NoSolution>;
+
+impl<'tcx> From<TypeError<'tcx>> for NoSolution {
+    fn from(_: TypeError<'tcx>) -> NoSolution {
+        NoSolution
+    }
+}
+
+#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
+pub struct DropckOutlivesResult<'tcx> {
+    pub kinds: Vec<GenericArg<'tcx>>,
+    pub overflows: Vec<Ty<'tcx>>,
+}
+
+impl<'tcx> DropckOutlivesResult<'tcx> {
+    pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
+        if let Some(overflow_ty) = self.overflows.iter().next() {
+            let mut err = struct_span_err!(
+                tcx.sess,
+                span,
+                E0320,
+                "overflow while adding drop-check rules for {}",
+                ty,
+            );
+            err.note(&format!("overflowed on {}", overflow_ty));
+            err.emit();
+        }
+    }
+
+    pub fn into_kinds_reporting_overflows(
+        self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+        ty: Ty<'tcx>,
+    ) -> Vec<GenericArg<'tcx>> {
+        self.report_overflows(tcx, span, ty);
+        let DropckOutlivesResult { kinds, overflows: _ } = self;
+        kinds
+    }
+}
+
+/// A set of constraints that need to be satisfied in order for
+/// a type to be valid for destruction.
+#[derive(Clone, Debug, HashStable)]
+pub struct DtorckConstraint<'tcx> {
+    /// Types that are required to be alive in order for this
+    /// type to be valid for destruction.
+    pub outlives: Vec<ty::subst::GenericArg<'tcx>>,
+
+    /// Types that could not be resolved: projections and params.
+    pub dtorck_types: Vec<Ty<'tcx>>,
+
+    /// If, during the computation of the dtorck constraint, we
+    /// overflow, that gets recorded here. The caller is expected to
+    /// report an error.
+    pub overflows: Vec<Ty<'tcx>>,
+}
+
+impl<'tcx> DtorckConstraint<'tcx> {
+    pub fn empty() -> DtorckConstraint<'tcx> {
+        DtorckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] }
+    }
+}
+
+impl<'tcx> FromIterator<DtorckConstraint<'tcx>> for DtorckConstraint<'tcx> {
+    fn from_iter<I: IntoIterator<Item = DtorckConstraint<'tcx>>>(iter: I) -> Self {
+        let mut result = Self::empty();
+
+        for DtorckConstraint { outlives, dtorck_types, overflows } in iter {
+            result.outlives.extend(outlives);
+            result.dtorck_types.extend(dtorck_types);
+            result.overflows.extend(overflows);
+        }
+
+        result
+    }
+}
+
+/// This returns true if the type `ty` is "trivial" for
+/// dropck-outlives -- that is, if it doesn't require any types to
+/// outlive. This is similar but not *quite* the same as the
+/// `needs_drop` test in the compiler already -- that is, for every
+/// type T for which this function return true, needs-drop would
+/// return `false`. But the reverse does not hold: in particular,
+/// `needs_drop` returns false for `PhantomData`, but it is not
+/// trivial for dropck-outlives.
+///
+/// Note also that `needs_drop` requires a "global" type (i.e., one
+/// with erased regions), but this function does not.
+pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
+    match ty.kind {
+        // None of these types have a destructor and hence they do not
+        // require anything in particular to outlive the dtor's
+        // execution.
+        ty::Infer(ty::FreshIntTy(_))
+        | ty::Infer(ty::FreshFloatTy(_))
+        | ty::Bool
+        | ty::Int(_)
+        | ty::Uint(_)
+        | ty::Float(_)
+        | ty::Never
+        | ty::FnDef(..)
+        | ty::FnPtr(_)
+        | ty::Char
+        | ty::GeneratorWitness(..)
+        | ty::RawPtr(_)
+        | ty::Ref(..)
+        | ty::Str
+        | ty::Foreign(..)
+        | ty::Error => true,
+
+        // [T; N] and [T] have same properties as T.
+        ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty),
+
+        // (T1..Tn) and closures have same properties as T1..Tn --
+        // check if *any* of those are trivial.
+        ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
+        ty::Closure(def_id, ref substs) => {
+            substs.as_closure().upvar_tys(def_id, tcx).all(|t| trivial_dropck_outlives(tcx, t))
+        }
+
+        ty::Adt(def, _) => {
+            if Some(def.did) == tcx.lang_items().manually_drop() {
+                // `ManuallyDrop` never has a dtor.
+                true
+            } else {
+                // Other types might. Moreover, PhantomData doesn't
+                // have a dtor, but it is considered to own its
+                // content, so it is non-trivial. Unions can have `impl Drop`,
+                // and hence are non-trivial as well.
+                false
+            }
+        }
+
+        // The following *might* require a destructor: needs deeper inspection.
+        ty::Dynamic(..)
+        | ty::Projection(..)
+        | ty::Param(_)
+        | ty::Opaque(..)
+        | ty::Placeholder(..)
+        | ty::Infer(_)
+        | ty::Bound(..)
+        | ty::Generator(..) => false,
+
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+    }
+}
+
+#[derive(Debug, HashStable)]
+pub struct CandidateStep<'tcx> {
+    pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
+    pub autoderefs: usize,
+    /// `true` if the type results from a dereference of a raw pointer.
+    /// when assembling candidates, we include these steps, but not when
+    /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
+    /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
+    /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
+    pub from_unsafe_deref: bool,
+    pub unsize: bool,
+}
+
+#[derive(Clone, Debug, HashStable)]
+pub struct MethodAutoderefStepsResult<'tcx> {
+    /// The valid autoderef steps that could be find.
+    pub steps: Lrc<Vec<CandidateStep<'tcx>>>,
+    /// If Some(T), a type autoderef reported an error on.
+    pub opt_bad_ty: Option<Lrc<MethodAutoderefBadTy<'tcx>>>,
+    /// If `true`, `steps` has been truncated due to reaching the
+    /// recursion limit.
+    pub reached_recursion_limit: bool,
+}
+
+#[derive(Debug, HashStable)]
+pub struct MethodAutoderefBadTy<'tcx> {
+    pub reached_raw_pointer: bool,
+    pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
+}
+
+/// Result from the `normalize_projection_ty` query.
+#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
+pub struct NormalizationResult<'tcx> {
+    /// Result of normalization.
+    pub normalized_ty: Ty<'tcx>,
+}
+
+/// Outlives bounds are relationships between generic parameters,
+/// whether they both be regions (`'a: 'b`) or whether types are
+/// involved (`T: 'a`). These relationships can be extracted from the
+/// full set of predicates we understand or also from types (in which
+/// case they are called implied bounds). They are fed to the
+/// `OutlivesEnv` which in turn is supplied to the region checker and
+/// other parts of the inference system.
+#[derive(Clone, Debug, TypeFoldable, Lift)]
+pub enum OutlivesBound<'tcx> {
+    RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
+    RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
+    RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OutlivesBound<'tcx> {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            OutlivesBound::RegionSubRegion(ref a, ref b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher);
+            }
+            OutlivesBound::RegionSubParam(ref a, ref b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher);
+            }
+            OutlivesBound::RegionSubProjection(ref a, ref b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}