aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/lib.rs')
-rw-r--r--crates/hir_ty/src/lib.rs1220
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;
14pub(crate) mod infer; 14pub(crate) mod infer;
15pub(crate) mod utils; 15pub(crate) mod utils;
16mod chalk_cast; 16mod chalk_cast;
17mod chalk_ext;
18mod builder;
19mod walk;
20mod types;
17 21
18pub mod display; 22pub mod display;
19pub mod db; 23pub mod db;
@@ -24,36 +28,33 @@ mod tests;
24#[cfg(test)] 28#[cfg(test)]
25mod test_db; 29mod test_db;
26 30
27use std::{iter, mem, ops::Deref, sync::Arc}; 31use std::sync::Arc;
28 32
29use base_db::salsa; 33use base_db::salsa;
34use chalk_ir::UintTy;
30use hir_def::{ 35use 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};
34use itertools::Itertools;
35use smallvec::SmallVec;
36 39
37use crate::{ 40use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
38 db::HirDatabase,
39 display::HirDisplay,
40 utils::{generics, make_mut_slice, Generics},
41};
42 41
43pub use autoderef::autoderef; 42pub use autoderef::autoderef;
44pub use infer::{InferenceResult, InferenceVar}; 43pub use builder::TyBuilder;
44pub use chalk_ext::*;
45pub use infer::{could_unify, InferenceResult};
45pub use lower::{ 46pub 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};
49pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment}; 50pub use traits::{chalk::Interner, TraitEnvironment};
51pub use types::*;
52pub use walk::TypeWalk;
50 53
51pub use chalk_ir::{ 54pub 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
55pub use crate::traits::chalk::Interner;
56
57pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; 58pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
58pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 59pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
59pub type FnDefId = chalk_ir::FnDefId<Interner>; 60pub type FnDefId = chalk_ir::FnDefId<Interner>;
@@ -61,371 +62,26 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>;
61pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 62pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
62pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; 63pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
63 64
65pub type VariableKind = chalk_ir::VariableKind<Interner>;
66pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
64pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; 67pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
65 68
66pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 69pub type Lifetime = chalk_ir::Lifetime<Interner>;
67 70pub type LifetimeData = chalk_ir::LifetimeData<Interner>;
68#[derive(Clone, PartialEq, Eq, Debug, Hash)] 71pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;
69pub enum Lifetime {
70 Parameter(LifetimeParamId),
71 Static,
72}
73
74#[derive(Clone, PartialEq, Eq, Debug, Hash)]
75pub struct OpaqueTy {
76 pub opaque_ty_id: OpaqueTyId,
77 pub substitution: Substitution,
78}
79
80impl 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( 73pub type Const = chalk_ir::Const<Interner>;
86 &mut self, 74pub type ConstData = chalk_ir::ConstData<Interner>;
87 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 75pub type ConstValue = chalk_ir::ConstValue<Interner>;
88 binders: DebruijnIndex, 76pub 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)]
98pub struct ProjectionTy {
99 pub associated_ty_id: AssocTypeId,
100 pub substitution: Substitution,
101}
102
103impl 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 { 78pub 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
123impl 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)]
138pub struct DynTy {
139 /// The unknown self type.
140 pub bounds: Binders<QuantifiedWhereClauses>,
141}
142 79
143pub type FnSig = chalk_ir::FnSig<Interner>; 80pub type FnSig = chalk_ir::FnSig<Interner>;
144 81
145#[derive(Clone, PartialEq, Eq, Debug, Hash)] 82// FIXME: get rid of this
146pub struct FnPointer { 83pub 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)]
153pub 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
165impl 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)]
191pub 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)]
305pub struct Ty(Arc<TyKind>);
306
307impl TyKind {
308 pub fn intern(self, _interner: &Interner) -> Ty {
309 Ty(Arc::new(self))
310 }
311}
312
313impl 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)]
329pub struct Substitution(SmallVec<[Ty; 2]>);
330
331impl 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
349impl 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, &params)
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)] 92pub fn wrap_empty_binders<T>(value: T) -> Binders<T>
437pub struct SubstsBuilder { 93where
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}
442impl SubstsBuilder { 98
443 pub fn build(self) -> Substitution { 99pub 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 } 111pub 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
482impl 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)]
491pub struct Binders<T> {
492 pub num_binders: usize,
493 pub value: T,
494}
495
496impl<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
529impl<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
535impl<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
543impl<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)]
559pub struct TraitRef {
560 pub trait_id: ChalkTraitId,
561 pub substitution: Substitution,
562}
563
564impl 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
574impl 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)]
591pub 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
598impl 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
614impl 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
634pub type QuantifiedWhereClause = Binders<WhereClause>;
635
636#[derive(Debug, Clone, PartialEq, Eq, Hash)]
637pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
638
639impl 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)]
659pub struct Canonical<T> {
660 pub value: T,
661 pub binders: CanonicalVarKinds,
662}
663
664impl<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
721impl TypeWalk for CallableSig { 167impl 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
739impl 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(&parameters))
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.
1045pub 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
1155impl 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
1217impl<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)]
1235pub enum ImplTraitId { 170pub enum ImplTraitId {
@@ -1277,6 +212,18 @@ pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderI
1277 } 212 }
1278} 213}
1279 214
215pub 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
221pub 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
1280pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { 227pub 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 {
1284pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId { 231pub 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
235pub fn static_lifetime() -> Lifetime {
236 LifetimeData::Static.intern(&Interner)
237}
238
239pub 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}