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.rs48
1 files changed, 36 insertions, 12 deletions
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index 42d7af146..d11708299 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -2,13 +2,14 @@
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, 7 adt::VariantData,
8 db::DefDatabase, 8 db::DefDatabase,
9 generics::{ 9 generics::{
10 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, 10 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
11 }, 11 },
12 intern::Interned,
12 path::Path, 13 path::Path,
13 resolver::{HasResolver, TypeNs}, 14 resolver::{HasResolver, TypeNs},
14 type_ref::TypeRef, 15 type_ref::TypeRef,
@@ -16,7 +17,7 @@ use hir_def::{
16}; 17};
17use hir_expand::name::{name, Name}; 18use hir_expand::name::{name, Name};
18 19
19use crate::{db::HirDatabase, TraitRef, TypeWalk, WhereClause}; 20use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TyKind, TypeWalk, WhereClause};
20 21
21fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 22fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
22 let resolver = trait_.resolver(db); 23 let resolver = trait_.resolver(db);
@@ -32,11 +33,10 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
32 .filter_map(|pred| match pred { 33 .filter_map(|pred| match pred {
33 WherePredicate::ForLifetime { target, bound, .. } 34 WherePredicate::ForLifetime { target, bound, .. }
34 | WherePredicate::TypeBound { target, bound } => match target { 35 | WherePredicate::TypeBound { target, bound } => match target {
35 WherePredicateTypeTarget::TypeRef(TypeRef::Path(p)) 36 WherePredicateTypeTarget::TypeRef(type_ref) => match &**type_ref {
36 if p == &Path::from(name![Self]) => 37 TypeRef::Path(p) if p == &Path::from(name![Self]) => bound.as_path(),
37 { 38 _ => None,
38 bound.as_path() 39 },
39 }
40 WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { 40 WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => {
41 bound.as_path() 41 bound.as_path()
42 } 42 }
@@ -66,13 +66,15 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
66 .filter_map(|pred| { 66 .filter_map(|pred| {
67 pred.as_ref().filter_map(|pred| match pred.skip_binders() { 67 pred.as_ref().filter_map(|pred| match pred.skip_binders() {
68 // FIXME: how to correctly handle higher-ranked bounds here? 68 // FIXME: how to correctly handle higher-ranked bounds here?
69 WhereClause::Implemented(tr) => { 69 WhereClause::Implemented(tr) => Some(
70 Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) 70 tr.clone()
71 } 71 .shifted_out_to(DebruijnIndex::ONE)
72 .expect("FIXME unexpected higher-ranked trait bound"),
73 ),
72 _ => None, 74 _ => None,
73 }) 75 })
74 }) 76 })
75 .map(|pred| pred.subst(&trait_ref.substitution)) 77 .map(|pred| pred.substitute(&Interner, &trait_ref.substitution))
76 .collect() 78 .collect()
77} 79}
78 80
@@ -103,6 +105,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 105/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
104/// `Self: OtherTrait<i32>`. 106/// `Self: OtherTrait<i32>`.
105pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> Vec<TraitRef> { 107pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> Vec<TraitRef> {
108 // FIXME: replace by Chalk's `super_traits`, maybe make this a query
109
106 // we need to take care a bit here to avoid infinite loops in case of cycles 110 // 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;`) 111 // (i.e. if we have `trait A: B; trait B: A;`)
108 let mut result = vec![trait_ref]; 112 let mut result = vec![trait_ref];
@@ -159,7 +163,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
159#[derive(Debug)] 163#[derive(Debug)]
160pub(crate) struct Generics { 164pub(crate) struct Generics {
161 def: GenericDefId, 165 def: GenericDefId,
162 pub(crate) params: Arc<GenericParams>, 166 pub(crate) params: Interned<GenericParams>,
163 parent_generics: Option<Box<Generics>>, 167 parent_generics: Option<Box<Generics>>,
164} 168}
165 169
@@ -249,6 +253,26 @@ impl Generics {
249 self.parent_generics.as_ref().and_then(|g| g.find_param(param)) 253 self.parent_generics.as_ref().and_then(|g| g.find_param(param))
250 } 254 }
251 } 255 }
256
257 /// Returns a Substitution that replaces each parameter by a bound variable.
258 pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution {
259 Substitution::from_iter(
260 &Interner,
261 self.iter()
262 .enumerate()
263 .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
264 )
265 }
266
267 /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
268 pub(crate) fn type_params_subst(&self, db: &dyn HirDatabase) -> Substitution {
269 Substitution::from_iter(
270 &Interner,
271 self.iter().map(|(id, _)| {
272 TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(&Interner)
273 }),
274 )
275 }
252} 276}
253 277
254fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { 278fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> {