From 4e42f388c375b0d6eb25af087cb2a66069419529 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 22 Jan 2020 09:04:50 +0100 Subject: [PATCH] Move traits::query datatypes to traits::types. --- src/librustc/traits/query/dropck_outlives.rs | 79 +---- src/librustc/traits/query/method_autoderef.rs | 34 +- src/librustc/traits/query/mod.rs | 37 +- src/librustc/traits/query/normalize.rs | 9 +- src/librustc/traits/query/outlives_bounds.rs | 38 +- .../traits/query/type_op/ascribe_user_type.rs | 17 +- src/librustc/traits/query/type_op/eq.rs | 14 +- src/librustc/traits/query/type_op/mod.rs | 2 + .../traits/query/type_op/normalize.rs | 14 +- .../traits/query/type_op/prove_predicate.rs | 11 +- src/librustc/traits/query/type_op/subtype.rs | 14 +- src/librustc/traits/types/mod.rs | 1 + src/librustc/traits/types/query.rs | 332 ++++++++++++++++++ 13 files changed, 353 insertions(+), 249 deletions(-) create mode 100644 src/librustc/traits/types/query.rs diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index 2e5ef5adcd3..a1d7a2836e4 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -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 { - pub kinds: Vec>, - pub overflows: Vec>, -} - -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> { - 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>, - - /// Types that could not be resolved: projections and params. - pub dtorck_types: Vec>, - - /// 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>, -} - -impl<'tcx> DtorckConstraint<'tcx> { - pub fn empty() -> DtorckConstraint<'tcx> { - DtorckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] } - } -} - -impl<'tcx> FromIterator> for DtorckConstraint<'tcx> { - fn from_iter>>(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 diff --git a/src/librustc/traits/query/method_autoderef.rs b/src/librustc/traits/query/method_autoderef.rs index 4ef775750ec..80748c5ef38 100644 --- a/src/librustc/traits/query/method_autoderef.rs +++ b/src/librustc/traits/query/method_autoderef.rs @@ -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>>, - /// If Some(T), a type autoderef reported an error on. - pub opt_bad_ty: Option>>, - /// 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}; diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs index 440268aab8f..20a873dc4c6 100644 --- a/src/librustc/traits/query/mod.rs +++ b/src/librustc/traits/query/mod.rs @@ -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; @@ -16,35 +12,4 @@ 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>>; - -#[derive(Clone, Debug, HashStable)] -pub struct NoSolution; - -pub type Fallible = Result; - -impl<'tcx> From> for NoSolution { - fn from(_: TypeError<'tcx>) -> NoSolution { - NoSolution - } -} +pub use rustc::traits::types::query::*; diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 20d7b556377..737b4fc6bb9 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -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(&self, value: &T) -> Result, 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>, diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs index 07e57e847b1..594faffa5f3 100644 --- a/src/librustc/traits/query/outlives_bounds.rs +++ b/src/librustc/traits/query/outlives_bounds.rs @@ -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> 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 diff --git a/src/librustc/traits/query/type_op/ascribe_user_type.rs b/src/librustc/traits/query/type_op/ascribe_user_type.rs index 46b656eb945..b14b79f0907 100644 --- a/src/librustc/traits/query/type_op/ascribe_user_type.rs +++ b/src/librustc/traits/query/type_op/ascribe_user_type.rs @@ -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 = (); diff --git a/src/librustc/traits/query/type_op/eq.rs b/src/librustc/traits/query/type_op/eq.rs index 267722362c5..1de13430d46 100644 --- a/src/librustc/traits/query/type_op/eq.rs +++ b/src/librustc/traits/query/type_op/eq.rs @@ -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 = (); diff --git a/src/librustc/traits/query/type_op/mod.rs b/src/librustc/traits/query/type_op/mod.rs index adf63e4d60c..2d03d77cf66 100644 --- a/src/librustc/traits/query/type_op/mod.rs +++ b/src/librustc/traits/query/type_op/mod.rs @@ -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). diff --git a/src/librustc/traits/query/type_op/normalize.rs b/src/librustc/traits/query/type_op/normalize.rs index 8a028eecd5b..b1e0e29620d 100644 --- a/src/librustc/traits/query/type_op/normalize.rs +++ b/src/librustc/traits/query/type_op/normalize.rs @@ -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 { - pub value: T, -} - -impl<'tcx, T> Normalize -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 where diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs index 15870ec95d8..92cfb82e27e 100644 --- a/src/librustc/traits/query/type_op/prove_predicate.rs +++ b/src/librustc/traits/query/type_op/prove_predicate.rs @@ -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 = (); diff --git a/src/librustc/traits/query/type_op/subtype.rs b/src/librustc/traits/query/type_op/subtype.rs index c70508a20a1..2877a74aaff 100644 --- a/src/librustc/traits/query/type_op/subtype.rs +++ b/src/librustc/traits/query/type_op/subtype.rs @@ -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 = (); diff --git a/src/librustc/traits/types/mod.rs b/src/librustc/traits/types/mod.rs index 05fd02d6aa6..c7952488026 100644 --- a/src/librustc/traits/types/mod.rs +++ b/src/librustc/traits/types/mod.rs @@ -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 index 00000000000..c9055182620 --- /dev/null +++ b/src/librustc/traits/types/query.rs @@ -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 { + pub value: T, + } + + impl<'tcx, T> Normalize + 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>>; + +#[derive(Clone, Debug, HashStable)] +pub struct NoSolution; + +pub type Fallible = Result; + +impl<'tcx> From> for NoSolution { + fn from(_: TypeError<'tcx>) -> NoSolution { + NoSolution + } +} + +#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)] +pub struct DropckOutlivesResult<'tcx> { + pub kinds: Vec>, + pub overflows: Vec>, +} + +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> { + 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>, + + /// Types that could not be resolved: projections and params. + pub dtorck_types: Vec>, + + /// 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>, +} + +impl<'tcx> DtorckConstraint<'tcx> { + pub fn empty() -> DtorckConstraint<'tcx> { + DtorckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] } + } +} + +impl<'tcx> FromIterator> for DtorckConstraint<'tcx> { + fn from_iter>>(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>>, + /// If Some(T), a type autoderef reported an error on. + pub opt_bad_ty: Option>>, + /// 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> 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); + } + } + } +}