diff options
Diffstat (limited to 'crates/hir_ty/src/lib.rs')
-rw-r--r-- | crates/hir_ty/src/lib.rs | 1220 |
1 files changed, 90 insertions, 1130 deletions
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 69265286f..87f10e9d5 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -14,6 +14,10 @@ mod lower; | |||
14 | pub(crate) mod infer; | 14 | pub(crate) mod infer; |
15 | pub(crate) mod utils; | 15 | pub(crate) mod utils; |
16 | mod chalk_cast; | 16 | mod chalk_cast; |
17 | mod chalk_ext; | ||
18 | mod builder; | ||
19 | mod walk; | ||
20 | mod types; | ||
17 | 21 | ||
18 | pub mod display; | 22 | pub mod display; |
19 | pub mod db; | 23 | pub mod db; |
@@ -24,36 +28,33 @@ mod tests; | |||
24 | #[cfg(test)] | 28 | #[cfg(test)] |
25 | mod test_db; | 29 | mod test_db; |
26 | 30 | ||
27 | use std::{iter, mem, ops::Deref, sync::Arc}; | 31 | use std::sync::Arc; |
28 | 32 | ||
29 | use base_db::salsa; | 33 | use base_db::salsa; |
34 | use chalk_ir::UintTy; | ||
30 | use hir_def::{ | 35 | use hir_def::{ |
31 | builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, | 36 | expr::ExprId, type_ref::Rawness, ConstParamId, LifetimeParamId, TraitId, TypeAliasId, |
32 | GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, | 37 | TypeParamId, |
33 | }; | 38 | }; |
34 | use itertools::Itertools; | ||
35 | use smallvec::SmallVec; | ||
36 | 39 | ||
37 | use crate::{ | 40 | use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; |
38 | db::HirDatabase, | ||
39 | display::HirDisplay, | ||
40 | utils::{generics, make_mut_slice, Generics}, | ||
41 | }; | ||
42 | 41 | ||
43 | pub use autoderef::autoderef; | 42 | pub use autoderef::autoderef; |
44 | pub use infer::{InferenceResult, InferenceVar}; | 43 | pub use builder::TyBuilder; |
44 | pub use chalk_ext::*; | ||
45 | pub use infer::{could_unify, InferenceResult}; | ||
45 | pub use lower::{ | 46 | pub use lower::{ |
46 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, | 47 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, |
47 | TyDefId, TyLoweringContext, ValueTyDefId, | 48 | TyDefId, TyLoweringContext, ValueTyDefId, |
48 | }; | 49 | }; |
49 | pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment}; | 50 | pub use traits::{chalk::Interner, TraitEnvironment}; |
51 | pub use types::*; | ||
52 | pub use walk::TypeWalk; | ||
50 | 53 | ||
51 | pub use chalk_ir::{ | 54 | pub use chalk_ir::{ |
52 | cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, | 55 | cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, |
53 | }; | 56 | }; |
54 | 57 | ||
55 | pub use crate::traits::chalk::Interner; | ||
56 | |||
57 | pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; | 58 | pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; |
58 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; | 59 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; |
59 | pub type FnDefId = chalk_ir::FnDefId<Interner>; | 60 | pub type FnDefId = chalk_ir::FnDefId<Interner>; |
@@ -61,371 +62,26 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>; | |||
61 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; | 62 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; |
62 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; | 63 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; |
63 | 64 | ||
65 | pub type VariableKind = chalk_ir::VariableKind<Interner>; | ||
66 | pub type VariableKinds = chalk_ir::VariableKinds<Interner>; | ||
64 | pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; | 67 | pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; |
65 | 68 | ||
66 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | 69 | pub type Lifetime = chalk_ir::Lifetime<Interner>; |
67 | 70 | pub type LifetimeData = chalk_ir::LifetimeData<Interner>; | |
68 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 71 | pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>; |
69 | pub enum Lifetime { | ||
70 | Parameter(LifetimeParamId), | ||
71 | Static, | ||
72 | } | ||
73 | |||
74 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
75 | pub struct OpaqueTy { | ||
76 | pub opaque_ty_id: OpaqueTyId, | ||
77 | pub substitution: Substitution, | ||
78 | } | ||
79 | |||
80 | impl TypeWalk for OpaqueTy { | ||
81 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
82 | self.substitution.walk(f); | ||
83 | } | ||
84 | 72 | ||
85 | fn walk_mut_binders( | 73 | pub type Const = chalk_ir::Const<Interner>; |
86 | &mut self, | 74 | pub type ConstData = chalk_ir::ConstData<Interner>; |
87 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | 75 | pub type ConstValue = chalk_ir::ConstValue<Interner>; |
88 | binders: DebruijnIndex, | 76 | pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>; |
89 | ) { | ||
90 | self.substitution.walk_mut_binders(f, binders); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | /// A "projection" type corresponds to an (unnormalized) | ||
95 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
96 | /// trait and all its parameters are fully known. | ||
97 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
98 | pub struct ProjectionTy { | ||
99 | pub associated_ty_id: AssocTypeId, | ||
100 | pub substitution: Substitution, | ||
101 | } | ||
102 | |||
103 | impl ProjectionTy { | ||
104 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { | ||
105 | TraitRef { | ||
106 | trait_id: to_chalk_trait_id(self.trait_(db)), | ||
107 | substitution: self.substitution.clone(), | ||
108 | } | ||
109 | } | ||
110 | |||
111 | pub fn self_type_parameter(&self) -> &Ty { | ||
112 | &self.substitution[0] | ||
113 | } | ||
114 | 77 | ||
115 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { | 78 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; |
116 | match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container { | ||
117 | AssocContainerId::TraitId(it) => it, | ||
118 | _ => panic!("projection ty without parent trait"), | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | |||
123 | impl TypeWalk for ProjectionTy { | ||
124 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
125 | self.substitution.walk(f); | ||
126 | } | ||
127 | |||
128 | fn walk_mut_binders( | ||
129 | &mut self, | ||
130 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
131 | binders: DebruijnIndex, | ||
132 | ) { | ||
133 | self.substitution.walk_mut_binders(f, binders); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
138 | pub struct DynTy { | ||
139 | /// The unknown self type. | ||
140 | pub bounds: Binders<QuantifiedWhereClauses>, | ||
141 | } | ||
142 | 79 | ||
143 | pub type FnSig = chalk_ir::FnSig<Interner>; | 80 | pub type FnSig = chalk_ir::FnSig<Interner>; |
144 | 81 | ||
145 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 82 | // FIXME: get rid of this |
146 | pub struct FnPointer { | 83 | pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution { |
147 | pub num_args: usize, | 84 | Substitution::intern(s.interned()[..std::cmp::min(s.len(&Interner), n)].into()) |
148 | pub sig: FnSig, | ||
149 | pub substs: Substitution, | ||
150 | } | ||
151 | |||
152 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
153 | pub enum AliasTy { | ||
154 | /// A "projection" type corresponds to an (unnormalized) | ||
155 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
156 | /// trait and all its parameters are fully known. | ||
157 | Projection(ProjectionTy), | ||
158 | /// An opaque type (`impl Trait`). | ||
159 | /// | ||
160 | /// This is currently only used for return type impl trait; each instance of | ||
161 | /// `impl Trait` in a return type gets its own ID. | ||
162 | Opaque(OpaqueTy), | ||
163 | } | ||
164 | |||
165 | impl TypeWalk for AliasTy { | ||
166 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
167 | match self { | ||
168 | AliasTy::Projection(it) => it.walk(f), | ||
169 | AliasTy::Opaque(it) => it.walk(f), | ||
170 | } | ||
171 | } | ||
172 | |||
173 | fn walk_mut_binders( | ||
174 | &mut self, | ||
175 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
176 | binders: DebruijnIndex, | ||
177 | ) { | ||
178 | match self { | ||
179 | AliasTy::Projection(it) => it.walk_mut_binders(f, binders), | ||
180 | AliasTy::Opaque(it) => it.walk_mut_binders(f, binders), | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | /// A type. | ||
185 | /// | ||
186 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | ||
187 | /// the same thing (but in a different way). | ||
188 | /// | ||
189 | /// This should be cheap to clone. | ||
190 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
191 | pub enum TyKind { | ||
192 | /// Structures, enumerations and unions. | ||
193 | Adt(AdtId<Interner>, Substitution), | ||
194 | |||
195 | /// Represents an associated item like `Iterator::Item`. This is used | ||
196 | /// when we have tried to normalize a projection like `T::Item` but | ||
197 | /// couldn't find a better representation. In that case, we generate | ||
198 | /// an **application type** like `(Iterator::Item)<T>`. | ||
199 | AssociatedType(AssocTypeId, Substitution), | ||
200 | |||
201 | /// a scalar type like `bool` or `u32` | ||
202 | Scalar(Scalar), | ||
203 | |||
204 | /// A tuple type. For example, `(i32, bool)`. | ||
205 | Tuple(usize, Substitution), | ||
206 | |||
207 | /// An array with the given length. Written as `[T; n]`. | ||
208 | Array(Ty), | ||
209 | |||
210 | /// The pointee of an array slice. Written as `[T]`. | ||
211 | Slice(Ty), | ||
212 | |||
213 | /// A raw pointer. Written as `*mut T` or `*const T` | ||
214 | Raw(Mutability, Ty), | ||
215 | |||
216 | /// A reference; a pointer with an associated lifetime. Written as | ||
217 | /// `&'a mut T` or `&'a T`. | ||
218 | Ref(Mutability, Ty), | ||
219 | |||
220 | /// This represents a placeholder for an opaque type in situations where we | ||
221 | /// don't know the hidden type (i.e. currently almost always). This is | ||
222 | /// analogous to the `AssociatedType` type constructor. | ||
223 | /// It is also used as the type of async block, with one type parameter | ||
224 | /// representing the Future::Output type. | ||
225 | OpaqueType(OpaqueTyId, Substitution), | ||
226 | |||
227 | /// The anonymous type of a function declaration/definition. Each | ||
228 | /// function has a unique type, which is output (for a function | ||
229 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
230 | /// | ||
231 | /// This includes tuple struct / enum variant constructors as well. | ||
232 | /// | ||
233 | /// For example the type of `bar` here: | ||
234 | /// | ||
235 | /// ``` | ||
236 | /// fn foo() -> i32 { 1 } | ||
237 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
238 | /// ``` | ||
239 | FnDef(FnDefId, Substitution), | ||
240 | |||
241 | /// The pointee of a string slice. Written as `str`. | ||
242 | Str, | ||
243 | |||
244 | /// The never type `!`. | ||
245 | Never, | ||
246 | |||
247 | /// The type of a specific closure. | ||
248 | /// | ||
249 | /// The closure signature is stored in a `FnPtr` type in the first type | ||
250 | /// parameter. | ||
251 | Closure(ClosureId, Substitution), | ||
252 | |||
253 | /// Represents a foreign type declared in external blocks. | ||
254 | ForeignType(ForeignDefId), | ||
255 | |||
256 | /// A pointer to a function. Written as `fn() -> i32`. | ||
257 | /// | ||
258 | /// For example the type of `bar` here: | ||
259 | /// | ||
260 | /// ``` | ||
261 | /// fn foo() -> i32 { 1 } | ||
262 | /// let bar: fn() -> i32 = foo; | ||
263 | /// ``` | ||
264 | Function(FnPointer), | ||
265 | |||
266 | /// An "alias" type represents some form of type alias, such as: | ||
267 | /// - An associated type projection like `<T as Iterator>::Item` | ||
268 | /// - `impl Trait` types | ||
269 | /// - Named type aliases like `type Foo<X> = Vec<X>` | ||
270 | Alias(AliasTy), | ||
271 | |||
272 | /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) | ||
273 | /// {}` when we're type-checking the body of that function. In this | ||
274 | /// situation, we know this stands for *some* type, but don't know the exact | ||
275 | /// type. | ||
276 | Placeholder(PlaceholderIndex), | ||
277 | |||
278 | /// A bound type variable. This is used in various places: when representing | ||
279 | /// some polymorphic type like the type of function `fn f<T>`, the type | ||
280 | /// parameters get turned into variables; during trait resolution, inference | ||
281 | /// variables get turned into bound variables and back; and in `Dyn` the | ||
282 | /// `Self` type is represented with a bound variable as well. | ||
283 | BoundVar(BoundVar), | ||
284 | |||
285 | /// A type variable used during type checking. | ||
286 | InferenceVar(InferenceVar, TyVariableKind), | ||
287 | |||
288 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | ||
289 | /// | ||
290 | /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)` | ||
291 | /// represents the `Self` type inside the bounds. This is currently | ||
292 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | ||
293 | /// didn't seem worth the overhead yet. | ||
294 | Dyn(DynTy), | ||
295 | |||
296 | /// A placeholder for a type which could not be computed; this is propagated | ||
297 | /// to avoid useless error messages. Doubles as a placeholder where type | ||
298 | /// variables are inserted before type checking, since we want to try to | ||
299 | /// infer a better type here anyway -- for the IDE use case, we want to try | ||
300 | /// to infer as much as possible even in the presence of type errors. | ||
301 | Unknown, | ||
302 | } | ||
303 | |||
304 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
305 | pub struct Ty(Arc<TyKind>); | ||
306 | |||
307 | impl TyKind { | ||
308 | pub fn intern(self, _interner: &Interner) -> Ty { | ||
309 | Ty(Arc::new(self)) | ||
310 | } | ||
311 | } | ||
312 | |||
313 | impl Ty { | ||
314 | pub fn interned(&self, _interner: &Interner) -> &TyKind { | ||
315 | &self.0 | ||
316 | } | ||
317 | |||
318 | pub fn interned_mut(&mut self) -> &mut TyKind { | ||
319 | Arc::make_mut(&mut self.0) | ||
320 | } | ||
321 | |||
322 | pub fn into_inner(self) -> TyKind { | ||
323 | Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone()) | ||
324 | } | ||
325 | } | ||
326 | |||
327 | /// A list of substitutions for generic parameters. | ||
328 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
329 | pub struct Substitution(SmallVec<[Ty; 2]>); | ||
330 | |||
331 | impl TypeWalk for Substitution { | ||
332 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
333 | for t in self.0.iter() { | ||
334 | t.walk(f); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | fn walk_mut_binders( | ||
339 | &mut self, | ||
340 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
341 | binders: DebruijnIndex, | ||
342 | ) { | ||
343 | for t in &mut self.0 { | ||
344 | t.walk_mut_binders(f, binders); | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | |||
349 | impl Substitution { | ||
350 | pub fn interned(&self, _: &Interner) -> &[Ty] { | ||
351 | &self.0 | ||
352 | } | ||
353 | |||
354 | pub fn empty() -> Substitution { | ||
355 | Substitution(SmallVec::new()) | ||
356 | } | ||
357 | |||
358 | pub fn single(ty: Ty) -> Substitution { | ||
359 | Substitution({ | ||
360 | let mut v = SmallVec::new(); | ||
361 | v.push(ty); | ||
362 | v | ||
363 | }) | ||
364 | } | ||
365 | |||
366 | pub fn prefix(&self, n: usize) -> Substitution { | ||
367 | Substitution(self.0[..std::cmp::min(self.0.len(), n)].into()) | ||
368 | } | ||
369 | |||
370 | pub fn suffix(&self, n: usize) -> Substitution { | ||
371 | Substitution(self.0[self.0.len() - std::cmp::min(self.0.len(), n)..].into()) | ||
372 | } | ||
373 | |||
374 | pub fn as_single(&self) -> &Ty { | ||
375 | if self.0.len() != 1 { | ||
376 | panic!("expected substs of len 1, got {:?}", self); | ||
377 | } | ||
378 | &self.0[0] | ||
379 | } | ||
380 | |||
381 | pub fn from_iter(_interner: &Interner, elements: impl IntoIterator<Item = Ty>) -> Self { | ||
382 | Substitution(elements.into_iter().collect()) | ||
383 | } | ||
384 | |||
385 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). | ||
386 | pub(crate) fn type_params_for_generics( | ||
387 | db: &dyn HirDatabase, | ||
388 | generic_params: &Generics, | ||
389 | ) -> Substitution { | ||
390 | Substitution( | ||
391 | generic_params | ||
392 | .iter() | ||
393 | .map(|(id, _)| TyKind::Placeholder(to_placeholder_idx(db, id)).intern(&Interner)) | ||
394 | .collect(), | ||
395 | ) | ||
396 | } | ||
397 | |||
398 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). | ||
399 | pub fn type_params(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution { | ||
400 | let params = generics(db.upcast(), def.into()); | ||
401 | Substitution::type_params_for_generics(db, ¶ms) | ||
402 | } | ||
403 | |||
404 | /// Return Substs that replace each parameter by a bound variable. | ||
405 | pub(crate) fn bound_vars(generic_params: &Generics, debruijn: DebruijnIndex) -> Substitution { | ||
406 | Substitution( | ||
407 | generic_params | ||
408 | .iter() | ||
409 | .enumerate() | ||
410 | .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)) | ||
411 | .collect(), | ||
412 | ) | ||
413 | } | ||
414 | |||
415 | pub fn build_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { | ||
416 | let def = def.into(); | ||
417 | let params = generics(db.upcast(), def); | ||
418 | let param_count = params.len(); | ||
419 | Substitution::builder(param_count) | ||
420 | } | ||
421 | |||
422 | pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder { | ||
423 | Substitution::builder(generic_params.len()) | ||
424 | } | ||
425 | |||
426 | fn builder(param_count: usize) -> SubstsBuilder { | ||
427 | SubstsBuilder { vec: Vec::with_capacity(param_count), param_count } | ||
428 | } | ||
429 | } | 85 | } |
430 | 86 | ||
431 | /// Return an index of a parameter in the generic type parameter list by it's id. | 87 | /// Return an index of a parameter in the generic type parameter list by it's id. |
@@ -433,244 +89,36 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> { | |||
433 | generics(db.upcast(), id.parent).param_idx(id) | 89 | generics(db.upcast(), id.parent).param_idx(id) |
434 | } | 90 | } |
435 | 91 | ||
436 | #[derive(Debug, Clone)] | 92 | pub fn wrap_empty_binders<T>(value: T) -> Binders<T> |
437 | pub struct SubstsBuilder { | 93 | where |
438 | vec: Vec<Ty>, | 94 | T: TypeWalk, |
439 | param_count: usize, | 95 | { |
440 | } | 96 | Binders::empty(&Interner, value.shifted_in_from(DebruijnIndex::ONE)) |
441 | 97 | } | |
442 | impl SubstsBuilder { | 98 | |
443 | pub fn build(self) -> Substitution { | 99 | pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> { |
444 | assert_eq!(self.vec.len(), self.param_count); | 100 | Binders::new( |
445 | Substitution(self.vec.into()) | 101 | VariableKinds::from_iter( |
446 | } | 102 | &Interner, |
447 | 103 | std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)) | |
448 | pub fn push(mut self, ty: Ty) -> Self { | 104 | .take(num_vars), |
449 | self.vec.push(ty); | 105 | ), |
450 | self | 106 | value, |
451 | } | 107 | ) |
452 | 108 | } | |
453 | fn remaining(&self) -> usize { | 109 | |
454 | self.param_count - self.vec.len() | 110 | // FIXME: get rid of this |
455 | } | 111 | pub fn make_canonical<T>( |
456 | 112 | value: T, | |
457 | pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { | 113 | kinds: impl IntoIterator<Item = TyVariableKind>, |
458 | self.fill( | 114 | ) -> Canonical<T> { |
459 | (starting_from..) | 115 | let kinds = kinds.into_iter().map(|tk| { |
460 | .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), | 116 | chalk_ir::CanonicalVarKind::new( |
117 | chalk_ir::VariableKind::Ty(tk), | ||
118 | chalk_ir::UniverseIndex::ROOT, | ||
461 | ) | 119 | ) |
462 | } | 120 | }); |
463 | 121 | Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) } | |
464 | pub fn fill_with_unknown(self) -> Self { | ||
465 | self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) | ||
466 | } | ||
467 | |||
468 | pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self { | ||
469 | self.vec.extend(filler.take(self.remaining())); | ||
470 | assert_eq!(self.remaining(), 0); | ||
471 | self | ||
472 | } | ||
473 | |||
474 | pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self { | ||
475 | assert!(self.vec.is_empty()); | ||
476 | assert!(parent_substs.len() <= self.param_count); | ||
477 | self.vec.extend(parent_substs.iter().cloned()); | ||
478 | self | ||
479 | } | ||
480 | } | ||
481 | |||
482 | impl Deref for Substitution { | ||
483 | type Target = [Ty]; | ||
484 | |||
485 | fn deref(&self) -> &[Ty] { | ||
486 | &self.0 | ||
487 | } | ||
488 | } | ||
489 | |||
490 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | ||
491 | pub struct Binders<T> { | ||
492 | pub num_binders: usize, | ||
493 | pub value: T, | ||
494 | } | ||
495 | |||
496 | impl<T> Binders<T> { | ||
497 | pub fn new(num_binders: usize, value: T) -> Self { | ||
498 | Self { num_binders, value } | ||
499 | } | ||
500 | |||
501 | pub fn wrap_empty(value: T) -> Self | ||
502 | where | ||
503 | T: TypeWalk, | ||
504 | { | ||
505 | Self { num_binders: 0, value: value.shift_bound_vars(DebruijnIndex::ONE) } | ||
506 | } | ||
507 | |||
508 | pub fn as_ref(&self) -> Binders<&T> { | ||
509 | Binders { num_binders: self.num_binders, value: &self.value } | ||
510 | } | ||
511 | |||
512 | pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Binders<U> { | ||
513 | Binders { num_binders: self.num_binders, value: f(self.value) } | ||
514 | } | ||
515 | |||
516 | pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> { | ||
517 | Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) | ||
518 | } | ||
519 | |||
520 | pub fn skip_binders(&self) -> &T { | ||
521 | &self.value | ||
522 | } | ||
523 | |||
524 | pub fn into_value_and_skipped_binders(self) -> (T, usize) { | ||
525 | (self.value, self.num_binders) | ||
526 | } | ||
527 | } | ||
528 | |||
529 | impl<T: Clone> Binders<&T> { | ||
530 | pub fn cloned(&self) -> Binders<T> { | ||
531 | Binders { num_binders: self.num_binders, value: self.value.clone() } | ||
532 | } | ||
533 | } | ||
534 | |||
535 | impl<T: TypeWalk> Binders<T> { | ||
536 | /// Substitutes all variables. | ||
537 | pub fn subst(self, subst: &Substitution) -> T { | ||
538 | assert_eq!(subst.len(), self.num_binders); | ||
539 | self.value.subst_bound_vars(subst) | ||
540 | } | ||
541 | } | ||
542 | |||
543 | impl<T: TypeWalk> TypeWalk for Binders<T> { | ||
544 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
545 | self.value.walk(f); | ||
546 | } | ||
547 | |||
548 | fn walk_mut_binders( | ||
549 | &mut self, | ||
550 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
551 | binders: DebruijnIndex, | ||
552 | ) { | ||
553 | self.value.walk_mut_binders(f, binders.shifted_in()) | ||
554 | } | ||
555 | } | ||
556 | |||
557 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | ||
558 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
559 | pub struct TraitRef { | ||
560 | pub trait_id: ChalkTraitId, | ||
561 | pub substitution: Substitution, | ||
562 | } | ||
563 | |||
564 | impl TraitRef { | ||
565 | pub fn self_type_parameter(&self) -> &Ty { | ||
566 | &self.substitution[0] | ||
567 | } | ||
568 | |||
569 | pub fn hir_trait_id(&self) -> TraitId { | ||
570 | from_chalk_trait_id(self.trait_id) | ||
571 | } | ||
572 | } | ||
573 | |||
574 | impl TypeWalk for TraitRef { | ||
575 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
576 | self.substitution.walk(f); | ||
577 | } | ||
578 | |||
579 | fn walk_mut_binders( | ||
580 | &mut self, | ||
581 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
582 | binders: DebruijnIndex, | ||
583 | ) { | ||
584 | self.substitution.walk_mut_binders(f, binders); | ||
585 | } | ||
586 | } | ||
587 | |||
588 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | ||
589 | /// parameters of a generic item. | ||
590 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
591 | pub enum WhereClause { | ||
592 | /// The given trait needs to be implemented for its type parameters. | ||
593 | Implemented(TraitRef), | ||
594 | /// An associated type bindings like in `Iterator<Item = T>`. | ||
595 | AliasEq(AliasEq), | ||
596 | } | ||
597 | |||
598 | impl WhereClause { | ||
599 | pub fn is_implemented(&self) -> bool { | ||
600 | matches!(self, WhereClause::Implemented(_)) | ||
601 | } | ||
602 | |||
603 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> { | ||
604 | match self { | ||
605 | WhereClause::Implemented(tr) => Some(tr.clone()), | ||
606 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => { | ||
607 | Some(proj.trait_ref(db)) | ||
608 | } | ||
609 | WhereClause::AliasEq(_) => None, | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | impl TypeWalk for WhereClause { | ||
615 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
616 | match self { | ||
617 | WhereClause::Implemented(trait_ref) => trait_ref.walk(f), | ||
618 | WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), | ||
619 | } | ||
620 | } | ||
621 | |||
622 | fn walk_mut_binders( | ||
623 | &mut self, | ||
624 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
625 | binders: DebruijnIndex, | ||
626 | ) { | ||
627 | match self { | ||
628 | WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), | ||
629 | WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders), | ||
630 | } | ||
631 | } | ||
632 | } | ||
633 | |||
634 | pub type QuantifiedWhereClause = Binders<WhereClause>; | ||
635 | |||
636 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
637 | pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); | ||
638 | |||
639 | impl QuantifiedWhereClauses { | ||
640 | pub fn from_iter( | ||
641 | _interner: &Interner, | ||
642 | elements: impl IntoIterator<Item = QuantifiedWhereClause>, | ||
643 | ) -> Self { | ||
644 | QuantifiedWhereClauses(elements.into_iter().collect()) | ||
645 | } | ||
646 | |||
647 | pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { | ||
648 | &self.0 | ||
649 | } | ||
650 | } | ||
651 | |||
652 | /// Basically a claim (currently not validated / checked) that the contained | ||
653 | /// type / trait ref contains no inference variables; any inference variables it | ||
654 | /// contained have been replaced by bound variables, and `kinds` tells us how | ||
655 | /// many there are and whether they were normal or float/int variables. This is | ||
656 | /// used to erase irrelevant differences between types before using them in | ||
657 | /// queries. | ||
658 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
659 | pub struct Canonical<T> { | ||
660 | pub value: T, | ||
661 | pub binders: CanonicalVarKinds, | ||
662 | } | ||
663 | |||
664 | impl<T> Canonical<T> { | ||
665 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { | ||
666 | let kinds = kinds.into_iter().map(|tk| { | ||
667 | chalk_ir::CanonicalVarKind::new( | ||
668 | chalk_ir::VariableKind::Ty(tk), | ||
669 | chalk_ir::UniverseIndex::ROOT, | ||
670 | ) | ||
671 | }); | ||
672 | Self { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) } | ||
673 | } | ||
674 | } | 122 | } |
675 | 123 | ||
676 | /// A function signature as seen by type inference: Several parameter types and | 124 | /// A function signature as seen by type inference: Several parameter types and |
@@ -692,23 +140,21 @@ impl CallableSig { | |||
692 | 140 | ||
693 | pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { | 141 | pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { |
694 | CallableSig { | 142 | CallableSig { |
695 | // FIXME: what to do about lifetime params? | 143 | // FIXME: what to do about lifetime params? -> return PolyFnSig |
696 | params_and_return: fn_ptr | 144 | params_and_return: fn_ptr |
697 | .substs | 145 | .substitution |
698 | .clone() | 146 | .clone() |
699 | .shift_bound_vars_out(DebruijnIndex::ONE) | 147 | .shifted_out_to(DebruijnIndex::ONE) |
700 | .interned(&Interner) | 148 | .expect("unexpected lifetime vars in fn ptr") |
149 | .0 | ||
150 | .interned() | ||
701 | .iter() | 151 | .iter() |
702 | .cloned() | 152 | .map(|arg| arg.assert_ty_ref(&Interner).clone()) |
703 | .collect(), | 153 | .collect(), |
704 | is_varargs: fn_ptr.sig.variadic, | 154 | is_varargs: fn_ptr.sig.variadic, |
705 | } | 155 | } |
706 | } | 156 | } |
707 | 157 | ||
708 | pub fn from_substs(substs: &Substitution) -> CallableSig { | ||
709 | CallableSig { params_and_return: substs.iter().cloned().collect(), is_varargs: false } | ||
710 | } | ||
711 | |||
712 | pub fn params(&self) -> &[Ty] { | 158 | pub fn params(&self) -> &[Ty] { |
713 | &self.params_and_return[0..self.params_and_return.len() - 1] | 159 | &self.params_and_return[0..self.params_and_return.len() - 1] |
714 | } | 160 | } |
@@ -718,518 +164,7 @@ impl CallableSig { | |||
718 | } | 164 | } |
719 | } | 165 | } |
720 | 166 | ||
721 | impl TypeWalk for CallableSig { | 167 | impl Ty {} |
722 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
723 | for t in self.params_and_return.iter() { | ||
724 | t.walk(f); | ||
725 | } | ||
726 | } | ||
727 | |||
728 | fn walk_mut_binders( | ||
729 | &mut self, | ||
730 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
731 | binders: DebruijnIndex, | ||
732 | ) { | ||
733 | for t in make_mut_slice(&mut self.params_and_return) { | ||
734 | t.walk_mut_binders(f, binders); | ||
735 | } | ||
736 | } | ||
737 | } | ||
738 | |||
739 | impl Ty { | ||
740 | pub fn unit() -> Self { | ||
741 | TyKind::Tuple(0, Substitution::empty()).intern(&Interner) | ||
742 | } | ||
743 | |||
744 | pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty { | ||
745 | TyKind::Adt(AdtId(adt), substs).intern(&Interner) | ||
746 | } | ||
747 | |||
748 | pub fn fn_ptr(sig: CallableSig) -> Self { | ||
749 | TyKind::Function(FnPointer { | ||
750 | num_args: sig.params().len(), | ||
751 | sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, | ||
752 | substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()), | ||
753 | }) | ||
754 | .intern(&Interner) | ||
755 | } | ||
756 | |||
757 | pub fn builtin(builtin: BuiltinType) -> Self { | ||
758 | match builtin { | ||
759 | BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), | ||
760 | BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner), | ||
761 | BuiltinType::Str => TyKind::Str.intern(&Interner), | ||
762 | BuiltinType::Int(t) => { | ||
763 | TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner) | ||
764 | } | ||
765 | BuiltinType::Uint(t) => { | ||
766 | TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner) | ||
767 | } | ||
768 | BuiltinType::Float(t) => { | ||
769 | TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner) | ||
770 | } | ||
771 | } | ||
772 | } | ||
773 | |||
774 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { | ||
775 | match self.interned(&Interner) { | ||
776 | TyKind::Ref(mutability, ty) => Some((ty, *mutability)), | ||
777 | _ => None, | ||
778 | } | ||
779 | } | ||
780 | |||
781 | pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { | ||
782 | match self.interned(&Interner) { | ||
783 | TyKind::Ref(mutability, ty) => Some((ty, Rawness::Ref, *mutability)), | ||
784 | TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)), | ||
785 | _ => None, | ||
786 | } | ||
787 | } | ||
788 | |||
789 | pub fn strip_references(&self) -> &Ty { | ||
790 | let mut t: &Ty = self; | ||
791 | |||
792 | while let TyKind::Ref(_mutability, ty) = t.interned(&Interner) { | ||
793 | t = ty; | ||
794 | } | ||
795 | |||
796 | t | ||
797 | } | ||
798 | |||
799 | pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> { | ||
800 | match self.interned(&Interner) { | ||
801 | TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), | ||
802 | _ => None, | ||
803 | } | ||
804 | } | ||
805 | |||
806 | pub fn as_tuple(&self) -> Option<&Substitution> { | ||
807 | match self.interned(&Interner) { | ||
808 | TyKind::Tuple(_, substs) => Some(substs), | ||
809 | _ => None, | ||
810 | } | ||
811 | } | ||
812 | |||
813 | pub fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> { | ||
814 | match *self.interned(&Interner) { | ||
815 | TyKind::Adt(AdtId(adt), ..) => Some(adt.into()), | ||
816 | TyKind::FnDef(callable, ..) => { | ||
817 | Some(db.lookup_intern_callable_def(callable.into()).into()) | ||
818 | } | ||
819 | TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()), | ||
820 | TyKind::ForeignType(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()), | ||
821 | _ => None, | ||
822 | } | ||
823 | } | ||
824 | |||
825 | pub fn is_never(&self) -> bool { | ||
826 | matches!(self.interned(&Interner), TyKind::Never) | ||
827 | } | ||
828 | |||
829 | pub fn is_unknown(&self) -> bool { | ||
830 | matches!(self.interned(&Interner), TyKind::Unknown) | ||
831 | } | ||
832 | |||
833 | pub fn equals_ctor(&self, other: &Ty) -> bool { | ||
834 | match (self.interned(&Interner), other.interned(&Interner)) { | ||
835 | (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2, | ||
836 | (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_), TyKind::Array(_)) => true, | ||
837 | (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2, | ||
838 | (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2, | ||
839 | (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => { | ||
840 | ty_id == ty_id2 | ||
841 | } | ||
842 | (TyKind::ForeignType(ty_id, ..), TyKind::ForeignType(ty_id2, ..)) => ty_id == ty_id2, | ||
843 | (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2, | ||
844 | (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..)) | ||
845 | | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => { | ||
846 | mutability == mutability2 | ||
847 | } | ||
848 | ( | ||
849 | TyKind::Function(FnPointer { num_args, sig, .. }), | ||
850 | TyKind::Function(FnPointer { num_args: num_args2, sig: sig2, .. }), | ||
851 | ) => num_args == num_args2 && sig == sig2, | ||
852 | (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => { | ||
853 | cardinality == cardinality2 | ||
854 | } | ||
855 | (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true, | ||
856 | (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2, | ||
857 | _ => false, | ||
858 | } | ||
859 | } | ||
860 | |||
861 | /// If this is a `dyn Trait` type, this returns the `Trait` part. | ||
862 | fn dyn_trait_ref(&self) -> Option<&TraitRef> { | ||
863 | match self.interned(&Interner) { | ||
864 | TyKind::Dyn(dyn_ty) => { | ||
865 | dyn_ty.bounds.value.interned().get(0).and_then(|b| match b.skip_binders() { | ||
866 | WhereClause::Implemented(trait_ref) => Some(trait_ref), | ||
867 | _ => None, | ||
868 | }) | ||
869 | } | ||
870 | _ => None, | ||
871 | } | ||
872 | } | ||
873 | |||
874 | /// If this is a `dyn Trait`, returns that trait. | ||
875 | pub fn dyn_trait(&self) -> Option<TraitId> { | ||
876 | self.dyn_trait_ref().map(|it| it.trait_id).map(from_chalk_trait_id) | ||
877 | } | ||
878 | |||
879 | fn builtin_deref(&self) -> Option<Ty> { | ||
880 | match self.interned(&Interner) { | ||
881 | TyKind::Ref(.., ty) => Some(ty.clone()), | ||
882 | TyKind::Raw(.., ty) => Some(ty.clone()), | ||
883 | _ => None, | ||
884 | } | ||
885 | } | ||
886 | |||
887 | pub fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> { | ||
888 | match self.interned(&Interner) { | ||
889 | &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())), | ||
890 | _ => None, | ||
891 | } | ||
892 | } | ||
893 | |||
894 | pub fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> { | ||
895 | if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) { | ||
896 | Some(func) | ||
897 | } else { | ||
898 | None | ||
899 | } | ||
900 | } | ||
901 | |||
902 | pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> { | ||
903 | match self.interned(&Interner) { | ||
904 | TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)), | ||
905 | TyKind::FnDef(def, parameters) => { | ||
906 | let callable_def = db.lookup_intern_callable_def((*def).into()); | ||
907 | let sig = db.callable_item_signature(callable_def); | ||
908 | Some(sig.subst(¶meters)) | ||
909 | } | ||
910 | TyKind::Closure(.., substs) => { | ||
911 | let sig_param = &substs[0]; | ||
912 | sig_param.callable_sig(db) | ||
913 | } | ||
914 | _ => None, | ||
915 | } | ||
916 | } | ||
917 | |||
918 | /// Returns the type parameters of this type if it has some (i.e. is an ADT | ||
919 | /// or function); so if `self` is `Option<u32>`, this returns the `u32`. | ||
920 | pub fn substs(&self) -> Option<&Substitution> { | ||
921 | match self.interned(&Interner) { | ||
922 | TyKind::Adt(_, substs) | ||
923 | | TyKind::FnDef(_, substs) | ||
924 | | TyKind::Function(FnPointer { substs, .. }) | ||
925 | | TyKind::Tuple(_, substs) | ||
926 | | TyKind::OpaqueType(_, substs) | ||
927 | | TyKind::AssociatedType(_, substs) | ||
928 | | TyKind::Closure(.., substs) => Some(substs), | ||
929 | _ => None, | ||
930 | } | ||
931 | } | ||
932 | |||
933 | fn substs_mut(&mut self) -> Option<&mut Substitution> { | ||
934 | match self.interned_mut() { | ||
935 | TyKind::Adt(_, substs) | ||
936 | | TyKind::FnDef(_, substs) | ||
937 | | TyKind::Function(FnPointer { substs, .. }) | ||
938 | | TyKind::Tuple(_, substs) | ||
939 | | TyKind::OpaqueType(_, substs) | ||
940 | | TyKind::AssociatedType(_, substs) | ||
941 | | TyKind::Closure(.., substs) => Some(substs), | ||
942 | _ => None, | ||
943 | } | ||
944 | } | ||
945 | |||
946 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> { | ||
947 | match self.interned(&Interner) { | ||
948 | TyKind::OpaqueType(opaque_ty_id, ..) => { | ||
949 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { | ||
950 | ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => { | ||
951 | let krate = def.module(db.upcast()).krate(); | ||
952 | if let Some(future_trait) = db | ||
953 | .lang_item(krate, "future_trait".into()) | ||
954 | .and_then(|item| item.as_trait()) | ||
955 | { | ||
956 | // This is only used by type walking. | ||
957 | // Parameters will be walked outside, and projection predicate is not used. | ||
958 | // So just provide the Future trait. | ||
959 | let impl_bound = Binders::new( | ||
960 | 0, | ||
961 | WhereClause::Implemented(TraitRef { | ||
962 | trait_id: to_chalk_trait_id(future_trait), | ||
963 | substitution: Substitution::empty(), | ||
964 | }), | ||
965 | ); | ||
966 | Some(vec![impl_bound]) | ||
967 | } else { | ||
968 | None | ||
969 | } | ||
970 | } | ||
971 | ImplTraitId::ReturnTypeImplTrait(..) => None, | ||
972 | } | ||
973 | } | ||
974 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { | ||
975 | let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into()) | ||
976 | { | ||
977 | ImplTraitId::ReturnTypeImplTrait(func, idx) => { | ||
978 | db.return_type_impl_traits(func).map(|it| { | ||
979 | let data = (*it) | ||
980 | .as_ref() | ||
981 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | ||
982 | data.subst(&opaque_ty.substitution) | ||
983 | }) | ||
984 | } | ||
985 | // It always has an parameter for Future::Output type. | ||
986 | ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(), | ||
987 | }; | ||
988 | |||
989 | predicates.map(|it| it.value) | ||
990 | } | ||
991 | TyKind::Placeholder(idx) => { | ||
992 | let id = from_placeholder_idx(db, *idx); | ||
993 | let generic_params = db.generic_params(id.parent); | ||
994 | let param_data = &generic_params.types[id.local_id]; | ||
995 | match param_data.provenance { | ||
996 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { | ||
997 | let substs = Substitution::type_params(db, id.parent); | ||
998 | let predicates = db | ||
999 | .generic_predicates(id.parent) | ||
1000 | .into_iter() | ||
1001 | .map(|pred| pred.clone().subst(&substs)) | ||
1002 | .filter(|wc| match &wc.skip_binders() { | ||
1003 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | ||
1004 | WhereClause::AliasEq(AliasEq { | ||
1005 | alias: AliasTy::Projection(proj), | ||
1006 | ty: _, | ||
1007 | }) => proj.self_type_parameter() == self, | ||
1008 | _ => false, | ||
1009 | }) | ||
1010 | .collect_vec(); | ||
1011 | |||
1012 | Some(predicates) | ||
1013 | } | ||
1014 | _ => None, | ||
1015 | } | ||
1016 | } | ||
1017 | _ => None, | ||
1018 | } | ||
1019 | } | ||
1020 | |||
1021 | pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> { | ||
1022 | match self.interned(&Interner) { | ||
1023 | TyKind::AssociatedType(id, ..) => { | ||
1024 | match from_assoc_type_id(*id).lookup(db.upcast()).container { | ||
1025 | AssocContainerId::TraitId(trait_id) => Some(trait_id), | ||
1026 | _ => None, | ||
1027 | } | ||
1028 | } | ||
1029 | TyKind::Alias(AliasTy::Projection(projection_ty)) => { | ||
1030 | match from_assoc_type_id(projection_ty.associated_ty_id) | ||
1031 | .lookup(db.upcast()) | ||
1032 | .container | ||
1033 | { | ||
1034 | AssocContainerId::TraitId(trait_id) => Some(trait_id), | ||
1035 | _ => None, | ||
1036 | } | ||
1037 | } | ||
1038 | _ => None, | ||
1039 | } | ||
1040 | } | ||
1041 | } | ||
1042 | |||
1043 | /// This allows walking structures that contain types to do something with those | ||
1044 | /// types, similar to Chalk's `Fold` trait. | ||
1045 | pub trait TypeWalk { | ||
1046 | fn walk(&self, f: &mut impl FnMut(&Ty)); | ||
1047 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
1048 | self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST); | ||
1049 | } | ||
1050 | /// Walk the type, counting entered binders. | ||
1051 | /// | ||
1052 | /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers | ||
1053 | /// to the innermost binder, 1 to the next, etc.. So when we want to | ||
1054 | /// substitute a certain bound variable, we can't just walk the whole type | ||
1055 | /// and blindly replace each instance of a certain index; when we 'enter' | ||
1056 | /// things that introduce new bound variables, we have to keep track of | ||
1057 | /// that. Currently, the only thing that introduces bound variables on our | ||
1058 | /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound | ||
1059 | /// variable for the self type. | ||
1060 | fn walk_mut_binders( | ||
1061 | &mut self, | ||
1062 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
1063 | binders: DebruijnIndex, | ||
1064 | ); | ||
1065 | |||
1066 | fn fold_binders( | ||
1067 | mut self, | ||
1068 | f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty, | ||
1069 | binders: DebruijnIndex, | ||
1070 | ) -> Self | ||
1071 | where | ||
1072 | Self: Sized, | ||
1073 | { | ||
1074 | self.walk_mut_binders( | ||
1075 | &mut |ty_mut, binders| { | ||
1076 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
1077 | *ty_mut = f(ty, binders); | ||
1078 | }, | ||
1079 | binders, | ||
1080 | ); | ||
1081 | self | ||
1082 | } | ||
1083 | |||
1084 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self | ||
1085 | where | ||
1086 | Self: Sized, | ||
1087 | { | ||
1088 | self.walk_mut(&mut |ty_mut| { | ||
1089 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
1090 | *ty_mut = f(ty); | ||
1091 | }); | ||
1092 | self | ||
1093 | } | ||
1094 | |||
1095 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
1096 | fn subst_bound_vars(self, substs: &Substitution) -> Self | ||
1097 | where | ||
1098 | Self: Sized, | ||
1099 | { | ||
1100 | self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST) | ||
1101 | } | ||
1102 | |||
1103 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
1104 | fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self | ||
1105 | where | ||
1106 | Self: Sized, | ||
1107 | { | ||
1108 | self.walk_mut_binders( | ||
1109 | &mut |ty, binders| { | ||
1110 | if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { | ||
1111 | if bound.debruijn >= binders { | ||
1112 | *ty = substs.0[bound.index].clone().shift_bound_vars(binders); | ||
1113 | } | ||
1114 | } | ||
1115 | }, | ||
1116 | depth, | ||
1117 | ); | ||
1118 | self | ||
1119 | } | ||
1120 | |||
1121 | /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`. | ||
1122 | fn shift_bound_vars(self, n: DebruijnIndex) -> Self | ||
1123 | where | ||
1124 | Self: Sized, | ||
1125 | { | ||
1126 | self.fold_binders( | ||
1127 | &mut |ty, binders| match ty.interned(&Interner) { | ||
1128 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
1129 | TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner) | ||
1130 | } | ||
1131 | _ => ty, | ||
1132 | }, | ||
1133 | DebruijnIndex::INNERMOST, | ||
1134 | ) | ||
1135 | } | ||
1136 | |||
1137 | /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`. | ||
1138 | fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self | ||
1139 | where | ||
1140 | Self: Sized + std::fmt::Debug, | ||
1141 | { | ||
1142 | self.fold_binders( | ||
1143 | &mut |ty, binders| match ty.interned(&Interner) { | ||
1144 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
1145 | TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone())) | ||
1146 | .intern(&Interner) | ||
1147 | } | ||
1148 | _ => ty, | ||
1149 | }, | ||
1150 | DebruijnIndex::INNERMOST, | ||
1151 | ) | ||
1152 | } | ||
1153 | } | ||
1154 | |||
1155 | impl TypeWalk for Ty { | ||
1156 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
1157 | match self.interned(&Interner) { | ||
1158 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
1159 | for t in p_ty.substitution.iter() { | ||
1160 | t.walk(f); | ||
1161 | } | ||
1162 | } | ||
1163 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
1164 | for t in o_ty.substitution.iter() { | ||
1165 | t.walk(f); | ||
1166 | } | ||
1167 | } | ||
1168 | TyKind::Dyn(dyn_ty) => { | ||
1169 | for p in dyn_ty.bounds.value.interned().iter() { | ||
1170 | p.walk(f); | ||
1171 | } | ||
1172 | } | ||
1173 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
1174 | ty.walk(f); | ||
1175 | } | ||
1176 | _ => { | ||
1177 | if let Some(substs) = self.substs() { | ||
1178 | for t in substs.iter() { | ||
1179 | t.walk(f); | ||
1180 | } | ||
1181 | } | ||
1182 | } | ||
1183 | } | ||
1184 | f(self); | ||
1185 | } | ||
1186 | |||
1187 | fn walk_mut_binders( | ||
1188 | &mut self, | ||
1189 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
1190 | binders: DebruijnIndex, | ||
1191 | ) { | ||
1192 | match self.interned_mut() { | ||
1193 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
1194 | p_ty.substitution.walk_mut_binders(f, binders); | ||
1195 | } | ||
1196 | TyKind::Dyn(dyn_ty) => { | ||
1197 | for p in make_mut_slice(&mut dyn_ty.bounds.value.0) { | ||
1198 | p.walk_mut_binders(f, binders.shifted_in()); | ||
1199 | } | ||
1200 | } | ||
1201 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
1202 | o_ty.substitution.walk_mut_binders(f, binders); | ||
1203 | } | ||
1204 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
1205 | ty.walk_mut_binders(f, binders); | ||
1206 | } | ||
1207 | _ => { | ||
1208 | if let Some(substs) = self.substs_mut() { | ||
1209 | substs.walk_mut_binders(f, binders); | ||
1210 | } | ||
1211 | } | ||
1212 | } | ||
1213 | f(self, binders); | ||
1214 | } | ||
1215 | } | ||
1216 | |||
1217 | impl<T: TypeWalk> TypeWalk for Vec<T> { | ||
1218 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
1219 | for t in self { | ||
1220 | t.walk(f); | ||
1221 | } | ||
1222 | } | ||
1223 | fn walk_mut_binders( | ||
1224 | &mut self, | ||
1225 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
1226 | binders: DebruijnIndex, | ||
1227 | ) { | ||
1228 | for t in self { | ||
1229 | t.walk_mut_binders(f, binders); | ||
1230 | } | ||
1231 | } | ||
1232 | } | ||
1233 | 168 | ||
1234 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | 169 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] |
1235 | pub enum ImplTraitId { | 170 | pub enum ImplTraitId { |
@@ -1277,6 +212,18 @@ pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderI | |||
1277 | } | 212 | } |
1278 | } | 213 | } |
1279 | 214 | ||
215 | pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId { | ||
216 | assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); | ||
217 | let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); | ||
218 | db.lookup_intern_lifetime_param_id(interned_id) | ||
219 | } | ||
220 | |||
221 | pub fn const_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> ConstParamId { | ||
222 | assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); | ||
223 | let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); | ||
224 | db.lookup_intern_const_param_id(interned_id) | ||
225 | } | ||
226 | |||
1280 | pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { | 227 | pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { |
1281 | chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) | 228 | chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) |
1282 | } | 229 | } |
@@ -1284,3 +231,16 @@ pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { | |||
1284 | pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId { | 231 | pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId { |
1285 | salsa::InternKey::from_intern_id(id.0) | 232 | salsa::InternKey::from_intern_id(id.0) |
1286 | } | 233 | } |
234 | |||
235 | pub fn static_lifetime() -> Lifetime { | ||
236 | LifetimeData::Static.intern(&Interner) | ||
237 | } | ||
238 | |||
239 | pub fn dummy_usize_const() -> Const { | ||
240 | let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner); | ||
241 | chalk_ir::ConstData { | ||
242 | ty: usize_ty, | ||
243 | value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }), | ||
244 | } | ||
245 | .intern(&Interner) | ||
246 | } | ||