]> git.proxmox.com Git - rustc.git/blame - src/librustc_middle/traits/query.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_middle / traits / query.rs
CommitLineData
74b04a01
XL
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//! `librustc_traits`.
7
8use crate::ich::StableHashingContext;
9use crate::infer::canonical::{Canonical, QueryResponse};
10use crate::ty::error::TypeError;
11use crate::ty::subst::GenericArg;
12use crate::ty::{self, Ty, TyCtxt};
13
14use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
15use rustc_data_structures::sync::Lrc;
16use rustc_errors::struct_span_err;
17use rustc_span::source_map::Span;
18use std::iter::FromIterator;
19use std::mem;
20
21pub 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 impl<'tcx> Eq<'tcx> {
48 pub fn new(a: Ty<'tcx>, b: Ty<'tcx>) -> Self {
49 Self { a, b }
50 }
51 }
52
53 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
54 pub struct Subtype<'tcx> {
55 pub sub: Ty<'tcx>,
56 pub sup: Ty<'tcx>,
57 }
58
59 impl<'tcx> Subtype<'tcx> {
60 pub fn new(sub: Ty<'tcx>, sup: Ty<'tcx>) -> Self {
61 Self { sub, sup }
62 }
63 }
64
65 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
66 pub struct ProvePredicate<'tcx> {
67 pub predicate: Predicate<'tcx>,
68 }
69
70 impl<'tcx> ProvePredicate<'tcx> {
71 pub fn new(predicate: Predicate<'tcx>) -> Self {
72 ProvePredicate { predicate }
73 }
74 }
75
76 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
77 pub struct Normalize<T> {
78 pub value: T,
79 }
80
81 impl<'tcx, T> Normalize<T>
82 where
83 T: fmt::Debug + TypeFoldable<'tcx>,
84 {
85 pub fn new(value: T) -> Self {
86 Self { value }
87 }
88 }
89}
90
91pub type CanonicalProjectionGoal<'tcx> =
92 Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
93
94pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
95
96pub type CanonicalPredicateGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
97
98pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
99 Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>;
100
101pub type CanonicalTypeOpEqGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Eq<'tcx>>>;
102
103pub type CanonicalTypeOpSubtypeGoal<'tcx> =
104 Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Subtype<'tcx>>>;
105
106pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
107 Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>;
108
109pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
110 Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
111
112#[derive(Clone, Debug, HashStable)]
113pub struct NoSolution;
114
115pub type Fallible<T> = Result<T, NoSolution>;
116
117impl<'tcx> From<TypeError<'tcx>> for NoSolution {
118 fn from(_: TypeError<'tcx>) -> NoSolution {
119 NoSolution
120 }
121}
122
123#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
124pub struct DropckOutlivesResult<'tcx> {
125 pub kinds: Vec<GenericArg<'tcx>>,
126 pub overflows: Vec<Ty<'tcx>>,
127}
128
129impl<'tcx> DropckOutlivesResult<'tcx> {
130 pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
3dfed10e 131 if let Some(overflow_ty) = self.overflows.get(0) {
74b04a01
XL
132 let mut err = struct_span_err!(
133 tcx.sess,
134 span,
135 E0320,
136 "overflow while adding drop-check rules for {}",
137 ty,
138 );
139 err.note(&format!("overflowed on {}", overflow_ty));
140 err.emit();
141 }
142 }
143
144 pub fn into_kinds_reporting_overflows(
145 self,
146 tcx: TyCtxt<'tcx>,
147 span: Span,
148 ty: Ty<'tcx>,
149 ) -> Vec<GenericArg<'tcx>> {
150 self.report_overflows(tcx, span, ty);
151 let DropckOutlivesResult { kinds, overflows: _ } = self;
152 kinds
153 }
154}
155
156/// A set of constraints that need to be satisfied in order for
157/// a type to be valid for destruction.
158#[derive(Clone, Debug, HashStable)]
159pub struct DtorckConstraint<'tcx> {
160 /// Types that are required to be alive in order for this
161 /// type to be valid for destruction.
162 pub outlives: Vec<ty::subst::GenericArg<'tcx>>,
163
164 /// Types that could not be resolved: projections and params.
165 pub dtorck_types: Vec<Ty<'tcx>>,
166
167 /// If, during the computation of the dtorck constraint, we
168 /// overflow, that gets recorded here. The caller is expected to
169 /// report an error.
170 pub overflows: Vec<Ty<'tcx>>,
171}
172
173impl<'tcx> DtorckConstraint<'tcx> {
174 pub fn empty() -> DtorckConstraint<'tcx> {
175 DtorckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] }
176 }
177}
178
179impl<'tcx> FromIterator<DtorckConstraint<'tcx>> for DtorckConstraint<'tcx> {
180 fn from_iter<I: IntoIterator<Item = DtorckConstraint<'tcx>>>(iter: I) -> Self {
181 let mut result = Self::empty();
182
183 for DtorckConstraint { outlives, dtorck_types, overflows } in iter {
184 result.outlives.extend(outlives);
185 result.dtorck_types.extend(dtorck_types);
186 result.overflows.extend(overflows);
187 }
188
189 result
190 }
191}
192
193/// This returns true if the type `ty` is "trivial" for
194/// dropck-outlives -- that is, if it doesn't require any types to
195/// outlive. This is similar but not *quite* the same as the
196/// `needs_drop` test in the compiler already -- that is, for every
197/// type T for which this function return true, needs-drop would
198/// return `false`. But the reverse does not hold: in particular,
199/// `needs_drop` returns false for `PhantomData`, but it is not
200/// trivial for dropck-outlives.
201///
202/// Note also that `needs_drop` requires a "global" type (i.e., one
203/// with erased regions), but this function does not.
204pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
205 match ty.kind {
206 // None of these types have a destructor and hence they do not
207 // require anything in particular to outlive the dtor's
208 // execution.
209 ty::Infer(ty::FreshIntTy(_))
210 | ty::Infer(ty::FreshFloatTy(_))
211 | ty::Bool
212 | ty::Int(_)
213 | ty::Uint(_)
214 | ty::Float(_)
215 | ty::Never
216 | ty::FnDef(..)
217 | ty::FnPtr(_)
218 | ty::Char
219 | ty::GeneratorWitness(..)
220 | ty::RawPtr(_)
221 | ty::Ref(..)
222 | ty::Str
223 | ty::Foreign(..)
f035d41b 224 | ty::Error(_) => true,
74b04a01
XL
225
226 // [T; N] and [T] have same properties as T.
227 ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty),
228
229 // (T1..Tn) and closures have same properties as T1..Tn --
230 // check if *any* of those are trivial.
231 ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
ba9703b0
XL
232 ty::Closure(_, ref substs) => {
233 substs.as_closure().upvar_tys().all(|t| trivial_dropck_outlives(tcx, t))
74b04a01
XL
234 }
235
236 ty::Adt(def, _) => {
237 if Some(def.did) == tcx.lang_items().manually_drop() {
238 // `ManuallyDrop` never has a dtor.
239 true
240 } else {
241 // Other types might. Moreover, PhantomData doesn't
242 // have a dtor, but it is considered to own its
243 // content, so it is non-trivial. Unions can have `impl Drop`,
244 // and hence are non-trivial as well.
245 false
246 }
247 }
248
249 // The following *might* require a destructor: needs deeper inspection.
250 ty::Dynamic(..)
251 | ty::Projection(..)
252 | ty::Param(_)
253 | ty::Opaque(..)
254 | ty::Placeholder(..)
255 | ty::Infer(_)
256 | ty::Bound(..)
257 | ty::Generator(..) => false,
74b04a01
XL
258 }
259}
260
261#[derive(Debug, HashStable)]
262pub struct CandidateStep<'tcx> {
263 pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
264 pub autoderefs: usize,
265 /// `true` if the type results from a dereference of a raw pointer.
266 /// when assembling candidates, we include these steps, but not when
267 /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
268 /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
269 /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
270 pub from_unsafe_deref: bool,
271 pub unsize: bool,
272}
273
274#[derive(Clone, Debug, HashStable)]
275pub struct MethodAutoderefStepsResult<'tcx> {
276 /// The valid autoderef steps that could be find.
277 pub steps: Lrc<Vec<CandidateStep<'tcx>>>,
278 /// If Some(T), a type autoderef reported an error on.
279 pub opt_bad_ty: Option<Lrc<MethodAutoderefBadTy<'tcx>>>,
280 /// If `true`, `steps` has been truncated due to reaching the
281 /// recursion limit.
282 pub reached_recursion_limit: bool,
283}
284
285#[derive(Debug, HashStable)]
286pub struct MethodAutoderefBadTy<'tcx> {
287 pub reached_raw_pointer: bool,
288 pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
289}
290
291/// Result from the `normalize_projection_ty` query.
292#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
293pub struct NormalizationResult<'tcx> {
294 /// Result of normalization.
295 pub normalized_ty: Ty<'tcx>,
296}
297
298/// Outlives bounds are relationships between generic parameters,
299/// whether they both be regions (`'a: 'b`) or whether types are
300/// involved (`T: 'a`). These relationships can be extracted from the
301/// full set of predicates we understand or also from types (in which
302/// case they are called implied bounds). They are fed to the
303/// `OutlivesEnv` which in turn is supplied to the region checker and
304/// other parts of the inference system.
305#[derive(Clone, Debug, TypeFoldable, Lift)]
306pub enum OutlivesBound<'tcx> {
307 RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
308 RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
309 RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
310}
311
312impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OutlivesBound<'tcx> {
313 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
314 mem::discriminant(self).hash_stable(hcx, hasher);
315 match *self {
316 OutlivesBound::RegionSubRegion(ref a, ref b) => {
317 a.hash_stable(hcx, hasher);
318 b.hash_stable(hcx, hasher);
319 }
320 OutlivesBound::RegionSubParam(ref a, ref b) => {
321 a.hash_stable(hcx, hasher);
322 b.hash_stable(hcx, hasher);
323 }
324 OutlivesBound::RegionSubProjection(ref a, ref b) => {
325 a.hash_stable(hcx, hasher);
326 b.hash_stable(hcx, hasher);
327 }
328 }
329 }
330}