diff options
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 49 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 101 | ||||
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_path.rs | 2 |
6 files changed, 85 insertions, 77 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index b4b47057d..54da937ea 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -28,7 +28,8 @@ use crate::{ | |||
28 | expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, | 28 | expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, |
29 | ty::display::HirFormatter, | 29 | ty::display::HirFormatter, |
30 | ty::{ | 30 | ty::{ |
31 | self, InEnvironment, InferenceResult, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, | 31 | self, InEnvironment, InferenceResult, TraitEnvironment, TraitRef, Ty, TyDefId, TypeCtor, |
32 | TypeWalk, | ||
32 | }, | 33 | }, |
33 | CallableDef, Either, HirDisplay, Name, Source, | 34 | CallableDef, Either, HirDisplay, Name, Source, |
34 | }; | 35 | }; |
@@ -498,12 +499,9 @@ impl Adt { | |||
498 | let subst = db.generic_defaults(self.into()); | 499 | let subst = db.generic_defaults(self.into()); |
499 | subst.iter().any(|ty| ty == &Ty::Unknown) | 500 | subst.iter().any(|ty| ty == &Ty::Unknown) |
500 | } | 501 | } |
501 | pub fn ty(self, db: &impl HirDatabase) -> Ty { | 502 | pub fn ty(self, db: &impl HirDatabase) -> Type { |
502 | match self { | 503 | let id = AdtId::from(self); |
503 | Adt::Struct(it) => it.ty(db), | 504 | Type::from_def(db, id.module(db).krate, id) |
504 | Adt::Union(it) => it.ty(db), | ||
505 | Adt::Enum(it) => it.ty(db), | ||
506 | } | ||
507 | } | 505 | } |
508 | 506 | ||
509 | pub fn module(self, db: &impl DefDatabase) -> Module { | 507 | pub fn module(self, db: &impl DefDatabase) -> Module { |
@@ -795,8 +793,8 @@ impl TypeAlias { | |||
795 | db.type_alias_data(self.id).type_ref.clone() | 793 | db.type_alias_data(self.id).type_ref.clone() |
796 | } | 794 | } |
797 | 795 | ||
798 | pub fn ty(self, db: &impl HirDatabase) -> Ty { | 796 | pub fn ty(self, db: &impl HirDatabase) -> Type { |
799 | db.ty(self.id.into()) | 797 | Type::from_def(db, self.id.lookup(db).module(db).krate, self.id) |
800 | } | 798 | } |
801 | 799 | ||
802 | pub fn name(self, db: &impl DefDatabase) -> Name { | 800 | pub fn name(self, db: &impl DefDatabase) -> Name { |
@@ -989,6 +987,17 @@ pub struct Type { | |||
989 | } | 987 | } |
990 | 988 | ||
991 | impl Type { | 989 | impl Type { |
990 | fn from_def( | ||
991 | db: &impl HirDatabase, | ||
992 | krate: CrateId, | ||
993 | def: impl HasResolver + Into<TyDefId>, | ||
994 | ) -> Type { | ||
995 | let resolver = def.resolver(db); | ||
996 | let environment = TraitEnvironment::lower(db, &resolver); | ||
997 | let ty = db.ty(def.into()); | ||
998 | Type { krate, ty: InEnvironment { value: ty, environment } } | ||
999 | } | ||
1000 | |||
992 | pub fn is_bool(&self) -> bool { | 1001 | pub fn is_bool(&self) -> bool { |
993 | match &self.ty.value { | 1002 | match &self.ty.value { |
994 | Ty::Apply(a_ty) => match a_ty.ctor { | 1003 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -1097,6 +1106,28 @@ impl Type { | |||
1097 | .map(move |ty| self.derived(ty)) | 1106 | .map(move |ty| self.derived(ty)) |
1098 | } | 1107 | } |
1099 | 1108 | ||
1109 | // This would be nicer if it just returned an iterator, but that runs into | ||
1110 | // lifetime problems, because we need to borrow temp `CrateImplBlocks`. | ||
1111 | pub fn iterate_impl_items<T>( | ||
1112 | self, | ||
1113 | db: &impl HirDatabase, | ||
1114 | krate: Crate, | ||
1115 | mut callback: impl FnMut(AssocItem) -> Option<T>, | ||
1116 | ) -> Option<T> { | ||
1117 | for krate in self.ty.value.def_crates(db, krate.crate_id)? { | ||
1118 | let impls = db.impls_in_crate(krate); | ||
1119 | |||
1120 | for impl_block in impls.lookup_impl_blocks(&self.ty.value) { | ||
1121 | for &item in db.impl_data(impl_block).items.iter() { | ||
1122 | if let Some(result) = callback(item.into()) { | ||
1123 | return Some(result); | ||
1124 | } | ||
1125 | } | ||
1126 | } | ||
1127 | } | ||
1128 | None | ||
1129 | } | ||
1130 | |||
1100 | // FIXME: remove | 1131 | // FIXME: remove |
1101 | pub fn into_ty(self) -> Ty { | 1132 | pub fn into_ty(self) -> Ty { |
1102 | self.ty.value | 1133 | self.ty.value |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 7c4ebd4b4..9f3e6c43f 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -389,14 +389,14 @@ impl SourceAnalyzer { | |||
389 | pub fn iterate_path_candidates<T>( | 389 | pub fn iterate_path_candidates<T>( |
390 | &self, | 390 | &self, |
391 | db: &impl HirDatabase, | 391 | db: &impl HirDatabase, |
392 | ty: Ty, | 392 | ty: &Type, |
393 | name: Option<&Name>, | 393 | name: Option<&Name>, |
394 | callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | 394 | callback: impl FnMut(&Ty, AssocItem) -> Option<T>, |
395 | ) -> Option<T> { | 395 | ) -> Option<T> { |
396 | // There should be no inference vars in types passed here | 396 | // There should be no inference vars in types passed here |
397 | // FIXME check that? | 397 | // FIXME check that? |
398 | // FIXME replace Unknown by bound vars here | 398 | // FIXME replace Unknown by bound vars here |
399 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 399 | let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 }; |
400 | method_resolution::iterate_method_candidates( | 400 | method_resolution::iterate_method_candidates( |
401 | &canonical, | 401 | &canonical, |
402 | db, | 402 | db, |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 709492d21..1c0f71adc 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -189,7 +189,7 @@ impl Ty { | |||
189 | Ty::Param { idx, name } | 189 | Ty::Param { idx, name } |
190 | } | 190 | } |
191 | TypeNs::SelfType(impl_block) => ImplBlock::from(impl_block).target_ty(db), | 191 | TypeNs::SelfType(impl_block) => ImplBlock::from(impl_block).target_ty(db), |
192 | TypeNs::AdtSelfType(adt) => Adt::from(adt).ty(db), | 192 | TypeNs::AdtSelfType(adt) => db.ty(adt.into()), |
193 | 193 | ||
194 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), | 194 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), |
195 | TypeNs::BuiltinType(it) => { | 195 | TypeNs::BuiltinType(it) => { |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index fdc87a28d..92645e2a5 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -97,14 +97,15 @@ impl CrateImplBlocks { | |||
97 | } | 97 | } |
98 | } | 98 | } |
99 | 99 | ||
100 | fn def_crates( | 100 | impl Ty { |
101 | db: &impl HirDatabase, | 101 | pub(crate) fn def_crates( |
102 | cur_crate: CrateId, | 102 | &self, |
103 | ty: &Ty, | 103 | db: &impl HirDatabase, |
104 | ) -> Option<ArrayVec<[CrateId; 2]>> { | 104 | cur_crate: CrateId, |
105 | // Types like slice can have inherent impls in several crates, (core and alloc). | 105 | ) -> Option<ArrayVec<[CrateId; 2]>> { |
106 | // The corresponding impls are marked with lang items, so we can use them to find the required crates. | 106 | // Types like slice can have inherent impls in several crates, (core and alloc). |
107 | macro_rules! lang_item_crate { | 107 | // The corresponding impls are marked with lang items, so we can use them to find the required crates. |
108 | macro_rules! lang_item_crate { | ||
108 | ($($name:expr),+ $(,)?) => {{ | 109 | ($($name:expr),+ $(,)?) => {{ |
109 | let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); | 110 | let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); |
110 | $( | 111 | $( |
@@ -114,38 +115,38 @@ fn def_crates( | |||
114 | }}; | 115 | }}; |
115 | } | 116 | } |
116 | 117 | ||
117 | let lang_item_targets = match ty { | 118 | let lang_item_targets = match self { |
118 | Ty::Apply(a_ty) => match a_ty.ctor { | 119 | Ty::Apply(a_ty) => match a_ty.ctor { |
119 | TypeCtor::Adt(def_id) => { | 120 | TypeCtor::Adt(def_id) => { |
120 | return Some(std::iter::once(def_id.module(db).krate).collect()) | 121 | return Some(std::iter::once(def_id.module(db).krate).collect()) |
121 | } | 122 | } |
122 | TypeCtor::Bool => lang_item_crate!("bool"), | 123 | TypeCtor::Bool => lang_item_crate!("bool"), |
123 | TypeCtor::Char => lang_item_crate!("char"), | 124 | TypeCtor::Char => lang_item_crate!("char"), |
124 | TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { | 125 | TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { |
125 | // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) | 126 | // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) |
126 | FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"), | 127 | FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"), |
127 | FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"), | 128 | FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"), |
129 | }, | ||
130 | TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()), | ||
131 | TypeCtor::Str => lang_item_crate!("str_alloc", "str"), | ||
132 | TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"), | ||
133 | TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"), | ||
134 | TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"), | ||
135 | _ => return None, | ||
128 | }, | 136 | }, |
129 | TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()), | ||
130 | TypeCtor::Str => lang_item_crate!("str_alloc", "str"), | ||
131 | TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"), | ||
132 | TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"), | ||
133 | TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"), | ||
134 | _ => return None, | 137 | _ => return None, |
135 | }, | 138 | }; |
136 | _ => return None, | 139 | let res = lang_item_targets |
137 | }; | 140 | .into_iter() |
138 | let res = lang_item_targets | 141 | .filter_map(|it| match it { |
139 | .into_iter() | 142 | LangItemTarget::ImplBlockId(it) => Some(it), |
140 | .filter_map(|it| match it { | 143 | _ => None, |
141 | LangItemTarget::ImplBlockId(it) => Some(it), | 144 | }) |
142 | _ => None, | 145 | .map(|it| it.module(db).krate) |
143 | }) | 146 | .collect(); |
144 | .map(|it| it.module(db).krate) | 147 | Some(res) |
145 | .collect(); | 148 | } |
146 | Some(res) | ||
147 | } | 149 | } |
148 | |||
149 | /// Look up the method with the given name, returning the actual autoderefed | 150 | /// Look up the method with the given name, returning the actual autoderefed |
150 | /// receiver type (but without autoref applied yet). | 151 | /// receiver type (but without autoref applied yet). |
151 | pub(crate) fn lookup_method( | 152 | pub(crate) fn lookup_method( |
@@ -286,7 +287,7 @@ fn iterate_inherent_methods<T>( | |||
286 | krate: CrateId, | 287 | krate: CrateId, |
287 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | 288 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, |
288 | ) -> Option<T> { | 289 | ) -> Option<T> { |
289 | for krate in def_crates(db, krate, &ty.value)? { | 290 | for krate in ty.value.def_crates(db, krate)? { |
290 | let impls = db.impls_in_crate(krate); | 291 | let impls = db.impls_in_crate(krate); |
291 | 292 | ||
292 | for impl_block in impls.lookup_impl_blocks(&ty.value) { | 293 | for impl_block in impls.lookup_impl_blocks(&ty.value) { |
@@ -342,30 +343,6 @@ pub(crate) fn implements_trait( | |||
342 | solution.is_some() | 343 | solution.is_some() |
343 | } | 344 | } |
344 | 345 | ||
345 | impl Ty { | ||
346 | // This would be nicer if it just returned an iterator, but that runs into | ||
347 | // lifetime problems, because we need to borrow temp `CrateImplBlocks`. | ||
348 | pub fn iterate_impl_items<T>( | ||
349 | self, | ||
350 | db: &impl HirDatabase, | ||
351 | krate: CrateId, | ||
352 | mut callback: impl FnMut(AssocItem) -> Option<T>, | ||
353 | ) -> Option<T> { | ||
354 | for krate in def_crates(db, krate, &self)? { | ||
355 | let impls = db.impls_in_crate(krate); | ||
356 | |||
357 | for impl_block in impls.lookup_impl_blocks(&self) { | ||
358 | for &item in db.impl_data(impl_block).items.iter() { | ||
359 | if let Some(result) = callback(item.into()) { | ||
360 | return Some(result); | ||
361 | } | ||
362 | } | ||
363 | } | ||
364 | } | ||
365 | None | ||
366 | } | ||
367 | } | ||
368 | |||
369 | /// This creates Substs for a trait with the given Self type and type variables | 346 | /// This creates Substs for a trait with the given Self type and type variables |
370 | /// for all other parameters, to query Chalk with it. | 347 | /// for all other parameters, to query Chalk with it. |
371 | fn generic_implements_goal( | 348 | fn generic_implements_goal( |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index c40f41717..5155365cc 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -484,7 +484,7 @@ impl Resolver { | |||
484 | } | 484 | } |
485 | } | 485 | } |
486 | 486 | ||
487 | pub trait HasResolver { | 487 | pub trait HasResolver: Copy { |
488 | /// Builds a resolver for type references inside this def. | 488 | /// Builds a resolver for type references inside this def. |
489 | fn resolver(self, db: &impl DefDatabase) -> Resolver; | 489 | fn resolver(self, db: &impl DefDatabase) -> Resolver; |
490 | } | 490 | } |
@@ -502,7 +502,7 @@ impl HasResolver for TraitId { | |||
502 | } | 502 | } |
503 | } | 503 | } |
504 | 504 | ||
505 | impl<T: Into<AdtId>> HasResolver for T { | 505 | impl<T: Into<AdtId> + Copy> HasResolver for T { |
506 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | 506 | fn resolver(self, db: &impl DefDatabase) -> Resolver { |
507 | let def = self.into(); | 507 | let def = self.into(); |
508 | def.module(db) | 508 | def.module(db) |
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 63e25e0bf..89e0009a1 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -50,7 +50,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
50 | hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), | 50 | hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), |
51 | _ => unreachable!(), | 51 | _ => unreachable!(), |
52 | }; | 52 | }; |
53 | ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| { | 53 | ctx.analyzer.iterate_path_candidates(ctx.db, &ty, None, |_ty, item| { |
54 | match item { | 54 | match item { |
55 | hir::AssocItem::Function(func) => { | 55 | hir::AssocItem::Function(func) => { |
56 | if !func.has_self_param(ctx.db) { | 56 | if !func.has_self_param(ctx.db) { |