]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/traits/query.rs
Merge commit '0eff589afc83e21a03a168497bbab6b4dfbb4ef6' into clippyup
[rust.git] / compiler / rustc_middle / src / 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
8 use crate::infer::canonical::{Canonical, QueryResponse};
9 use crate::ty::error::TypeError;
10 use crate::ty::subst::GenericArg;
11 use crate::ty::{self, Ty, TyCtxt};
12
13 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
14 use rustc_data_structures::sync::Lrc;
15 use rustc_errors::struct_span_err;
16 use rustc_query_system::ich::StableHashingContext;
17 use rustc_span::source_map::Span;
18 use std::iter::FromIterator;
19 use std::mem;
20
21 pub mod type_op {
22     use crate::ty::fold::TypeFoldable;
23     use crate::ty::subst::UserSubsts;
24     use crate::ty::{Predicate, Ty};
25     use rustc_hir::def_id::DefId;
26     use std::fmt;
27
28     #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
29     pub struct AscribeUserType<'tcx> {
30         pub mir_ty: Ty<'tcx>,
31         pub def_id: DefId,
32         pub user_substs: UserSubsts<'tcx>,
33     }
34
35     impl<'tcx> AscribeUserType<'tcx> {
36         pub fn new(mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>) -> Self {
37             Self { mir_ty, def_id, user_substs }
38         }
39     }
40
41     #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
42     pub struct Eq<'tcx> {
43         pub a: Ty<'tcx>,
44         pub b: Ty<'tcx>,
45     }
46
47     #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
48     pub struct Subtype<'tcx> {
49         pub sub: Ty<'tcx>,
50         pub sup: Ty<'tcx>,
51     }
52
53     #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
54     pub struct ProvePredicate<'tcx> {
55         pub predicate: Predicate<'tcx>,
56     }
57
58     impl<'tcx> ProvePredicate<'tcx> {
59         pub fn new(predicate: Predicate<'tcx>) -> Self {
60             ProvePredicate { predicate }
61         }
62     }
63
64     #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
65     pub struct Normalize<T> {
66         pub value: T,
67     }
68
69     impl<'tcx, T> Normalize<T>
70     where
71         T: fmt::Debug + TypeFoldable<'tcx>,
72     {
73         pub fn new(value: T) -> Self {
74             Self { value }
75         }
76     }
77 }
78
79 pub type CanonicalProjectionGoal<'tcx> =
80     Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
81
82 pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
83
84 pub type CanonicalPredicateGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
85
86 pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
87     Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>;
88
89 pub type CanonicalTypeOpEqGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Eq<'tcx>>>;
90
91 pub type CanonicalTypeOpSubtypeGoal<'tcx> =
92     Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Subtype<'tcx>>>;
93
94 pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
95     Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>;
96
97 pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
98     Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
99
100 #[derive(Clone, Debug, HashStable)]
101 pub struct NoSolution;
102
103 pub type Fallible<T> = Result<T, NoSolution>;
104
105 impl<'tcx> From<TypeError<'tcx>> for NoSolution {
106     fn from(_: TypeError<'tcx>) -> NoSolution {
107         NoSolution
108     }
109 }
110
111 #[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
112 pub struct DropckOutlivesResult<'tcx> {
113     pub kinds: Vec<GenericArg<'tcx>>,
114     pub overflows: Vec<Ty<'tcx>>,
115 }
116
117 impl<'tcx> DropckOutlivesResult<'tcx> {
118     pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
119         if let Some(overflow_ty) = self.overflows.get(0) {
120             let mut err = struct_span_err!(
121                 tcx.sess,
122                 span,
123                 E0320,
124                 "overflow while adding drop-check rules for {}",
125                 ty,
126             );
127             err.note(&format!("overflowed on {}", overflow_ty));
128             err.emit();
129         }
130     }
131
132     pub fn into_kinds_reporting_overflows(
133         self,
134         tcx: TyCtxt<'tcx>,
135         span: Span,
136         ty: Ty<'tcx>,
137     ) -> Vec<GenericArg<'tcx>> {
138         self.report_overflows(tcx, span, ty);
139         let DropckOutlivesResult { kinds, overflows: _ } = self;
140         kinds
141     }
142 }
143
144 /// A set of constraints that need to be satisfied in order for
145 /// a type to be valid for destruction.
146 #[derive(Clone, Debug, HashStable)]
147 pub struct DtorckConstraint<'tcx> {
148     /// Types that are required to be alive in order for this
149     /// type to be valid for destruction.
150     pub outlives: Vec<ty::subst::GenericArg<'tcx>>,
151
152     /// Types that could not be resolved: projections and params.
153     pub dtorck_types: Vec<Ty<'tcx>>,
154
155     /// If, during the computation of the dtorck constraint, we
156     /// overflow, that gets recorded here. The caller is expected to
157     /// report an error.
158     pub overflows: Vec<Ty<'tcx>>,
159 }
160
161 impl<'tcx> DtorckConstraint<'tcx> {
162     pub fn empty() -> DtorckConstraint<'tcx> {
163         DtorckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] }
164     }
165 }
166
167 impl<'tcx> FromIterator<DtorckConstraint<'tcx>> for DtorckConstraint<'tcx> {
168     fn from_iter<I: IntoIterator<Item = DtorckConstraint<'tcx>>>(iter: I) -> Self {
169         let mut result = Self::empty();
170
171         for DtorckConstraint { outlives, dtorck_types, overflows } in iter {
172             result.outlives.extend(outlives);
173             result.dtorck_types.extend(dtorck_types);
174             result.overflows.extend(overflows);
175         }
176
177         result
178     }
179 }
180
181 #[derive(Debug, HashStable)]
182 pub struct CandidateStep<'tcx> {
183     pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
184     pub autoderefs: usize,
185     /// `true` if the type results from a dereference of a raw pointer.
186     /// when assembling candidates, we include these steps, but not when
187     /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
188     /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
189     /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
190     pub from_unsafe_deref: bool,
191     pub unsize: bool,
192 }
193
194 #[derive(Clone, Debug, HashStable)]
195 pub struct MethodAutoderefStepsResult<'tcx> {
196     /// The valid autoderef steps that could be find.
197     pub steps: Lrc<Vec<CandidateStep<'tcx>>>,
198     /// If Some(T), a type autoderef reported an error on.
199     pub opt_bad_ty: Option<Lrc<MethodAutoderefBadTy<'tcx>>>,
200     /// If `true`, `steps` has been truncated due to reaching the
201     /// recursion limit.
202     pub reached_recursion_limit: bool,
203 }
204
205 #[derive(Debug, HashStable)]
206 pub struct MethodAutoderefBadTy<'tcx> {
207     pub reached_raw_pointer: bool,
208     pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
209 }
210
211 /// Result from the `normalize_projection_ty` query.
212 #[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
213 pub struct NormalizationResult<'tcx> {
214     /// Result of normalization.
215     pub normalized_ty: Ty<'tcx>,
216 }
217
218 /// Outlives bounds are relationships between generic parameters,
219 /// whether they both be regions (`'a: 'b`) or whether types are
220 /// involved (`T: 'a`). These relationships can be extracted from the
221 /// full set of predicates we understand or also from types (in which
222 /// case they are called implied bounds). They are fed to the
223 /// `OutlivesEnv` which in turn is supplied to the region checker and
224 /// other parts of the inference system.
225 #[derive(Clone, Debug, TypeFoldable, Lift)]
226 pub enum OutlivesBound<'tcx> {
227     RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
228     RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
229     RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
230 }
231
232 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OutlivesBound<'tcx> {
233     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
234         mem::discriminant(self).hash_stable(hcx, hasher);
235         match *self {
236             OutlivesBound::RegionSubRegion(ref a, ref b) => {
237                 a.hash_stable(hcx, hasher);
238                 b.hash_stable(hcx, hasher);
239             }
240             OutlivesBound::RegionSubParam(ref a, ref b) => {
241                 a.hash_stable(hcx, hasher);
242                 b.hash_stable(hcx, hasher);
243             }
244             OutlivesBound::RegionSubProjection(ref a, ref b) => {
245                 a.hash_stable(hcx, hasher);
246                 b.hash_stable(hcx, hasher);
247             }
248         }
249     }
250 }