rustc_middle/traits/
query.rs

1//! Experimental types for the trait query interface. The methods
2//! defined in this module are all based on **canonicalization**,
3//! which makes a canonical query by replacing unbound inference
4//! variables and regions, so that results can be reused more broadly.
5//! The providers for the queries defined here can be found in
6//! `rustc_traits`.
7
8use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
9use rustc_span::Span;
10
11use crate::error::DropCheckOverflow;
12use crate::infer::canonical::{Canonical, CanonicalQueryInput, QueryResponse};
13pub use crate::traits::solve::NoSolution;
14use crate::ty::{self, GenericArg, Ty, TyCtxt};
15
16pub mod type_op {
17    use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
18
19    use crate::ty::{Predicate, Ty, UserType};
20
21    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
22    pub struct AscribeUserType<'tcx> {
23        pub mir_ty: Ty<'tcx>,
24        pub user_ty: UserType<'tcx>,
25    }
26
27    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
28    pub struct Eq<'tcx> {
29        pub a: Ty<'tcx>,
30        pub b: Ty<'tcx>,
31    }
32
33    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
34    pub struct Subtype<'tcx> {
35        pub sub: Ty<'tcx>,
36        pub sup: Ty<'tcx>,
37    }
38
39    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
40    pub struct ProvePredicate<'tcx> {
41        pub predicate: Predicate<'tcx>,
42    }
43
44    /// Normalizes, but not in the new solver.
45    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
46    pub struct Normalize<T> {
47        pub value: T,
48    }
49
50    /// Normalizes, and deeply normalizes in the new solver.
51    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
52    pub struct DeeplyNormalize<T> {
53        pub value: T,
54    }
55
56    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
57    pub struct ImpliedOutlivesBounds<'tcx> {
58        pub ty: Ty<'tcx>,
59    }
60
61    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
62    pub struct DropckOutlives<'tcx> {
63        pub dropped_ty: Ty<'tcx>,
64    }
65}
66
67pub type CanonicalAliasGoal<'tcx> =
68    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
69
70pub type CanonicalTyGoal<'tcx> = CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
71
72pub type CanonicalPredicateGoal<'tcx> =
73    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
74
75pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
76    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>;
77
78pub type CanonicalTypeOpEqGoal<'tcx> =
79    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Eq<'tcx>>>;
80
81pub type CanonicalTypeOpSubtypeGoal<'tcx> =
82    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Subtype<'tcx>>>;
83
84pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
85    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>;
86
87pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
88    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
89
90pub type CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T> =
91    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::DeeplyNormalize<T>>>;
92
93pub type CanonicalImpliedOutlivesBoundsGoal<'tcx> =
94    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ImpliedOutlivesBounds<'tcx>>>;
95
96pub type CanonicalDropckOutlivesGoal<'tcx> =
97    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::DropckOutlives<'tcx>>>;
98
99#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable)]
100pub struct DropckOutlivesResult<'tcx> {
101    pub kinds: Vec<GenericArg<'tcx>>,
102    pub overflows: Vec<Ty<'tcx>>,
103}
104
105impl<'tcx> DropckOutlivesResult<'tcx> {
106    pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
107        if let Some(overflow_ty) = self.overflows.get(0) {
108            tcx.dcx().emit_err(DropCheckOverflow { span, ty, overflow_ty: *overflow_ty });
109        }
110    }
111}
112
113/// A set of constraints that need to be satisfied in order for
114/// a type to be valid for destruction.
115#[derive(Clone, Debug, HashStable)]
116pub struct DropckConstraint<'tcx> {
117    /// Types that are required to be alive in order for this
118    /// type to be valid for destruction.
119    pub outlives: Vec<ty::GenericArg<'tcx>>,
120
121    /// Types that could not be resolved: projections and params.
122    pub dtorck_types: Vec<Ty<'tcx>>,
123
124    /// If, during the computation of the dtorck constraint, we
125    /// overflow, that gets recorded here. The caller is expected to
126    /// report an error.
127    pub overflows: Vec<Ty<'tcx>>,
128}
129
130impl<'tcx> DropckConstraint<'tcx> {
131    pub fn empty() -> DropckConstraint<'tcx> {
132        DropckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] }
133    }
134}
135
136impl<'tcx> FromIterator<DropckConstraint<'tcx>> for DropckConstraint<'tcx> {
137    fn from_iter<I: IntoIterator<Item = DropckConstraint<'tcx>>>(iter: I) -> Self {
138        let mut result = Self::empty();
139
140        for DropckConstraint { outlives, dtorck_types, overflows } in iter {
141            result.outlives.extend(outlives);
142            result.dtorck_types.extend(dtorck_types);
143            result.overflows.extend(overflows);
144        }
145
146        result
147    }
148}
149
150#[derive(Debug, HashStable)]
151pub struct CandidateStep<'tcx> {
152    pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
153    pub autoderefs: usize,
154    /// `true` if the type results from a dereference of a raw pointer.
155    /// when assembling candidates, we include these steps, but not when
156    /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
157    /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
158    /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
159    pub from_unsafe_deref: bool,
160    pub unsize: bool,
161    /// We will generate CandidateSteps which are reachable via a chain
162    /// of following `Receiver`. The first 'n' of those will be reachable
163    /// by following a chain of 'Deref' instead (since there's a blanket
164    /// implementation of Receiver for Deref).
165    /// We use the entire set of steps when identifying method candidates
166    /// (e.g. identifying relevant `impl` blocks) but only those that are
167    /// reachable via Deref when examining what the receiver type can
168    /// be converted into by autodereffing.
169    pub reachable_via_deref: bool,
170}
171
172#[derive(Copy, Clone, Debug, HashStable)]
173pub struct MethodAutoderefStepsResult<'tcx> {
174    /// The valid autoderef steps that could be found by following a chain
175    /// of `Receiver<Target=T>` or `Deref<Target=T>` trait implementations.
176    pub steps: &'tcx [CandidateStep<'tcx>],
177    /// If Some(T), a type autoderef reported an error on.
178    pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,
179    /// If `true`, `steps` has been truncated due to reaching the
180    /// recursion limit.
181    pub reached_recursion_limit: bool,
182}
183
184#[derive(Debug, HashStable)]
185pub struct MethodAutoderefBadTy<'tcx> {
186    pub reached_raw_pointer: bool,
187    pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
188}
189
190/// Result of the `normalize_canonicalized_{{,inherent_}projection,weak}_ty` queries.
191#[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
192pub struct NormalizationResult<'tcx> {
193    /// Result of the normalization.
194    pub normalized_ty: Ty<'tcx>,
195}
196
197/// Outlives bounds are relationships between generic parameters,
198/// whether they both be regions (`'a: 'b`) or whether types are
199/// involved (`T: 'a`). These relationships can be extracted from the
200/// full set of predicates we understand or also from types (in which
201/// case they are called implied bounds). They are fed to the
202/// `OutlivesEnv` which in turn is supplied to the region checker and
203/// other parts of the inference system.
204#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable)]
205pub enum OutlivesBound<'tcx> {
206    RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
207    RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
208    RegionSubAlias(ty::Region<'tcx>, ty::AliasTy<'tcx>),
209}