diff options
Diffstat (limited to 'crates/hir_ty/src/utils.rs')
-rw-r--r-- | crates/hir_ty/src/utils.rs | 73 |
1 files changed, 38 insertions, 35 deletions
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index 42d7af146..2f04ee57a 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs | |||
@@ -1,22 +1,21 @@ | |||
1 | //! Helper functions for working with def, which don't need to be a separate | 1 | //! Helper functions for working with def, which don't need to be a separate |
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`). |
3 | use std::sync::Arc; | ||
4 | 3 | ||
5 | use chalk_ir::DebruijnIndex; | 4 | use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex}; |
6 | use hir_def::{ | 5 | use hir_def::{ |
7 | adt::VariantData, | ||
8 | db::DefDatabase, | 6 | db::DefDatabase, |
9 | generics::{ | 7 | generics::{ |
10 | GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, | 8 | GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, |
11 | }, | 9 | }, |
10 | intern::Interned, | ||
12 | path::Path, | 11 | path::Path, |
13 | resolver::{HasResolver, TypeNs}, | 12 | resolver::{HasResolver, TypeNs}, |
14 | type_ref::TypeRef, | 13 | type_ref::TypeRef, |
15 | AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, | 14 | AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, |
16 | }; | 15 | }; |
17 | use hir_expand::name::{name, Name}; | 16 | use hir_expand::name::{name, Name}; |
18 | 17 | ||
19 | use crate::{db::HirDatabase, TraitRef, TypeWalk, WhereClause}; | 18 | use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TraitRefExt, TyKind, WhereClause}; |
20 | 19 | ||
21 | fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | 20 | fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { |
22 | let resolver = trait_.resolver(db); | 21 | let resolver = trait_.resolver(db); |
@@ -32,11 +31,10 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | |||
32 | .filter_map(|pred| match pred { | 31 | .filter_map(|pred| match pred { |
33 | WherePredicate::ForLifetime { target, bound, .. } | 32 | WherePredicate::ForLifetime { target, bound, .. } |
34 | | WherePredicate::TypeBound { target, bound } => match target { | 33 | | WherePredicate::TypeBound { target, bound } => match target { |
35 | WherePredicateTypeTarget::TypeRef(TypeRef::Path(p)) | 34 | WherePredicateTypeTarget::TypeRef(type_ref) => match &**type_ref { |
36 | if p == &Path::from(name![Self]) => | 35 | TypeRef::Path(p) if p == &Path::from(name![Self]) => bound.as_path(), |
37 | { | 36 | _ => None, |
38 | bound.as_path() | 37 | }, |
39 | } | ||
40 | WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { | 38 | WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { |
41 | bound.as_path() | 39 | bound.as_path() |
42 | } | 40 | } |
@@ -66,19 +64,21 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr | |||
66 | .filter_map(|pred| { | 64 | .filter_map(|pred| { |
67 | pred.as_ref().filter_map(|pred| match pred.skip_binders() { | 65 | pred.as_ref().filter_map(|pred| match pred.skip_binders() { |
68 | // FIXME: how to correctly handle higher-ranked bounds here? | 66 | // FIXME: how to correctly handle higher-ranked bounds here? |
69 | WhereClause::Implemented(tr) => { | 67 | WhereClause::Implemented(tr) => Some( |
70 | Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) | 68 | tr.clone() |
71 | } | 69 | .shifted_out_to(&Interner, DebruijnIndex::ONE) |
70 | .expect("FIXME unexpected higher-ranked trait bound"), | ||
71 | ), | ||
72 | _ => None, | 72 | _ => None, |
73 | }) | 73 | }) |
74 | }) | 74 | }) |
75 | .map(|pred| pred.subst(&trait_ref.substitution)) | 75 | .map(|pred| pred.substitute(&Interner, &trait_ref.substitution)) |
76 | .collect() | 76 | .collect() |
77 | } | 77 | } |
78 | 78 | ||
79 | /// Returns an iterator over the whole super trait hierarchy (including the | 79 | /// Returns an iterator over the whole super trait hierarchy (including the |
80 | /// trait itself). | 80 | /// trait itself). |
81 | pub(super) fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | 81 | pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { |
82 | // we need to take care a bit here to avoid infinite loops in case of cycles | 82 | // we need to take care a bit here to avoid infinite loops in case of cycles |
83 | // (i.e. if we have `trait A: B; trait B: A;`) | 83 | // (i.e. if we have `trait A: B; trait B: A;`) |
84 | let mut result = vec![trait_]; | 84 | let mut result = vec![trait_]; |
@@ -103,6 +103,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 | 103 | /// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get |
104 | /// `Self: OtherTrait<i32>`. | 104 | /// `Self: OtherTrait<i32>`. |
105 | pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> Vec<TraitRef> { | 105 | pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> Vec<TraitRef> { |
106 | // FIXME: replace by Chalk's `super_traits`, maybe make this a query | ||
107 | |||
106 | // we need to take care a bit here to avoid infinite loops in case of cycles | 108 | // 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;`) | 109 | // (i.e. if we have `trait A: B; trait B: A;`) |
108 | let mut result = vec![trait_ref]; | 110 | let mut result = vec![trait_ref]; |
@@ -132,25 +134,6 @@ pub(super) fn associated_type_by_name_including_super_traits( | |||
132 | }) | 134 | }) |
133 | } | 135 | } |
134 | 136 | ||
135 | pub(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). | ||
146 | /// The underlying values are cloned if there are other strong references. | ||
147 | pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] { | ||
148 | if Arc::get_mut(a).is_none() { | ||
149 | *a = a.iter().cloned().collect(); | ||
150 | } | ||
151 | Arc::get_mut(a).unwrap() | ||
152 | } | ||
153 | |||
154 | pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { | 137 | pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { |
155 | let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def))); | 138 | let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def))); |
156 | Generics { def, params: db.generic_params(def), parent_generics } | 139 | Generics { def, params: db.generic_params(def), parent_generics } |
@@ -159,7 +142,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { | |||
159 | #[derive(Debug)] | 142 | #[derive(Debug)] |
160 | pub(crate) struct Generics { | 143 | pub(crate) struct Generics { |
161 | def: GenericDefId, | 144 | def: GenericDefId, |
162 | pub(crate) params: Arc<GenericParams>, | 145 | pub(crate) params: Interned<GenericParams>, |
163 | parent_generics: Option<Box<Generics>>, | 146 | parent_generics: Option<Box<Generics>>, |
164 | } | 147 | } |
165 | 148 | ||
@@ -249,6 +232,26 @@ impl Generics { | |||
249 | self.parent_generics.as_ref().and_then(|g| g.find_param(param)) | 232 | self.parent_generics.as_ref().and_then(|g| g.find_param(param)) |
250 | } | 233 | } |
251 | } | 234 | } |
235 | |||
236 | /// Returns a Substitution that replaces each parameter by a bound variable. | ||
237 | pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution { | ||
238 | Substitution::from_iter( | ||
239 | &Interner, | ||
240 | self.iter() | ||
241 | .enumerate() | ||
242 | .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), | ||
243 | ) | ||
244 | } | ||
245 | |||
246 | /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`). | ||
247 | pub(crate) fn type_params_subst(&self, db: &dyn HirDatabase) -> Substitution { | ||
248 | Substitution::from_iter( | ||
249 | &Interner, | ||
250 | self.iter().map(|(id, _)| { | ||
251 | TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(&Interner) | ||
252 | }), | ||
253 | ) | ||
254 | } | ||
252 | } | 255 | } |
253 | 256 | ||
254 | fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { | 257 | fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { |