Move traits::query datatypes to traits::types.
This commit is contained in:
parent
a77da35ed4
commit
4e42f388c3
@ -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
|
||||
|
@ -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};
|
||||
|
@ -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<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::*;
|
||||
|
@ -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>,
|
||||
|
@ -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
|
||||
|
@ -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 = ();
|
||||
|
@ -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 = ();
|
||||
|
@ -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).
|
||||
|
@ -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
|
||||
|
@ -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 = ();
|
||||
|
@ -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 = ();
|
||||
|
@ -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;
|
||||
|
332
src/librustc/traits/types/query.rs
Normal file
332
src/librustc/traits/types/query.rs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user