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