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.rs53
1 files changed, 18 insertions, 35 deletions
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index b23e91b1b..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`).
3use std::sync::Arc;
4 3
5use chalk_ir::{BoundVar, DebruijnIndex}; 4use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex};
6use hir_def::{ 5use 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};
17use hir_expand::name::{name, Name}; 16use hir_expand::name::{name, Name};
18 17
19use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TyKind, TypeWalk, WhereClause}; 18use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TraitRefExt, TyKind, WhereClause};
20 19
21fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 20fn 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).
81pub(super) fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 81pub 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>`.
105pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> Vec<TraitRef> { 105pub(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
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).
146/// 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] {
148 if Arc::get_mut(a).is_none() {
149 *a = a.iter().cloned().collect();
150 }
151 Arc::get_mut(a).unwrap()
152}
153
154pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { 137pub(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)]
160pub(crate) struct Generics { 143pub(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