]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/lib.rs
Add lowering of array lengths in types
[rust.git] / crates / hir_ty / src / lib.rs
1 //! The type system. We currently use this to infer types for completion, hover
2 //! information and various assists.
3
4 #[allow(unused)]
5 macro_rules! eprintln {
6     ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
7 }
8
9 mod autoderef;
10 mod builder;
11 mod chalk_db;
12 mod chalk_ext;
13 mod infer;
14 mod interner;
15 mod lower;
16 mod mapping;
17 mod op;
18 mod tls;
19 mod utils;
20 mod walk;
21 pub mod db;
22 pub mod diagnostics;
23 pub mod display;
24 pub mod method_resolution;
25 pub mod primitive;
26 pub mod traits;
27
28 #[cfg(test)]
29 mod tests;
30 #[cfg(test)]
31 mod test_db;
32
33 use std::sync::Arc;
34
35 use chalk_ir::{
36     fold::{Fold, Shift},
37     interner::HasInterner,
38     UintTy,
39 };
40 use hir_def::{
41     expr::ExprId,
42     type_ref::{ConstScalar, Rawness},
43     TypeParamId,
44 };
45
46 use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
47
48 pub use autoderef::autoderef;
49 pub use builder::TyBuilder;
50 pub use chalk_ext::*;
51 pub use infer::{could_unify, InferenceResult};
52 pub use interner::Interner;
53 pub use lower::{
54     associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
55     TyDefId, TyLoweringContext, ValueTyDefId,
56 };
57 pub use mapping::{
58     const_from_placeholder_idx, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
59     from_placeholder_idx, lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
60     to_foreign_def_id, to_placeholder_idx,
61 };
62 pub use traits::TraitEnvironment;
63 pub use utils::all_super_traits;
64 pub use walk::TypeWalk;
65
66 pub use chalk_ir::{
67     cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
68 };
69
70 pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
71 pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
72 pub type FnDefId = chalk_ir::FnDefId<Interner>;
73 pub type ClosureId = chalk_ir::ClosureId<Interner>;
74 pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
75 pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
76
77 pub type VariableKind = chalk_ir::VariableKind<Interner>;
78 pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
79 pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
80 pub type Binders<T> = chalk_ir::Binders<T>;
81 pub type Substitution = chalk_ir::Substitution<Interner>;
82 pub type GenericArg = chalk_ir::GenericArg<Interner>;
83 pub type GenericArgData = chalk_ir::GenericArgData<Interner>;
84
85 pub type Ty = chalk_ir::Ty<Interner>;
86 pub type TyKind = chalk_ir::TyKind<Interner>;
87 pub type DynTy = chalk_ir::DynTy<Interner>;
88 pub type FnPointer = chalk_ir::FnPointer<Interner>;
89 // pub type FnSubst = chalk_ir::FnSubst<Interner>;
90 pub use chalk_ir::FnSubst;
91 pub type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
92 pub type AliasTy = chalk_ir::AliasTy<Interner>;
93 pub type OpaqueTy = chalk_ir::OpaqueTy<Interner>;
94 pub type InferenceVar = chalk_ir::InferenceVar;
95
96 pub type Lifetime = chalk_ir::Lifetime<Interner>;
97 pub type LifetimeData = chalk_ir::LifetimeData<Interner>;
98 pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;
99
100 pub type Const = chalk_ir::Const<Interner>;
101 pub type ConstData = chalk_ir::ConstData<Interner>;
102 pub type ConstValue = chalk_ir::ConstValue<Interner>;
103 pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>;
104
105 pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
106 pub type TraitRef = chalk_ir::TraitRef<Interner>;
107 pub type QuantifiedWhereClause = Binders<WhereClause>;
108 pub type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>;
109 pub type Canonical<T> = chalk_ir::Canonical<T>;
110
111 pub type FnSig = chalk_ir::FnSig<Interner>;
112
113 pub type InEnvironment<T> = chalk_ir::InEnvironment<T>;
114 pub type DomainGoal = chalk_ir::DomainGoal<Interner>;
115 pub type AliasEq = chalk_ir::AliasEq<Interner>;
116 pub type Solution = chalk_solve::Solution<Interner>;
117 pub type ConstrainedSubst = chalk_ir::ConstrainedSubst<Interner>;
118 pub type Guidance = chalk_solve::Guidance<Interner>;
119 pub type WhereClause = chalk_ir::WhereClause<Interner>;
120
121 // FIXME: get rid of this
122 pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
123     Substitution::from_iter(
124         &Interner,
125         s.as_slice(&Interner)[..std::cmp::min(s.len(&Interner), n)].iter().cloned(),
126     )
127 }
128
129 /// Return an index of a parameter in the generic type parameter list by it's id.
130 pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
131     generics(db.upcast(), id.parent).param_idx(id)
132 }
133
134 pub(crate) fn wrap_empty_binders<T>(value: T) -> Binders<T>
135 where
136     T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>,
137 {
138     Binders::empty(&Interner, value.shifted_in_from(&Interner, DebruijnIndex::ONE))
139 }
140
141 pub(crate) fn make_only_type_binders<T: HasInterner<Interner = Interner>>(
142     num_vars: usize,
143     value: T,
144 ) -> Binders<T> {
145     Binders::new(
146         VariableKinds::from_iter(
147             &Interner,
148             std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
149                 .take(num_vars),
150         ),
151         value,
152     )
153 }
154
155 // FIXME: get rid of this
156 pub fn make_canonical<T: HasInterner<Interner = Interner>>(
157     value: T,
158     kinds: impl IntoIterator<Item = TyVariableKind>,
159 ) -> Canonical<T> {
160     let kinds = kinds.into_iter().map(|tk| {
161         chalk_ir::CanonicalVarKind::new(
162             chalk_ir::VariableKind::Ty(tk),
163             chalk_ir::UniverseIndex::ROOT,
164         )
165     });
166     Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
167 }
168
169 /// A function signature as seen by type inference: Several parameter types and
170 /// one return type.
171 #[derive(Clone, PartialEq, Eq, Debug)]
172 pub struct CallableSig {
173     params_and_return: Arc<[Ty]>,
174     is_varargs: bool,
175 }
176
177 has_interner!(CallableSig);
178
179 /// A polymorphic function signature.
180 pub type PolyFnSig = Binders<CallableSig>;
181
182 impl CallableSig {
183     pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> CallableSig {
184         params.push(ret);
185         CallableSig { params_and_return: params.into(), is_varargs }
186     }
187
188     pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
189         CallableSig {
190             // FIXME: what to do about lifetime params? -> return PolyFnSig
191             params_and_return: fn_ptr
192                 .substitution
193                 .clone()
194                 .shifted_out_to(&Interner, DebruijnIndex::ONE)
195                 .expect("unexpected lifetime vars in fn ptr")
196                 .0
197                 .as_slice(&Interner)
198                 .iter()
199                 .map(|arg| arg.assert_ty_ref(&Interner).clone())
200                 .collect(),
201             is_varargs: fn_ptr.sig.variadic,
202         }
203     }
204
205     pub fn params(&self) -> &[Ty] {
206         &self.params_and_return[0..self.params_and_return.len() - 1]
207     }
208
209     pub fn ret(&self) -> &Ty {
210         &self.params_and_return[self.params_and_return.len() - 1]
211     }
212 }
213
214 impl Fold<Interner> for CallableSig {
215     type Result = CallableSig;
216
217     fn fold_with<'i>(
218         self,
219         folder: &mut dyn chalk_ir::fold::Folder<'i, Interner>,
220         outer_binder: DebruijnIndex,
221     ) -> chalk_ir::Fallible<Self::Result>
222     where
223         Interner: 'i,
224     {
225         let vec = self.params_and_return.to_vec();
226         let folded = vec.fold_with(folder, outer_binder)?;
227         Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
228     }
229 }
230
231 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
232 pub enum ImplTraitId {
233     ReturnTypeImplTrait(hir_def::FunctionId, u16),
234     AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
235 }
236
237 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
238 pub struct ReturnTypeImplTraits {
239     pub(crate) impl_traits: Vec<ReturnTypeImplTrait>,
240 }
241
242 has_interner!(ReturnTypeImplTraits);
243
244 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
245 pub(crate) struct ReturnTypeImplTrait {
246     pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
247 }
248
249 pub fn static_lifetime() -> Lifetime {
250     LifetimeData::Static.intern(&Interner)
251 }
252
253 pub fn dummy_usize_const() -> Const {
254     let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
255     chalk_ir::ConstData {
256         ty: usize_ty,
257         value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
258             interned: ConstScalar::Unknown,
259         }),
260     }
261     .intern(&Interner)
262 }
263
264 pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + Fold<Interner>>(
265     t: T,
266     f: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
267 ) -> T::Result {
268     use chalk_ir::{fold::Folder, Fallible};
269     struct FreeVarFolder<F>(F);
270     impl<'i, F: FnMut(BoundVar, DebruijnIndex) -> Ty + 'i> Folder<'i, Interner> for FreeVarFolder<F> {
271         fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
272             self
273         }
274
275         fn interner(&self) -> &'i Interner {
276             &Interner
277         }
278
279         fn fold_free_var_ty(
280             &mut self,
281             bound_var: BoundVar,
282             outer_binder: DebruijnIndex,
283         ) -> Fallible<Ty> {
284             Ok(self.0(bound_var, outer_binder))
285         }
286     }
287     t.fold_with(&mut FreeVarFolder(f), DebruijnIndex::INNERMOST).expect("fold failed unexpectedly")
288 }
289
290 pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + Fold<Interner>>(
291     t: T,
292     f: impl FnMut(Ty, DebruijnIndex) -> Ty,
293     binders: DebruijnIndex,
294 ) -> T::Result {
295     use chalk_ir::{
296         fold::{Folder, SuperFold},
297         Fallible,
298     };
299     struct TyFolder<F>(F);
300     impl<'i, F: FnMut(Ty, DebruijnIndex) -> Ty + 'i> Folder<'i, Interner> for TyFolder<F> {
301         fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
302             self
303         }
304
305         fn interner(&self) -> &'i Interner {
306             &Interner
307         }
308
309         fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
310             let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?;
311             Ok(self.0(ty, outer_binder))
312         }
313     }
314     t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly")
315 }