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