aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/utils.rs')
-rw-r--r--crates/hir_ty/src/utils.rs63
1 files changed, 39 insertions, 24 deletions
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index 42d7af146..8d5d5cd73 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -2,21 +2,23 @@
2//! query, but can't be computed directly from `*Data` (ie, which need a `db`). 2//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use chalk_ir::DebruijnIndex; 5use chalk_ir::{BoundVar, DebruijnIndex};
6use hir_def::{ 6use hir_def::{
7 adt::VariantData,
8 db::DefDatabase, 7 db::DefDatabase,
9 generics::{ 8 generics::{
10 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, 9 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
11 }, 10 },
11 intern::Interned,
12 path::Path, 12 path::Path,
13 resolver::{HasResolver, TypeNs}, 13 resolver::{HasResolver, TypeNs},
14 type_ref::TypeRef, 14 type_ref::TypeRef,
15 AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, 15 AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId,
16}; 16};
17use hir_expand::name::{name, Name}; 17use hir_expand::name::{name, Name};
18 18
19use crate::{db::HirDatabase, TraitRef, TypeWalk, WhereClause}; 19use crate::{
20 db::HirDatabase, Interner, Substitution, TraitRef, TraitRefExt, TyKind, TypeWalk, WhereClause,
21};
20 22
21fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 23fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
22 let resolver = trait_.resolver(db); 24 let resolver = trait_.resolver(db);
@@ -32,11 +34,10 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
32 .filter_map(|pred| match pred { 34 .filter_map(|pred| match pred {
33 WherePredicate::ForLifetime { target, bound, .. } 35 WherePredicate::ForLifetime { target, bound, .. }
34 | WherePredicate::TypeBound { target, bound } => match target { 36 | WherePredicate::TypeBound { target, bound } => match target {
35 WherePredicateTypeTarget::TypeRef(TypeRef::Path(p)) 37 WherePredicateTypeTarget::TypeRef(type_ref) => match &**type_ref {
36 if p == &Path::from(name![Self]) => 38 TypeRef::Path(p) if p == &Path::from(name![Self]) => bound.as_path(),
37 { 39 _ => None,
38 bound.as_path() 40 },
39 }
40 WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { 41 WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => {
41 bound.as_path() 42 bound.as_path()
42 } 43 }
@@ -66,13 +67,15 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
66 .filter_map(|pred| { 67 .filter_map(|pred| {
67 pred.as_ref().filter_map(|pred| match pred.skip_binders() { 68 pred.as_ref().filter_map(|pred| match pred.skip_binders() {
68 // FIXME: how to correctly handle higher-ranked bounds here? 69 // FIXME: how to correctly handle higher-ranked bounds here?
69 WhereClause::Implemented(tr) => { 70 WhereClause::Implemented(tr) => Some(
70 Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) 71 tr.clone()
71 } 72 .shifted_out_to(DebruijnIndex::ONE)
73 .expect("FIXME unexpected higher-ranked trait bound"),
74 ),
72 _ => None, 75 _ => None,
73 }) 76 })
74 }) 77 })
75 .map(|pred| pred.subst(&trait_ref.substitution)) 78 .map(|pred| pred.substitute(&Interner, &trait_ref.substitution))
76 .collect() 79 .collect()
77} 80}
78 81
@@ -103,6 +106,8 @@ pub(super) fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<Tra
103/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get 106/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
104/// `Self: OtherTrait<i32>`. 107/// `Self: OtherTrait<i32>`.
105pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> Vec<TraitRef> { 108pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> Vec<TraitRef> {
109 // FIXME: replace by Chalk's `super_traits`, maybe make this a query
110
106 // we need to take care a bit here to avoid infinite loops in case of cycles 111 // we need to take care a bit here to avoid infinite loops in case of cycles
107 // (i.e. if we have `trait A: B; trait B: A;`) 112 // (i.e. if we have `trait A: B; trait B: A;`)
108 let mut result = vec![trait_ref]; 113 let mut result = vec![trait_ref];
@@ -132,16 +137,6 @@ pub(super) fn associated_type_by_name_including_super_traits(
132 }) 137 })
133} 138}
134 139
135pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> {
136 match var {
137 VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
138 VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
139 VariantId::EnumVariantId(it) => {
140 db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
141 }
142 }
143}
144
145/// Helper for mutating `Arc<[T]>` (i.e. `Arc::make_mut` for Arc slices). 140/// Helper for mutating `Arc<[T]>` (i.e. `Arc::make_mut` for Arc slices).
146/// The underlying values are cloned if there are other strong references. 141/// The underlying values are cloned if there are other strong references.
147pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] { 142pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] {
@@ -159,7 +154,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
159#[derive(Debug)] 154#[derive(Debug)]
160pub(crate) struct Generics { 155pub(crate) struct Generics {
161 def: GenericDefId, 156 def: GenericDefId,
162 pub(crate) params: Arc<GenericParams>, 157 pub(crate) params: Interned<GenericParams>,
163 parent_generics: Option<Box<Generics>>, 158 parent_generics: Option<Box<Generics>>,
164} 159}
165 160
@@ -249,6 +244,26 @@ impl Generics {
249 self.parent_generics.as_ref().and_then(|g| g.find_param(param)) 244 self.parent_generics.as_ref().and_then(|g| g.find_param(param))
250 } 245 }
251 } 246 }
247
248 /// Returns a Substitution that replaces each parameter by a bound variable.
249 pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution {
250 Substitution::from_iter(
251 &Interner,
252 self.iter()
253 .enumerate()
254 .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
255 )
256 }
257
258 /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
259 pub(crate) fn type_params_subst(&self, db: &dyn HirDatabase) -> Substitution {
260 Substitution::from_iter(
261 &Interner,
262 self.iter().map(|(id, _)| {
263 TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(&Interner)
264 }),
265 )
266 }
252} 267}
253 268
254fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { 269fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> {