]>
Commit | Line | Data |
---|---|---|
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 | |
cdc7bbd5 | 6 | //! `rustc_traits`. |
74b04a01 | 7 | |
f2b60f7d | 8 | use crate::error::DropCheckOverflow; |
74b04a01 XL |
9 | use crate::infer::canonical::{Canonical, QueryResponse}; |
10 | use crate::ty::error::TypeError; | |
11 | use crate::ty::subst::GenericArg; | |
12 | use crate::ty::{self, Ty, TyCtxt}; | |
74b04a01 XL |
13 | use rustc_span::source_map::Span; |
14 | use std::iter::FromIterator; | |
74b04a01 XL |
15 | |
16 | pub mod type_op { | |
17 | use crate::ty::fold::TypeFoldable; | |
18 | use crate::ty::subst::UserSubsts; | |
19 | use crate::ty::{Predicate, Ty}; | |
20 | use rustc_hir::def_id::DefId; | |
21 | use std::fmt; | |
22 | ||
064997fb FG |
23 | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] |
24 | #[derive(TypeFoldable, TypeVisitable)] | |
74b04a01 XL |
25 | pub struct AscribeUserType<'tcx> { |
26 | pub mir_ty: Ty<'tcx>, | |
27 | pub def_id: DefId, | |
28 | pub user_substs: UserSubsts<'tcx>, | |
29 | } | |
30 | ||
31 | impl<'tcx> AscribeUserType<'tcx> { | |
32 | pub fn new(mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>) -> Self { | |
33 | Self { mir_ty, def_id, user_substs } | |
34 | } | |
35 | } | |
36 | ||
064997fb FG |
37 | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] |
38 | #[derive(TypeFoldable, TypeVisitable)] | |
74b04a01 XL |
39 | pub struct Eq<'tcx> { |
40 | pub a: Ty<'tcx>, | |
41 | pub b: Ty<'tcx>, | |
42 | } | |
43 | ||
064997fb FG |
44 | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] |
45 | #[derive(TypeFoldable, TypeVisitable)] | |
74b04a01 XL |
46 | pub struct Subtype<'tcx> { |
47 | pub sub: Ty<'tcx>, | |
48 | pub sup: Ty<'tcx>, | |
49 | } | |
50 | ||
064997fb FG |
51 | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] |
52 | #[derive(TypeFoldable, TypeVisitable)] | |
74b04a01 XL |
53 | pub struct ProvePredicate<'tcx> { |
54 | pub predicate: Predicate<'tcx>, | |
55 | } | |
56 | ||
57 | impl<'tcx> ProvePredicate<'tcx> { | |
58 | pub fn new(predicate: Predicate<'tcx>) -> Self { | |
59 | ProvePredicate { predicate } | |
60 | } | |
61 | } | |
62 | ||
064997fb FG |
63 | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] |
64 | #[derive(TypeFoldable, TypeVisitable)] | |
74b04a01 XL |
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 | ||
5099ac24 | 100 | #[derive(Copy, Clone, Debug, HashStable)] |
74b04a01 XL |
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 | ||
064997fb | 111 | #[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)] |
74b04a01 XL |
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>) { | |
3dfed10e | 119 | if let Some(overflow_ty) = self.overflows.get(0) { |
f2b60f7d | 120 | tcx.sess.emit_err(DropCheckOverflow { span, ty, overflow_ty: *overflow_ty }); |
74b04a01 XL |
121 | } |
122 | } | |
123 | ||
124 | pub fn into_kinds_reporting_overflows( | |
125 | self, | |
126 | tcx: TyCtxt<'tcx>, | |
127 | span: Span, | |
128 | ty: Ty<'tcx>, | |
129 | ) -> Vec<GenericArg<'tcx>> { | |
130 | self.report_overflows(tcx, span, ty); | |
131 | let DropckOutlivesResult { kinds, overflows: _ } = self; | |
132 | kinds | |
133 | } | |
134 | } | |
135 | ||
136 | /// A set of constraints that need to be satisfied in order for | |
137 | /// a type to be valid for destruction. | |
138 | #[derive(Clone, Debug, HashStable)] | |
5e7ed085 | 139 | pub struct DropckConstraint<'tcx> { |
74b04a01 XL |
140 | /// Types that are required to be alive in order for this |
141 | /// type to be valid for destruction. | |
142 | pub outlives: Vec<ty::subst::GenericArg<'tcx>>, | |
143 | ||
144 | /// Types that could not be resolved: projections and params. | |
145 | pub dtorck_types: Vec<Ty<'tcx>>, | |
146 | ||
147 | /// If, during the computation of the dtorck constraint, we | |
148 | /// overflow, that gets recorded here. The caller is expected to | |
149 | /// report an error. | |
150 | pub overflows: Vec<Ty<'tcx>>, | |
151 | } | |
152 | ||
5e7ed085 FG |
153 | impl<'tcx> DropckConstraint<'tcx> { |
154 | pub fn empty() -> DropckConstraint<'tcx> { | |
155 | DropckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] } | |
74b04a01 XL |
156 | } |
157 | } | |
158 | ||
5e7ed085 FG |
159 | impl<'tcx> FromIterator<DropckConstraint<'tcx>> for DropckConstraint<'tcx> { |
160 | fn from_iter<I: IntoIterator<Item = DropckConstraint<'tcx>>>(iter: I) -> Self { | |
74b04a01 XL |
161 | let mut result = Self::empty(); |
162 | ||
5e7ed085 | 163 | for DropckConstraint { outlives, dtorck_types, overflows } in iter { |
74b04a01 XL |
164 | result.outlives.extend(outlives); |
165 | result.dtorck_types.extend(dtorck_types); | |
166 | result.overflows.extend(overflows); | |
167 | } | |
168 | ||
169 | result | |
170 | } | |
171 | } | |
172 | ||
74b04a01 XL |
173 | #[derive(Debug, HashStable)] |
174 | pub struct CandidateStep<'tcx> { | |
175 | pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, | |
176 | pub autoderefs: usize, | |
177 | /// `true` if the type results from a dereference of a raw pointer. | |
178 | /// when assembling candidates, we include these steps, but not when | |
179 | /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods | |
180 | /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then | |
181 | /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't. | |
182 | pub from_unsafe_deref: bool, | |
183 | pub unsize: bool, | |
184 | } | |
185 | ||
5099ac24 | 186 | #[derive(Copy, Clone, Debug, HashStable)] |
74b04a01 XL |
187 | pub struct MethodAutoderefStepsResult<'tcx> { |
188 | /// The valid autoderef steps that could be find. | |
5099ac24 | 189 | pub steps: &'tcx [CandidateStep<'tcx>], |
74b04a01 | 190 | /// If Some(T), a type autoderef reported an error on. |
5099ac24 | 191 | pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>, |
74b04a01 XL |
192 | /// If `true`, `steps` has been truncated due to reaching the |
193 | /// recursion limit. | |
194 | pub reached_recursion_limit: bool, | |
195 | } | |
196 | ||
197 | #[derive(Debug, HashStable)] | |
198 | pub struct MethodAutoderefBadTy<'tcx> { | |
199 | pub reached_raw_pointer: bool, | |
200 | pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, | |
201 | } | |
202 | ||
203 | /// Result from the `normalize_projection_ty` query. | |
064997fb | 204 | #[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] |
74b04a01 XL |
205 | pub struct NormalizationResult<'tcx> { |
206 | /// Result of normalization. | |
207 | pub normalized_ty: Ty<'tcx>, | |
208 | } | |
209 | ||
210 | /// Outlives bounds are relationships between generic parameters, | |
211 | /// whether they both be regions (`'a: 'b`) or whether types are | |
212 | /// involved (`T: 'a`). These relationships can be extracted from the | |
213 | /// full set of predicates we understand or also from types (in which | |
214 | /// case they are called implied bounds). They are fed to the | |
215 | /// `OutlivesEnv` which in turn is supplied to the region checker and | |
216 | /// other parts of the inference system. | |
064997fb | 217 | #[derive(Clone, Debug, TypeFoldable, TypeVisitable, Lift, HashStable)] |
74b04a01 XL |
218 | pub enum OutlivesBound<'tcx> { |
219 | RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), | |
220 | RegionSubParam(ty::Region<'tcx>, ty::ParamTy), | |
221 | RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>), | |
222 | } |