diff options
Diffstat (limited to 'crates/hir_ty/src/lib.rs')
-rw-r--r-- | crates/hir_ty/src/lib.rs | 237 |
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 | ||
31 | use std::sync::Arc; | 31 | use std::sync::Arc; |
32 | 32 | ||
33 | use itertools::Itertools; | ||
34 | |||
35 | use base_db::salsa; | 33 | use base_db::salsa; |
34 | use chalk_ir::UintTy; | ||
36 | use hir_def::{ | 35 | use 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 | ||
41 | use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; | 40 | use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; |
@@ -71,6 +70,11 @@ pub type Lifetime = chalk_ir::Lifetime<Interner>; | |||
71 | pub type LifetimeData = chalk_ir::LifetimeData<Interner>; | 70 | pub type LifetimeData = chalk_ir::LifetimeData<Interner>; |
72 | pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>; | 71 | pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>; |
73 | 72 | ||
73 | pub type Const = chalk_ir::Const<Interner>; | ||
74 | pub type ConstData = chalk_ir::ConstData<Interner>; | ||
75 | pub type ConstValue = chalk_ir::ConstValue<Interner>; | ||
76 | pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>; | ||
77 | |||
74 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | 78 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; |
75 | 79 | ||
76 | pub type FnSig = chalk_ir::FnSig<Interner>; | 80 | pub type FnSig = chalk_ir::FnSig<Interner>; |
@@ -165,69 +169,12 @@ impl CallableSig { | |||
165 | } | 169 | } |
166 | 170 | ||
167 | impl Ty { | 171 | impl 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, ¶meters)) | ||
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 | ||
291 | pub 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 | |||
491 | pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { | 297 | pub 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 { | |||
499 | pub fn static_lifetime() -> Lifetime { | 305 | pub fn static_lifetime() -> Lifetime { |
500 | LifetimeData::Static.intern(&Interner) | 306 | LifetimeData::Static.intern(&Interner) |
501 | } | 307 | } |
308 | |||
309 | pub 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 | } | ||