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.rs237
1 files changed, 26 insertions, 211 deletions
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index bccc73449..f5b658cba 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -30,12 +30,11 @@ mod test_db;
30 30
31use std::sync::Arc; 31use std::sync::Arc;
32 32
33use itertools::Itertools;
34
35use base_db::salsa; 33use base_db::salsa;
34use chalk_ir::UintTy;
36use hir_def::{ 35use hir_def::{
37 expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, 36 expr::ExprId, type_ref::Rawness, ConstParamId, LifetimeParamId, TraitId, TypeAliasId,
38 LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, 37 TypeParamId,
39}; 38};
40 39
41use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; 40use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
@@ -71,6 +70,11 @@ pub type Lifetime = chalk_ir::Lifetime<Interner>;
71pub type LifetimeData = chalk_ir::LifetimeData<Interner>; 70pub type LifetimeData = chalk_ir::LifetimeData<Interner>;
72pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>; 71pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;
73 72
73pub type Const = chalk_ir::Const<Interner>;
74pub type ConstData = chalk_ir::ConstData<Interner>;
75pub type ConstValue = chalk_ir::ConstValue<Interner>;
76pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>;
77
74pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 78pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
75 79
76pub type FnSig = chalk_ir::FnSig<Interner>; 80pub type FnSig = chalk_ir::FnSig<Interner>;
@@ -165,69 +169,12 @@ impl CallableSig {
165} 169}
166 170
167impl Ty { 171impl Ty {
168 pub fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
169 match self.kind(&Interner) {
170 TyKind::Ref(mutability, lifetime, ty) => Some((ty, *lifetime, *mutability)),
171 _ => None,
172 }
173 }
174
175 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
176 match self.kind(&Interner) {
177 TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)),
178 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
179 _ => None,
180 }
181 }
182
183 pub fn strip_references(&self) -> &Ty {
184 let mut t: &Ty = self;
185
186 while let TyKind::Ref(_mutability, _lifetime, ty) = t.kind(&Interner) {
187 t = ty;
188 }
189
190 t
191 }
192
193 pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
194 match self.kind(&Interner) {
195 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
196 _ => None,
197 }
198 }
199
200 pub fn as_tuple(&self) -> Option<&Substitution> {
201 match self.kind(&Interner) {
202 TyKind::Tuple(_, substs) => Some(substs),
203 _ => None,
204 }
205 }
206
207 pub fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
208 match *self.kind(&Interner) {
209 TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
210 TyKind::FnDef(callable, ..) => {
211 Some(db.lookup_intern_callable_def(callable.into()).into())
212 }
213 TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
214 TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
215 _ => None,
216 }
217 }
218
219 pub fn is_never(&self) -> bool {
220 matches!(self.kind(&Interner), TyKind::Never)
221 }
222
223 pub fn is_unknown(&self) -> bool {
224 matches!(self.kind(&Interner), TyKind::Error)
225 }
226
227 pub fn equals_ctor(&self, other: &Ty) -> bool { 172 pub fn equals_ctor(&self, other: &Ty) -> bool {
228 match (self.kind(&Interner), other.kind(&Interner)) { 173 match (self.kind(&Interner), other.kind(&Interner)) {
229 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2, 174 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
230 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_), TyKind::Array(_)) => true, 175 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => {
176 true
177 }
231 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2, 178 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
232 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2, 179 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
233 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => { 180 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => {
@@ -252,24 +199,6 @@ impl Ty {
252 } 199 }
253 } 200 }
254 201
255 /// If this is a `dyn Trait` type, this returns the `Trait` part.
256 fn dyn_trait_ref(&self) -> Option<&TraitRef> {
257 match self.kind(&Interner) {
258 TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
259 match b.skip_binders() {
260 WhereClause::Implemented(trait_ref) => Some(trait_ref),
261 _ => None,
262 }
263 }),
264 _ => None,
265 }
266 }
267
268 /// If this is a `dyn Trait`, returns that trait.
269 pub fn dyn_trait(&self) -> Option<TraitId> {
270 self.dyn_trait_ref().map(|it| it.trait_id).map(from_chalk_trait_id)
271 }
272
273 fn builtin_deref(&self) -> Option<Ty> { 202 fn builtin_deref(&self) -> Option<Ty> {
274 match self.kind(&Interner) { 203 match self.kind(&Interner) {
275 TyKind::Ref(.., ty) => Some(ty.clone()), 204 TyKind::Ref(.., ty) => Some(ty.clone()),
@@ -278,37 +207,6 @@ impl Ty {
278 } 207 }
279 } 208 }
280 209
281 pub fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
282 match self.kind(&Interner) {
283 &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
284 _ => None,
285 }
286 }
287
288 pub fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
289 if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) {
290 Some(func)
291 } else {
292 None
293 }
294 }
295
296 pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
297 match self.kind(&Interner) {
298 TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
299 TyKind::FnDef(def, parameters) => {
300 let callable_def = db.lookup_intern_callable_def((*def).into());
301 let sig = db.callable_item_signature(callable_def);
302 Some(sig.substitute(&Interner, &parameters))
303 }
304 TyKind::Closure(.., substs) => {
305 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner);
306 sig_param.callable_sig(db)
307 }
308 _ => None,
309 }
310 }
311
312 /// Returns the type parameters of this type if it has some (i.e. is an ADT 210 /// Returns the type parameters of this type if it has some (i.e. is an ADT
313 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 211 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
314 pub fn substs(&self) -> Option<&Substitution> { 212 pub fn substs(&self) -> Option<&Substitution> {
@@ -336,104 +234,6 @@ impl Ty {
336 _ => None, 234 _ => None,
337 } 235 }
338 } 236 }
339
340 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
341 match self.kind(&Interner) {
342 TyKind::OpaqueType(opaque_ty_id, ..) => {
343 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
344 ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
345 let krate = def.module(db.upcast()).krate();
346 if let Some(future_trait) = db
347 .lang_item(krate, "future_trait".into())
348 .and_then(|item| item.as_trait())
349 {
350 // This is only used by type walking.
351 // Parameters will be walked outside, and projection predicate is not used.
352 // So just provide the Future trait.
353 let impl_bound = Binders::empty(
354 &Interner,
355 WhereClause::Implemented(TraitRef {
356 trait_id: to_chalk_trait_id(future_trait),
357 substitution: Substitution::empty(&Interner),
358 }),
359 );
360 Some(vec![impl_bound])
361 } else {
362 None
363 }
364 }
365 ImplTraitId::ReturnTypeImplTrait(..) => None,
366 }
367 }
368 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
369 let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
370 {
371 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
372 db.return_type_impl_traits(func).map(|it| {
373 let data = (*it)
374 .as_ref()
375 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
376 data.substitute(&Interner, &opaque_ty.substitution)
377 })
378 }
379 // It always has an parameter for Future::Output type.
380 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
381 };
382
383 predicates.map(|it| it.into_value_and_skipped_binders().0)
384 }
385 TyKind::Placeholder(idx) => {
386 let id = from_placeholder_idx(db, *idx);
387 let generic_params = db.generic_params(id.parent);
388 let param_data = &generic_params.types[id.local_id];
389 match param_data.provenance {
390 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
391 let substs = TyBuilder::type_params_subst(db, id.parent);
392 let predicates = db
393 .generic_predicates(id.parent)
394 .into_iter()
395 .map(|pred| pred.clone().substitute(&Interner, &substs))
396 .filter(|wc| match &wc.skip_binders() {
397 WhereClause::Implemented(tr) => {
398 tr.self_type_parameter(&Interner) == self
399 }
400 WhereClause::AliasEq(AliasEq {
401 alias: AliasTy::Projection(proj),
402 ty: _,
403 }) => proj.self_type_parameter(&Interner) == self,
404 _ => false,
405 })
406 .collect_vec();
407
408 Some(predicates)
409 }
410 _ => None,
411 }
412 }
413 _ => None,
414 }
415 }
416
417 pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
418 match self.kind(&Interner) {
419 TyKind::AssociatedType(id, ..) => {
420 match from_assoc_type_id(*id).lookup(db.upcast()).container {
421 AssocContainerId::TraitId(trait_id) => Some(trait_id),
422 _ => None,
423 }
424 }
425 TyKind::Alias(AliasTy::Projection(projection_ty)) => {
426 match from_assoc_type_id(projection_ty.associated_ty_id)
427 .lookup(db.upcast())
428 .container
429 {
430 AssocContainerId::TraitId(trait_id) => Some(trait_id),
431 _ => None,
432 }
433 }
434 _ => None,
435 }
436 }
437} 237}
438 238
439#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] 239#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
@@ -488,6 +288,12 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L
488 db.lookup_intern_lifetime_param_id(interned_id) 288 db.lookup_intern_lifetime_param_id(interned_id)
489} 289}
490 290
291pub fn const_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> ConstParamId {
292 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
293 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
294 db.lookup_intern_const_param_id(interned_id)
295}
296
491pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { 297pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
492 chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) 298 chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
493} 299}
@@ -499,3 +305,12 @@ pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId {
499pub fn static_lifetime() -> Lifetime { 305pub fn static_lifetime() -> Lifetime {
500 LifetimeData::Static.intern(&Interner) 306 LifetimeData::Static.intern(&Interner)
501} 307}
308
309pub fn dummy_usize_const() -> Const {
310 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
311 chalk_ir::ConstData {
312 ty: usize_ty,
313 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
314 }
315 .intern(&Interner)
316}