aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model.rs127
-rw-r--r--crates/ra_hir/src/db.rs32
-rw-r--r--crates/ra_hir/src/expr.rs4
-rw-r--r--crates/ra_hir/src/source_binder.rs10
-rw-r--r--crates/ra_hir/src/ty.rs31
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs10
-rw-r--r--crates/ra_hir/src/ty/infer.rs65
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs10
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs46
-rw-r--r--crates/ra_hir/src/ty/lower.rs232
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs154
-rw-r--r--crates/ra_hir/src/ty/traits.rs17
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs75
-rw-r--r--crates/ra_hir/src/ty/utils.rs63
14 files changed, 428 insertions, 448 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 821f919d4..54da937ea 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -9,7 +9,7 @@ use hir_def::{
9 builtin_type::BuiltinType, 9 builtin_type::BuiltinType,
10 docs::Documentation, 10 docs::Documentation,
11 per_ns::PerNs, 11 per_ns::PerNs,
12 resolver::{HasResolver, TypeNs}, 12 resolver::HasResolver,
13 type_ref::{Mutability, TypeRef}, 13 type_ref::{Mutability, TypeRef},
14 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId, 14 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId,
15 HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, 15 HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId,
@@ -28,7 +28,7 @@ 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, Namespace, TraitEnvironment, TraitRef, Ty, TypeCtor, 31 self, InEnvironment, InferenceResult, TraitEnvironment, TraitRef, Ty, TyDefId, TypeCtor,
32 TypeWalk, 32 TypeWalk,
33 }, 33 },
34 CallableDef, Either, HirDisplay, Name, Source, 34 CallableDef, Either, HirDisplay, Name, Source,
@@ -354,11 +354,11 @@ impl Struct {
354 } 354 }
355 355
356 pub fn ty(self, db: &impl HirDatabase) -> Ty { 356 pub fn ty(self, db: &impl HirDatabase) -> Ty {
357 db.type_for_def(self.into(), Namespace::Types) 357 db.ty(self.id.into())
358 } 358 }
359 359
360 pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty { 360 pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty {
361 db.type_for_def(self.into(), Namespace::Values) 361 db.value_ty(self.id.into())
362 } 362 }
363 363
364 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { 364 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
@@ -381,7 +381,7 @@ impl Union {
381 } 381 }
382 382
383 pub fn ty(self, db: &impl HirDatabase) -> Ty { 383 pub fn ty(self, db: &impl HirDatabase) -> Ty {
384 db.type_for_def(self.into(), Namespace::Types) 384 db.ty(self.id.into())
385 } 385 }
386 386
387 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { 387 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
@@ -442,7 +442,7 @@ impl Enum {
442 } 442 }
443 443
444 pub fn ty(self, db: &impl HirDatabase) -> Ty { 444 pub fn ty(self, db: &impl HirDatabase) -> Ty {
445 db.type_for_def(self.into(), Namespace::Types) 445 db.ty(self.id.into())
446 } 446 }
447} 447}
448 448
@@ -499,12 +499,9 @@ impl Adt {
499 let subst = db.generic_defaults(self.into()); 499 let subst = db.generic_defaults(self.into());
500 subst.iter().any(|ty| ty == &Ty::Unknown) 500 subst.iter().any(|ty| ty == &Ty::Unknown)
501 } 501 }
502 pub fn ty(self, db: &impl HirDatabase) -> Ty { 502 pub fn ty(self, db: &impl HirDatabase) -> Type {
503 match self { 503 let id = AdtId::from(self);
504 Adt::Struct(it) => it.ty(db), 504 Type::from_def(db, id.module(db).krate, id)
505 Adt::Union(it) => it.ty(db),
506 Adt::Enum(it) => it.ty(db),
507 }
508 } 505 }
509 506
510 pub fn module(self, db: &impl DefDatabase) -> Module { 507 pub fn module(self, db: &impl DefDatabase) -> Module {
@@ -617,7 +614,7 @@ impl Function {
617 } 614 }
618 615
619 pub fn ty(self, db: &impl HirDatabase) -> Ty { 616 pub fn ty(self, db: &impl HirDatabase) -> Ty {
620 db.type_for_def(self.into(), Namespace::Values) 617 db.value_ty(self.id.into())
621 } 618 }
622 619
623 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 620 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
@@ -737,68 +734,11 @@ impl Trait {
737 } 734 }
738 735
739 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> { 736 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> {
740 db.trait_data(self.id).items.iter().map(|it| (*it).into()).collect() 737 db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
741 }
742
743 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
744 let resolver = self.id.resolver(db);
745 // returning the iterator directly doesn't easily work because of
746 // lifetime problems, but since there usually shouldn't be more than a
747 // few direct traits this should be fine (we could even use some kind of
748 // SmallVec if performance is a concern)
749 db.generic_params(self.id.into())
750 .where_predicates
751 .iter()
752 .filter_map(|pred| match &pred.type_ref {
753 TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
754 _ => None,
755 })
756 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
757 Some(TypeNs::TraitId(t)) => Some(t),
758 _ => None,
759 })
760 .map(Trait::from)
761 .collect()
762 }
763
764 /// Returns an iterator over the whole super trait hierarchy (including the
765 /// trait itself).
766 pub fn all_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
767 // we need to take care a bit here to avoid infinite loops in case of cycles
768 // (i.e. if we have `trait A: B; trait B: A;`)
769 let mut result = vec![self];
770 let mut i = 0;
771 while i < result.len() {
772 let t = result[i];
773 // yeah this is quadratic, but trait hierarchies should be flat
774 // enough that this doesn't matter
775 for tt in t.direct_super_traits(db) {
776 if !result.contains(&tt) {
777 result.push(tt);
778 }
779 }
780 i += 1;
781 }
782 result
783 }
784
785 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
786 let trait_data = db.trait_data(self.id);
787 let res =
788 trait_data.associated_types().map(TypeAlias::from).find(|t| &t.name(db) == name)?;
789 Some(res)
790 }
791
792 pub fn associated_type_by_name_including_super_traits(
793 self,
794 db: &impl HirDatabase,
795 name: &Name,
796 ) -> Option<TypeAlias> {
797 self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name))
798 } 738 }
799 739
800 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { 740 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef {
801 TraitRef::for_trait(db, self) 741 TraitRef::for_trait(db, self.id)
802 } 742 }
803 743
804 pub fn is_auto(self, db: &impl DefDatabase) -> bool { 744 pub fn is_auto(self, db: &impl DefDatabase) -> bool {
@@ -853,8 +793,8 @@ impl TypeAlias {
853 db.type_alias_data(self.id).type_ref.clone() 793 db.type_alias_data(self.id).type_ref.clone()
854 } 794 }
855 795
856 pub fn ty(self, db: &impl HirDatabase) -> Ty { 796 pub fn ty(self, db: &impl HirDatabase) -> Type {
857 db.type_for_def(self.into(), Namespace::Types) 797 Type::from_def(db, self.id.lookup(db).module(db).krate, self.id)
858 } 798 }
859 799
860 pub fn name(self, db: &impl DefDatabase) -> Name { 800 pub fn name(self, db: &impl DefDatabase) -> Name {
@@ -1003,7 +943,7 @@ impl ImplBlock {
1003 } 943 }
1004 pub fn for_trait(db: &impl HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplBlock> { 944 pub fn for_trait(db: &impl HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplBlock> {
1005 let impls = db.impls_in_crate(krate.crate_id); 945 let impls = db.impls_in_crate(krate.crate_id);
1006 impls.lookup_impl_blocks_for_trait(trait_).map(Self::from).collect() 946 impls.lookup_impl_blocks_for_trait(trait_.id).map(Self::from).collect()
1007 } 947 }
1008 948
1009 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { 949 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
@@ -1040,13 +980,24 @@ impl ImplBlock {
1040 } 980 }
1041} 981}
1042 982
1043#[derive(Clone, PartialEq, Eq)] 983#[derive(Clone, PartialEq, Eq, Debug)]
1044pub struct Type { 984pub struct Type {
1045 pub(crate) krate: CrateId, 985 pub(crate) krate: CrateId,
1046 pub(crate) ty: InEnvironment<Ty>, 986 pub(crate) ty: InEnvironment<Ty>,
1047} 987}
1048 988
1049impl Type { 989impl 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
1050 pub fn is_bool(&self) -> bool { 1001 pub fn is_bool(&self) -> bool {
1051 match &self.ty.value { 1002 match &self.ty.value {
1052 Ty::Apply(a_ty) => match a_ty.ctor { 1003 Ty::Apply(a_ty) => match a_ty.ctor {
@@ -1155,6 +1106,28 @@ impl Type {
1155 .map(move |ty| self.derived(ty)) 1106 .map(move |ty| self.derived(ty))
1156 } 1107 }
1157 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
1158 // FIXME: remove 1131 // FIXME: remove
1159 pub fn into_ty(self) -> Ty { 1132 pub fn into_ty(self) -> Ty {
1160 self.ty.value 1133 self.ty.value
@@ -1162,7 +1135,7 @@ impl Type {
1162 1135
1163 pub fn as_adt(&self) -> Option<Adt> { 1136 pub fn as_adt(&self) -> Option<Adt> {
1164 let (adt, _subst) = self.ty.value.as_adt()?; 1137 let (adt, _subst) = self.ty.value.as_adt()?;
1165 Some(adt) 1138 Some(adt.into())
1166 } 1139 }
1167 1140
1168 fn derived(&self, ty: Ty) -> Type { 1141 fn derived(&self, ty: Ty) -> Type {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 32f05a4d8..31b21ca84 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -2,6 +2,7 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{GenericDefId, LocalStructFieldId, TraitId, VariantId};
5use ra_arena::map::ArenaMap; 6use ra_arena::map::ArenaMap;
6use ra_db::{salsa, CrateId}; 7use ra_db::{salsa, CrateId};
7 8
@@ -9,22 +10,18 @@ use crate::{
9 ty::{ 10 ty::{
10 method_resolution::CrateImplBlocks, 11 method_resolution::CrateImplBlocks,
11 traits::{AssocTyValue, Impl}, 12 traits::{AssocTyValue, Impl},
12 CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, 13 CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, Ty, TyDefId, TypeCtor,
13 TypeCtor, 14 ValueTyDefId,
14 }, 15 },
15 Crate, DefWithBody, ImplBlock, Trait, 16 Crate, DefWithBody, ImplBlock,
16}; 17};
17 18
18pub use hir_def::{ 19pub use hir_def::db::{
19 db::{ 20 BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery,
20 BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery, 21 DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery,
21 DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery, 22 FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage,
22 FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, 23 LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, RawItemsWithSourceMapQuery,
23 InternDatabaseStorage, LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, 24 StaticDataQuery, StructDataQuery, TraitDataQuery, TypeAliasDataQuery,
24 RawItemsWithSourceMapQuery, StaticDataQuery, StructDataQuery, TraitDataQuery,
25 TypeAliasDataQuery,
26 },
27 GenericDefId, LocalStructFieldId, VariantId,
28}; 25};
29pub use hir_expand::db::{ 26pub use hir_expand::db::{
30 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, 27 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
@@ -37,8 +34,11 @@ pub trait HirDatabase: DefDatabase {
37 #[salsa::invoke(crate::ty::infer_query)] 34 #[salsa::invoke(crate::ty::infer_query)]
38 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>; 35 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>;
39 36
40 #[salsa::invoke(crate::ty::type_for_def)] 37 #[salsa::invoke(crate::ty::ty_query)]
41 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty; 38 fn ty(&self, def: TyDefId) -> Ty;
39
40 #[salsa::invoke(crate::ty::value_ty_query)]
41 fn value_ty(&self, def: ValueTyDefId) -> Ty;
42 42
43 #[salsa::invoke(crate::ty::field_types_query)] 43 #[salsa::invoke(crate::ty::field_types_query)]
44 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; 44 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
@@ -63,7 +63,7 @@ pub trait HirDatabase: DefDatabase {
63 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplBlocks>; 63 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplBlocks>;
64 64
65 #[salsa::invoke(crate::ty::traits::impls_for_trait_query)] 65 #[salsa::invoke(crate::ty::traits::impls_for_trait_query)]
66 fn impls_for_trait(&self, krate: Crate, trait_: Trait) -> Arc<[ImplBlock]>; 66 fn impls_for_trait(&self, krate: CrateId, trait_: TraitId) -> Arc<[ImplBlock]>;
67 67
68 /// This provides the Chalk trait solver instance. Because Chalk always 68 /// This provides the Chalk trait solver instance. Because Chalk always
69 /// works from a specific crate, this query is keyed on the crate; and 69 /// works from a specific crate, this query is keyed on the crate; and
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index adb9805ab..5c82c23d6 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -12,7 +12,7 @@ use crate::{
12 db::HirDatabase, 12 db::HirDatabase,
13 diagnostics::{MissingFields, MissingOkInTailExpr}, 13 diagnostics::{MissingFields, MissingOkInTailExpr},
14 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, 14 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
15 Adt, Function, Name, Path, 15 Function, Name, Path, Struct,
16}; 16};
17 17
18pub use hir_def::{ 18pub use hir_def::{
@@ -69,7 +69,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
69 } 69 }
70 70
71 let struct_def = match self.infer[id].as_adt() { 71 let struct_def = match self.infer[id].as_adt() {
72 Some((Adt::Struct(s), _)) => s, 72 Some((AdtId::StructId(s), _)) => Struct::from(s),
73 _ => return, 73 _ => return,
74 }; 74 };
75 75
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 82cb66583..9f3e6c43f 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -14,8 +14,7 @@ use hir_def::{
14 DefWithBodyId, 14 DefWithBodyId,
15}; 15};
16use hir_expand::{ 16use hir_expand::{
17 hygiene::Hygiene, name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind, 17 hygiene::Hygiene, name::AsName, AstId, HirFileId, MacroCallId, MacroFileKind, Source,
18 Source,
19}; 18};
20use ra_syntax::{ 19use ra_syntax::{
21 ast::{self, AstNode}, 20 ast::{self, AstNode},
@@ -390,14 +389,14 @@ impl SourceAnalyzer {
390 pub fn iterate_path_candidates<T>( 389 pub fn iterate_path_candidates<T>(
391 &self, 390 &self,
392 db: &impl HirDatabase, 391 db: &impl HirDatabase,
393 ty: Ty, 392 ty: &Type,
394 name: Option<&Name>, 393 name: Option<&Name>,
395 callback: impl FnMut(&Ty, AssocItem) -> Option<T>, 394 callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
396 ) -> Option<T> { 395 ) -> Option<T> {
397 // There should be no inference vars in types passed here 396 // There should be no inference vars in types passed here
398 // FIXME check that? 397 // FIXME check that?
399 // FIXME replace Unknown by bound vars here 398 // FIXME replace Unknown by bound vars here
400 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; 399 let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 };
401 method_resolution::iterate_method_candidates( 400 method_resolution::iterate_method_candidates(
402 &canonical, 401 &canonical,
403 db, 402 db,
@@ -451,9 +450,8 @@ impl SourceAnalyzer {
451 macro_call.file_id, 450 macro_call.file_id,
452 db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), 451 db.ast_id_map(macro_call.file_id).ast_id(macro_call.value),
453 ); 452 );
454 let macro_call_loc = MacroCallLoc { def, ast_id };
455 Some(Expansion { 453 Some(Expansion {
456 macro_call_id: db.intern_macro(macro_call_loc), 454 macro_call_id: def.as_call_id(db, ast_id),
457 macro_file_kind: to_macro_file_kind(macro_call.value), 455 macro_file_kind: to_macro_file_kind(macro_call.value),
458 }) 456 })
459 } 457 }
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index bd03055b9..791b6064a 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -9,6 +9,7 @@ mod op;
9mod lower; 9mod lower;
10mod infer; 10mod infer;
11pub(crate) mod display; 11pub(crate) mod display;
12pub(crate) mod utils;
12 13
13#[cfg(test)] 14#[cfg(test)]
14mod tests; 15mod tests;
@@ -18,14 +19,17 @@ use std::sync::Arc;
18use std::{fmt, iter, mem}; 19use std::{fmt, iter, mem};
19 20
20use hir_def::{ 21use hir_def::{
21 generics::GenericParams, AdtId, ContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, 22 expr::ExprId, generics::GenericParams, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId,
22 TraitId, TypeAliasId, 23 GenericDefId, HasModule, Lookup, TraitId, TypeAliasId,
23}; 24};
25use hir_expand::name::Name;
24use ra_db::{impl_intern_key, salsa}; 26use ra_db::{impl_intern_key, salsa};
25 27
26use crate::{ 28use crate::{
27 db::HirDatabase, expr::ExprId, util::make_mut_slice, Adt, Crate, FloatTy, IntTy, Mutability, 29 db::HirDatabase,
28 Name, Trait, Uncertain, 30 ty::primitive::{FloatTy, IntTy, Uncertain},
31 util::make_mut_slice,
32 Crate,
29}; 33};
30use display::{HirDisplay, HirFormatter}; 34use display::{HirDisplay, HirFormatter};
31 35
@@ -34,8 +38,8 @@ pub(crate) use infer::{infer_query, InferTy, InferenceResult};
34pub use lower::CallableDef; 38pub use lower::CallableDef;
35pub(crate) use lower::{ 39pub(crate) use lower::{
36 callable_item_sig, field_types_query, generic_defaults_query, 40 callable_item_sig, field_types_query, generic_defaults_query,
37 generic_predicates_for_param_query, generic_predicates_query, type_for_def, Namespace, 41 generic_predicates_for_param_query, generic_predicates_query, ty_query, value_ty_query,
38 TypableDef, 42 TyDefId, TypableDef, ValueTyDefId,
39}; 43};
40pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 44pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
41 45
@@ -444,7 +448,7 @@ impl Deref for Substs {
444#[derive(Clone, PartialEq, Eq, Debug, Hash)] 448#[derive(Clone, PartialEq, Eq, Debug, Hash)]
445pub struct TraitRef { 449pub struct TraitRef {
446 /// FIXME name? 450 /// FIXME name?
447 pub trait_: Trait, 451 pub trait_: TraitId,
448 pub substs: Substs, 452 pub substs: Substs,
449} 453}
450 454
@@ -595,10 +599,10 @@ impl Ty {
595 } 599 }
596 } 600 }
597 601
598 pub fn as_adt(&self) -> Option<(Adt, &Substs)> { 602 pub fn as_adt(&self) -> Option<(AdtId, &Substs)> {
599 match self { 603 match self {
600 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => { 604 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => {
601 Some(((*adt_def).into(), parameters)) 605 Some((*adt_def, parameters))
602 } 606 }
603 _ => None, 607 _ => None,
604 } 608 }
@@ -675,7 +679,7 @@ impl Ty {
675 } 679 }
676 680
677 /// If this is an `impl Trait` or `dyn Trait`, returns that trait. 681 /// If this is an `impl Trait` or `dyn Trait`, returns that trait.
678 pub fn inherent_trait(&self) -> Option<Trait> { 682 pub fn inherent_trait(&self) -> Option<TraitId> {
679 match self { 683 match self {
680 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 684 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
681 predicates.iter().find_map(|pred| match pred { 685 predicates.iter().find_map(|pred| match pred {
@@ -987,7 +991,10 @@ impl HirDisplay for Ty {
987 write!( 991 write!(
988 f, 992 f,
989 "{}", 993 "{}",
990 trait_ref.trait_.name(f.db).unwrap_or_else(Name::missing) 994 f.db.trait_data(trait_ref.trait_)
995 .name
996 .clone()
997 .unwrap_or_else(Name::missing)
991 )?; 998 )?;
992 if trait_ref.substs.len() > 1 { 999 if trait_ref.substs.len() > 1 {
993 write!(f, "<")?; 1000 write!(f, "<")?;
@@ -1048,7 +1055,7 @@ impl TraitRef {
1048 } else { 1055 } else {
1049 write!(f, ": ")?; 1056 write!(f, ": ")?;
1050 } 1057 }
1051 write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?; 1058 write!(f, "{}", f.db.trait_data(self.trait_).name.clone().unwrap_or_else(Name::missing))?;
1052 if self.substs.len() > 1 { 1059 if self.substs.len() > 1 {
1053 write!(f, "<")?; 1060 write!(f, "<")?;
1054 f.write_joined(&self.substs[1..], ", ")?; 1061 f.write_joined(&self.substs[1..], ", ")?;
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index 9e7593b8b..ae68234ac 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -10,7 +10,7 @@ use hir_expand::name;
10use log::{info, warn}; 10use log::{info, warn};
11use ra_db::CrateId; 11use ra_db::CrateId;
12 12
13use crate::{db::HirDatabase, Trait}; 13use crate::db::HirDatabase;
14 14
15use super::{ 15use super::{
16 traits::{InEnvironment, Solution}, 16 traits::{InEnvironment, Solution},
@@ -49,12 +49,12 @@ fn deref_by_trait(
49 ty: InEnvironment<&Canonical<Ty>>, 49 ty: InEnvironment<&Canonical<Ty>>,
50) -> Option<Canonical<Ty>> { 50) -> Option<Canonical<Ty>> {
51 let deref_trait = match db.lang_item(krate.into(), "deref".into())? { 51 let deref_trait = match db.lang_item(krate.into(), "deref".into())? {
52 LangItemTarget::TraitId(t) => Trait::from(t), 52 LangItemTarget::TraitId(it) => it,
53 _ => return None, 53 _ => return None,
54 }; 54 };
55 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; 55 let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?;
56 56
57 let generic_params = db.generic_params(target.id.into()); 57 let generic_params = db.generic_params(target.into());
58 if generic_params.count_params_including_parent() != 1 { 58 if generic_params.count_params_including_parent() != 1 {
59 // the Target type + Deref trait should only have one generic parameter, 59 // the Target type + Deref trait should only have one generic parameter,
60 // namely Deref's Self type 60 // namely Deref's Self type
@@ -69,7 +69,7 @@ fn deref_by_trait(
69 69
70 let projection = super::traits::ProjectionPredicate { 70 let projection = super::traits::ProjectionPredicate {
71 ty: Ty::Bound(0), 71 ty: Ty::Bound(0),
72 projection_ty: super::ProjectionTy { associated_ty: target.id, parameters }, 72 projection_ty: super::ProjectionTy { associated_ty: target, parameters },
73 }; 73 };
74 74
75 let obligation = super::Obligation::Projection(projection); 75 let obligation = super::Obligation::Projection(projection);
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index fce45321d..beb2efb7a 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -35,15 +35,15 @@ use test_utils::tested_by;
35 35
36use super::{ 36use super::{
37 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 37 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
38 ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef, 38 ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
39 TypeCtor, TypeWalk, Uncertain, 39 TypeWalk, Uncertain,
40}; 40};
41use crate::{ 41use crate::{
42 code_model::TypeAlias, 42 code_model::TypeAlias,
43 db::HirDatabase, 43 db::HirDatabase,
44 expr::{BindingAnnotation, Body, ExprId, PatId}, 44 expr::{BindingAnnotation, Body, ExprId, PatId},
45 ty::infer::diagnostics::InferenceDiagnostic, 45 ty::infer::diagnostics::InferenceDiagnostic,
46 Adt, AssocItem, DefWithBody, FloatTy, Function, IntTy, Path, StructField, Trait, VariantDef, 46 AssocItem, DefWithBody, FloatTy, Function, IntTy, Path, StructField, VariantDef,
47}; 47};
48 48
49macro_rules! ty_app { 49macro_rules! ty_app {
@@ -520,45 +520,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
520 None => return (Ty::Unknown, None), 520 None => return (Ty::Unknown, None),
521 }; 521 };
522 let resolver = &self.resolver; 522 let resolver = &self.resolver;
523 let def: TypableDef = 523 // FIXME: this should resolve assoc items as well, see this example:
524 // FIXME: this should resolve assoc items as well, see this example: 524 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
525 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 525 match resolver.resolve_path_in_type_ns_fully(self.db, &path) {
526 match resolver.resolve_path_in_type_ns_fully(self.db, &path) { 526 Some(TypeNs::AdtId(AdtId::StructId(strukt))) => {
527 Some(TypeNs::AdtId(AdtId::StructId(it))) => it.into(), 527 let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into());
528 Some(TypeNs::AdtId(AdtId::UnionId(it))) => it.into(), 528 let ty = self.db.ty(strukt.into());
529 Some(TypeNs::AdtSelfType(adt)) => adt.into(),
530 Some(TypeNs::EnumVariantId(it)) => it.into(),
531 Some(TypeNs::TypeAliasId(it)) => it.into(),
532
533 Some(TypeNs::SelfType(_)) |
534 Some(TypeNs::GenericParam(_)) |
535 Some(TypeNs::BuiltinType(_)) |
536 Some(TypeNs::TraitId(_)) |
537 Some(TypeNs::AdtId(AdtId::EnumId(_))) |
538 None => {
539 return (Ty::Unknown, None)
540 }
541 };
542 // FIXME remove the duplication between here and `Ty::from_path`?
543 let substs = Ty::substs_from_path(self.db, resolver, path, def);
544 match def {
545 TypableDef::Adt(Adt::Struct(s)) => {
546 let ty = s.ty(self.db);
547 let ty = self.insert_type_vars(ty.apply_substs(substs)); 529 let ty = self.insert_type_vars(ty.apply_substs(substs));
548 (ty, Some(s.into())) 530 (ty, Some(VariantDef::Struct(strukt.into())))
549 } 531 }
550 TypableDef::EnumVariant(var) => { 532 Some(TypeNs::EnumVariantId(var)) => {
551 let ty = var.parent_enum(self.db).ty(self.db); 533 let substs = Ty::substs_from_path(self.db, resolver, path, var.into());
534 let ty = self.db.ty(var.parent.into());
552 let ty = self.insert_type_vars(ty.apply_substs(substs)); 535 let ty = self.insert_type_vars(ty.apply_substs(substs));
553 (ty, Some(var.into())) 536 (ty, Some(VariantDef::EnumVariant(var.into())))
554 } 537 }
555 TypableDef::Adt(Adt::Enum(_)) 538 Some(_) | None => (Ty::Unknown, None),
556 | TypableDef::Adt(Adt::Union(_))
557 | TypableDef::TypeAlias(_)
558 | TypableDef::Function(_)
559 | TypableDef::Const(_)
560 | TypableDef::Static(_)
561 | TypableDef::BuiltinType(_) => (Ty::Unknown, None),
562 } 539 }
563 } 540 }
564 541
@@ -582,20 +559,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
582 559
583 fn resolve_into_iter_item(&self) -> Option<TypeAlias> { 560 fn resolve_into_iter_item(&self) -> Option<TypeAlias> {
584 let path = known::std_iter_into_iterator(); 561 let path = known::std_iter_into_iterator();
585 let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); 562 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
586 trait_.associated_type_by_name(self.db, &name::ITEM_TYPE) 563 self.db.trait_data(trait_).associated_type_by_name(&name::ITEM_TYPE).map(TypeAlias::from)
587 } 564 }
588 565
589 fn resolve_ops_try_ok(&self) -> Option<TypeAlias> { 566 fn resolve_ops_try_ok(&self) -> Option<TypeAlias> {
590 let path = known::std_ops_try(); 567 let path = known::std_ops_try();
591 let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); 568 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
592 trait_.associated_type_by_name(self.db, &name::OK_TYPE) 569 self.db.trait_data(trait_).associated_type_by_name(&name::OK_TYPE).map(TypeAlias::from)
593 } 570 }
594 571
595 fn resolve_future_future_output(&self) -> Option<TypeAlias> { 572 fn resolve_future_future_output(&self) -> Option<TypeAlias> {
596 let path = known::std_future_future(); 573 let path = known::std_future_future();
597 let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); 574 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
598 trait_.associated_type_by_name(self.db, &name::OUTPUT_TYPE) 575 self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE).map(TypeAlias::from)
599 } 576 }
600 577
601 fn resolve_boxed_box(&self) -> Option<AdtId> { 578 fn resolve_boxed_box(&self) -> Option<AdtId> {
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index 3d0895dc6..eb221d6bc 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -17,8 +17,8 @@ use crate::{
17 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 17 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
18 ty::{ 18 ty::{
19 autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy, 19 autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy,
20 Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, 20 Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
21 TypeCtor, TypeWalk, Uncertain, 21 TypeWalk, Uncertain,
22 }, 22 },
23 Name, 23 Name,
24}; 24};
@@ -558,11 +558,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
558 Some((ty, func)) => { 558 Some((ty, func)) => {
559 let ty = canonicalized_receiver.decanonicalize_ty(ty); 559 let ty = canonicalized_receiver.decanonicalize_ty(ty);
560 self.write_method_resolution(tgt_expr, func); 560 self.write_method_resolution(tgt_expr, func);
561 ( 561 (ty, self.db.value_ty(func.id.into()), Some(self.db.generic_params(func.id.into())))
562 ty,
563 self.db.type_for_def(func.into(), Namespace::Values),
564 Some(self.db.generic_params(func.id.into())),
565 )
566 } 562 }
567 None => (receiver_ty, Ty::Unknown, None), 563 None => (receiver_ty, Ty::Unknown, None),
568 }; 564 };
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 6165eba4f..be2067dd4 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -7,7 +7,7 @@ use hir_def::{
7 7
8use crate::{ 8use crate::{
9 db::HirDatabase, 9 db::HirDatabase,
10 ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk}, 10 ty::{method_resolution, Substs, Ty, TypeWalk, ValueTyDefId},
11 AssocItem, Container, Function, Name, Path, 11 AssocItem, Container, Function, Name, Path,
12}; 12};
13 13
@@ -56,7 +56,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
56 } 56 }
57 }; 57 };
58 58
59 let typable: TypableDef = match value { 59 let typable: ValueTyDefId = match value {
60 ValueNs::LocalBinding(pat) => { 60 ValueNs::LocalBinding(pat) => {
61 let ty = self.result.type_of_pat.get(pat)?.clone(); 61 let ty = self.result.type_of_pat.get(pat)?.clone();
62 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 62 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
@@ -69,11 +69,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
69 ValueNs::EnumVariantId(it) => it.into(), 69 ValueNs::EnumVariantId(it) => it.into(),
70 }; 70 };
71 71
72 let mut ty = self.db.type_for_def(typable, Namespace::Values); 72 let mut ty = self.db.value_ty(typable);
73 if let Some(self_subst) = self_subst { 73 if let Some(self_subst) = self_subst {
74 ty = ty.subst(&self_subst); 74 ty = ty.subst(&self_subst);
75 } 75 }
76
77 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 76 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
78 let ty = ty.subst(&substs); 77 let ty = ty.subst(&substs);
79 Some(ty) 78 Some(ty)
@@ -143,24 +142,27 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
143 id: ExprOrPatId, 142 id: ExprOrPatId,
144 ) -> Option<(ValueNs, Option<Substs>)> { 143 ) -> Option<(ValueNs, Option<Substs>)> {
145 let trait_ = trait_ref.trait_; 144 let trait_ = trait_ref.trait_;
146 let item = trait_.items(self.db).iter().copied().find_map(|item| match item { 145 let item =
147 AssocItem::Function(func) => { 146 self.db.trait_data(trait_).items.iter().map(|(_name, id)| (*id).into()).find_map(
148 if segment.name == func.name(self.db) { 147 |item| match item {
149 Some(AssocItem::Function(func)) 148 AssocItem::Function(func) => {
150 } else { 149 if segment.name == func.name(self.db) {
151 None 150 Some(AssocItem::Function(func))
152 } 151 } else {
153 } 152 None
153 }
154 }
154 155
155 AssocItem::Const(konst) => { 156 AssocItem::Const(konst) => {
156 if konst.name(self.db).map_or(false, |n| n == segment.name) { 157 if konst.name(self.db).map_or(false, |n| n == segment.name) {
157 Some(AssocItem::Const(konst)) 158 Some(AssocItem::Const(konst))
158 } else { 159 } else {
159 None 160 None
160 } 161 }
161 } 162 }
162 AssocItem::TypeAlias(_) => None, 163 AssocItem::TypeAlias(_) => None,
163 })?; 164 },
165 )?;
164 let def = match item { 166 let def = match item {
165 AssocItem::Function(f) => ValueNs::FunctionId(f.id), 167 AssocItem::Function(f) => ValueNs::FunctionId(f.id),
166 AssocItem::Const(c) => ValueNs::ConstId(c.id), 168 AssocItem::Const(c) => ValueNs::ConstId(c.id),
@@ -212,7 +214,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
212 .fill_with_params() 214 .fill_with_params()
213 .build(); 215 .build();
214 self.obligations.push(super::Obligation::Trait(TraitRef { 216 self.obligations.push(super::Obligation::Trait(TraitRef {
215 trait_: t, 217 trait_: t.id,
216 substs: trait_substs, 218 substs: trait_substs,
217 })); 219 }));
218 Some(substs) 220 Some(substs)
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 2d23890a5..1c0f71adc 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -14,8 +14,8 @@ use hir_def::{
14 path::{GenericArg, PathSegment}, 14 path::{GenericArg, PathSegment},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, AstItemDef, EnumVariantId, FunctionId, GenericDefId, HasModule, LocalStructFieldId, 17 AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule,
18 Lookup, StructId, VariantId, 18 LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
19}; 19};
20use ra_arena::map::ArenaMap; 20use ra_arena::map::ArenaMap;
21use ra_db::CrateId; 21use ra_db::CrateId;
@@ -28,24 +28,13 @@ use crate::{
28 db::HirDatabase, 28 db::HirDatabase,
29 ty::{ 29 ty::{
30 primitive::{FloatTy, IntTy}, 30 primitive::{FloatTy, IntTy},
31 Adt, 31 utils::{all_super_traits, associated_type_by_name_including_super_traits},
32 }, 32 },
33 util::make_mut_slice, 33 util::make_mut_slice,
34 Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, Trait, 34 Adt, Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, Trait,
35 TypeAlias, Union, 35 TypeAlias, Union,
36}; 36};
37 37
38// FIXME: this is only really used in `type_for_def`, which contains a bunch of
39// impossible cases. Perhaps we should recombine `TypeableDef` and `Namespace`
40// into a `AsTypeDef`, `AsValueDef` enums?
41#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub enum Namespace {
43 Types,
44 Values,
45 // Note that only type inference uses this enum, and it doesn't care about macros.
46 // Macro,
47}
48
49impl Ty { 38impl Ty {
50 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { 39 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self {
51 match type_ref { 40 match type_ref {
@@ -169,14 +158,16 @@ impl Ty {
169 ); 158 );
170 return if remaining_segments.len() == 1 { 159 return if remaining_segments.len() == 1 {
171 let segment = &remaining_segments[0]; 160 let segment = &remaining_segments[0];
172 match trait_ref 161 let associated_ty = associated_type_by_name_including_super_traits(
173 .trait_ 162 db,
174 .associated_type_by_name_including_super_traits(db, &segment.name) 163 trait_ref.trait_,
175 { 164 &segment.name,
165 );
166 match associated_ty {
176 Some(associated_ty) => { 167 Some(associated_ty) => {
177 // FIXME handle type parameters on the segment 168 // FIXME handle type parameters on the segment
178 Ty::Projection(ProjectionTy { 169 Ty::Projection(ProjectionTy {
179 associated_ty: associated_ty.id, 170 associated_ty,
180 parameters: trait_ref.substs, 171 parameters: trait_ref.substs,
181 }) 172 })
182 } 173 }
@@ -198,7 +189,7 @@ impl Ty {
198 Ty::Param { idx, name } 189 Ty::Param { idx, name }
199 } 190 }
200 TypeNs::SelfType(impl_block) => ImplBlock::from(impl_block).target_ty(db), 191 TypeNs::SelfType(impl_block) => ImplBlock::from(impl_block).target_ty(db),
201 TypeNs::AdtSelfType(adt) => Adt::from(adt).ty(db), 192 TypeNs::AdtSelfType(adt) => db.ty(adt.into()),
202 193
203 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()),
204 TypeNs::BuiltinType(it) => { 195 TypeNs::BuiltinType(it) => {
@@ -260,18 +251,16 @@ impl Ty {
260 GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), 251 GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_),
261 _ => None, 252 _ => None,
262 }); 253 });
263 let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); 254 let traits = traits_from_env.flat_map(|t| all_super_traits(db, t)).map(Trait::from);
264 for t in traits { 255 for t in traits {
265 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { 256 if let Some(associated_ty) = db.trait_data(t.id).associated_type_by_name(&segment.name)
257 {
266 let substs = Substs::build_for_def(db, t.id) 258 let substs = Substs::build_for_def(db, t.id)
267 .push(self_ty.clone()) 259 .push(self_ty.clone())
268 .fill_with_unknown() 260 .fill_with_unknown()
269 .build(); 261 .build();
270 // FIXME handle type parameters on the segment 262 // FIXME handle type parameters on the segment
271 return Ty::Projection(ProjectionTy { 263 return Ty::Projection(ProjectionTy { associated_ty, parameters: substs });
272 associated_ty: associated_ty.id,
273 parameters: substs,
274 });
275 } 264 }
276 } 265 }
277 Ty::Unknown 266 Ty::Unknown
@@ -281,27 +270,15 @@ impl Ty {
281 db: &impl HirDatabase, 270 db: &impl HirDatabase,
282 resolver: &Resolver, 271 resolver: &Resolver,
283 segment: &PathSegment, 272 segment: &PathSegment,
284 typable: TypableDef, 273 typable: TyDefId,
285 ) -> Ty { 274 ) -> Ty {
286 let ty = db.type_for_def(typable, Namespace::Types); 275 let generic_def = match typable {
287 let substs = Ty::substs_from_path_segment(db, resolver, segment, typable); 276 TyDefId::BuiltinType(_) => None,
288 ty.subst(&substs) 277 TyDefId::AdtId(it) => Some(it.into()),
289 } 278 TyDefId::TypeAliasId(it) => Some(it.into()),
290
291 pub(super) fn substs_from_path_segment(
292 db: &impl HirDatabase,
293 resolver: &Resolver,
294 segment: &PathSegment,
295 resolved: TypableDef,
296 ) -> Substs {
297 let def_generic: Option<GenericDefId> = match resolved {
298 TypableDef::Function(func) => Some(func.id.into()),
299 TypableDef::Adt(adt) => Some(adt.into()),
300 TypableDef::EnumVariant(var) => Some(var.parent_enum(db).id.into()),
301 TypableDef::TypeAlias(t) => Some(t.id.into()),
302 TypableDef::Const(_) | TypableDef::Static(_) | TypableDef::BuiltinType(_) => None,
303 }; 279 };
304 substs_from_path_segment(db, resolver, segment, def_generic, false) 280 let substs = substs_from_path_segment(db, resolver, segment, generic_def, false);
281 db.ty(typable).subst(&substs)
305 } 282 }
306 283
307 /// Collect generic arguments from a path into a `Substs`. See also 284 /// Collect generic arguments from a path into a `Substs`. See also
@@ -310,17 +287,18 @@ impl Ty {
310 db: &impl HirDatabase, 287 db: &impl HirDatabase,
311 resolver: &Resolver, 288 resolver: &Resolver,
312 path: &Path, 289 path: &Path,
313 resolved: TypableDef, 290 // Note that we don't call `db.value_type(resolved)` here,
291 // `ValueTyDefId` is just a convenient way to pass generics and
292 // special-case enum variants
293 resolved: ValueTyDefId,
314 ) -> Substs { 294 ) -> Substs {
315 let last = path.segments.last().expect("path should have at least one segment"); 295 let last = path.segments.last().expect("path should have at least one segment");
316 let segment = match resolved { 296 let (segment, generic_def) = match resolved {
317 TypableDef::Function(_) 297 ValueTyDefId::FunctionId(it) => (last, Some(it.into())),
318 | TypableDef::Adt(_) 298 ValueTyDefId::StructId(it) => (last, Some(it.into())),
319 | TypableDef::Const(_) 299 ValueTyDefId::ConstId(it) => (last, Some(it.into())),
320 | TypableDef::Static(_) 300 ValueTyDefId::StaticId(_) => (last, None),
321 | TypableDef::TypeAlias(_) 301 ValueTyDefId::EnumVariantId(var) => {
322 | TypableDef::BuiltinType(_) => last,
323 TypableDef::EnumVariant(_) => {
324 // the generic args for an enum variant may be either specified 302 // the generic args for an enum variant may be either specified
325 // on the segment referring to the enum, or on the segment 303 // on the segment referring to the enum, or on the segment
326 // referring to the variant. So `Option::<T>::None` and 304 // referring to the variant. So `Option::<T>::None` and
@@ -334,10 +312,10 @@ impl Ty {
334 // Option::None::<T> 312 // Option::None::<T>
335 last 313 last
336 }; 314 };
337 segment 315 (segment, Some(var.parent.into()))
338 } 316 }
339 }; 317 };
340 Ty::substs_from_path_segment(db, resolver, segment, resolved) 318 substs_from_path_segment(db, resolver, segment, generic_def, false)
341 } 319 }
342} 320}
343 321
@@ -422,7 +400,7 @@ impl TraitRef {
422 if let Some(self_ty) = explicit_self_ty { 400 if let Some(self_ty) = explicit_self_ty {
423 make_mut_slice(&mut substs.0)[0] = self_ty; 401 make_mut_slice(&mut substs.0)[0] = self_ty;
424 } 402 }
425 TraitRef { trait_: resolved, substs } 403 TraitRef { trait_: resolved.id, substs }
426 } 404 }
427 405
428 pub(crate) fn from_hir( 406 pub(crate) fn from_hir(
@@ -449,8 +427,8 @@ impl TraitRef {
449 substs_from_path_segment(db, resolver, segment, Some(resolved.id.into()), !has_self_param) 427 substs_from_path_segment(db, resolver, segment, Some(resolved.id.into()), !has_self_param)
450 } 428 }
451 429
452 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { 430 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: TraitId) -> TraitRef {
453 let substs = Substs::identity(&db.generic_params(trait_.id.into())); 431 let substs = Substs::identity(&db.generic_params(trait_.into()));
454 TraitRef { trait_, substs } 432 TraitRef { trait_, substs }
455 } 433 }
456 434
@@ -509,10 +487,11 @@ fn assoc_type_bindings_from_type_bound<'a>(
509 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 487 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
510 .map(move |(name, type_ref)| { 488 .map(move |(name, type_ref)| {
511 let associated_ty = 489 let associated_ty =
512 match trait_ref.trait_.associated_type_by_name_including_super_traits(db, &name) { 490 associated_type_by_name_including_super_traits(db, trait_ref.trait_, &name);
513 None => return GenericPredicate::Error, 491 let associated_ty = match associated_ty {
514 Some(t) => t.id, 492 None => return GenericPredicate::Error,
515 }; 493 Some(t) => t,
494 };
516 let projection_ty = 495 let projection_ty =
517 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; 496 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() };
518 let ty = Ty::from_hir(db, resolver, type_ref); 497 let ty = Ty::from_hir(db, resolver, type_ref);
@@ -521,33 +500,6 @@ fn assoc_type_bindings_from_type_bound<'a>(
521 }) 500 })
522} 501}
523 502
524/// Build the declared type of an item. This depends on the namespace; e.g. for
525/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
526/// the constructor function `(usize) -> Foo` which lives in the values
527/// namespace.
528pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty {
529 match (def, ns) {
530 (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f),
531 (TypableDef::Adt(Adt::Struct(s)), Namespace::Values) => type_for_struct_constructor(db, s),
532 (TypableDef::Adt(adt), Namespace::Types) => type_for_adt(db, adt),
533 (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v),
534 (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t),
535 (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c),
536 (TypableDef::Static(c), Namespace::Values) => type_for_static(db, c),
537 (TypableDef::BuiltinType(t), Namespace::Types) => type_for_builtin(t),
538
539 // 'error' cases:
540 (TypableDef::Function(_), Namespace::Types) => Ty::Unknown,
541 (TypableDef::Adt(Adt::Union(_)), Namespace::Values) => Ty::Unknown,
542 (TypableDef::Adt(Adt::Enum(_)), Namespace::Values) => Ty::Unknown,
543 (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown,
544 (TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown,
545 (TypableDef::Const(_), Namespace::Types) => Ty::Unknown,
546 (TypableDef::Static(_), Namespace::Types) => Ty::Unknown,
547 (TypableDef::BuiltinType(_), Namespace::Values) => Ty::Unknown,
548 }
549}
550
551/// Build the signature of a callable item (function, struct or enum variant). 503/// Build the signature of a callable item (function, struct or enum variant).
552pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { 504pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig {
553 match def { 505 match def {
@@ -646,24 +598,24 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig {
646 598
647/// Build the declared type of a function. This should not need to look at the 599/// Build the declared type of a function. This should not need to look at the
648/// function body. 600/// function body.
649fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { 601fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty {
650 let generics = db.generic_params(def.id.into()); 602 let generics = db.generic_params(def.into());
651 let substs = Substs::identity(&generics); 603 let substs = Substs::identity(&generics);
652 Ty::apply(TypeCtor::FnDef(def.id.into()), substs) 604 Ty::apply(TypeCtor::FnDef(def.into()), substs)
653} 605}
654 606
655/// Build the declared type of a const. 607/// Build the declared type of a const.
656fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { 608fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty {
657 let data = db.const_data(def.id); 609 let data = db.const_data(def);
658 let resolver = def.id.resolver(db); 610 let resolver = def.resolver(db);
659 611
660 Ty::from_hir(db, &resolver, &data.type_ref) 612 Ty::from_hir(db, &resolver, &data.type_ref)
661} 613}
662 614
663/// Build the declared type of a static. 615/// Build the declared type of a static.
664fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { 616fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty {
665 let data = db.static_data(def.id); 617 let data = db.static_data(def);
666 let resolver = def.id.resolver(db); 618 let resolver = def.resolver(db);
667 619
668 Ty::from_hir(db, &resolver, &data.type_ref) 620 Ty::from_hir(db, &resolver, &data.type_ref)
669} 621}
@@ -687,19 +639,19 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig
687 .iter() 639 .iter()
688 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 640 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
689 .collect::<Vec<_>>(); 641 .collect::<Vec<_>>();
690 let ret = type_for_adt(db, Struct::from(def)); 642 let ret = type_for_adt(db, def.into());
691 FnSig::from_params_and_return(params, ret) 643 FnSig::from_params_and_return(params, ret)
692} 644}
693 645
694/// Build the type of a tuple struct constructor. 646/// Build the type of a tuple struct constructor.
695fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 647fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty {
696 let struct_data = db.struct_data(def.id.into()); 648 let struct_data = db.struct_data(def.into());
697 if struct_data.variant_data.is_unit() { 649 if struct_data.variant_data.is_unit() {
698 return type_for_adt(db, def); // Unit struct 650 return type_for_adt(db, def.into()); // Unit struct
699 } 651 }
700 let generics = db.generic_params(def.id.into()); 652 let generics = db.generic_params(def.into());
701 let substs = Substs::identity(&generics); 653 let substs = Substs::identity(&generics);
702 Ty::apply(TypeCtor::FnDef(def.id.into()), substs) 654 Ty::apply(TypeCtor::FnDef(def.into()), substs)
703} 655}
704 656
705fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { 657fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig {
@@ -713,34 +665,33 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId
713 .collect::<Vec<_>>(); 665 .collect::<Vec<_>>();
714 let generics = db.generic_params(def.parent.into()); 666 let generics = db.generic_params(def.parent.into());
715 let substs = Substs::identity(&generics); 667 let substs = Substs::identity(&generics);
716 let ret = type_for_adt(db, Enum::from(def.parent)).subst(&substs); 668 let ret = type_for_adt(db, def.parent.into()).subst(&substs);
717 FnSig::from_params_and_return(params, ret) 669 FnSig::from_params_and_return(params, ret)
718} 670}
719 671
720/// Build the type of a tuple enum variant constructor. 672/// Build the type of a tuple enum variant constructor.
721fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { 673fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty {
722 let var_data = def.variant_data(db); 674 let enum_data = db.enum_data(def.parent);
675 let var_data = &enum_data.variants[def.local_id].variant_data;
723 if var_data.is_unit() { 676 if var_data.is_unit() {
724 return type_for_adt(db, def.parent_enum(db)); // Unit variant 677 return type_for_adt(db, def.parent.into()); // Unit variant
725 } 678 }
726 let generics = db.generic_params(def.parent_enum(db).id.into()); 679 let generics = db.generic_params(def.parent.into());
727 let substs = Substs::identity(&generics); 680 let substs = Substs::identity(&generics);
728 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) 681 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)
729} 682}
730 683
731fn type_for_adt(db: &impl HirDatabase, adt: impl Into<Adt>) -> Ty { 684fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty {
732 let adt = adt.into(); 685 let generics = db.generic_params(adt.into());
733 let adt_id: AdtId = adt.into(); 686 Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics))
734 let generics = db.generic_params(adt_id.into());
735 Ty::apply(TypeCtor::Adt(adt_id), Substs::identity(&generics))
736} 687}
737 688
738fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { 689fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty {
739 let generics = db.generic_params(t.id.into()); 690 let generics = db.generic_params(t.into());
740 let resolver = t.id.resolver(db); 691 let resolver = t.resolver(db);
741 let type_ref = t.type_ref(db); 692 let type_ref = &db.type_alias_data(t).type_ref;
742 let substs = Substs::identity(&generics); 693 let substs = Substs::identity(&generics);
743 let inner = Ty::from_hir(db, &resolver, &type_ref.unwrap_or(TypeRef::Error)); 694 let inner = Ty::from_hir(db, &resolver, type_ref.as_ref().unwrap_or(&TypeRef::Error));
744 inner.subst(&substs) 695 inner.subst(&substs)
745} 696}
746 697
@@ -807,3 +758,42 @@ impl From<CallableDef> for GenericDefId {
807 } 758 }
808 } 759 }
809} 760}
761
762#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
763pub enum TyDefId {
764 BuiltinType(BuiltinType),
765 AdtId(AdtId),
766 TypeAliasId(TypeAliasId),
767}
768impl_froms!(TyDefId: BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId);
769
770#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
771pub enum ValueTyDefId {
772 FunctionId(FunctionId),
773 StructId(StructId),
774 EnumVariantId(EnumVariantId),
775 ConstId(ConstId),
776 StaticId(StaticId),
777}
778impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId);
779
780/// Build the declared type of an item. This depends on the namespace; e.g. for
781/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
782/// the constructor function `(usize) -> Foo` which lives in the values
783/// namespace.
784pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty {
785 match def {
786 TyDefId::BuiltinType(it) => type_for_builtin(it),
787 TyDefId::AdtId(it) => type_for_adt(db, it),
788 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
789 }
790}
791pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty {
792 match def {
793 ValueTyDefId::FunctionId(it) => type_for_fn(db, it),
794 ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
795 ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
796 ValueTyDefId::ConstId(it) => type_for_const(db, it),
797 ValueTyDefId::StaticId(it) => type_for_static(db, it),
798 }
799}
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 489fcd64b..92645e2a5 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -6,9 +6,10 @@ use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, AssocItemId, AstItemDef, 9 lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, type_ref::Mutability,
10 HasModule, ImplId, TraitId, 10 AssocItemId, AstItemDef, HasModule, ImplId, TraitId,
11}; 11};
12use hir_expand::name::Name;
12use ra_db::CrateId; 13use ra_db::CrateId;
13use ra_prof::profile; 14use ra_prof::profile;
14use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
@@ -16,8 +17,8 @@ use rustc_hash::FxHashMap;
16use crate::{ 17use crate::{
17 db::HirDatabase, 18 db::HirDatabase,
18 ty::primitive::{FloatBitness, Uncertain}, 19 ty::primitive::{FloatBitness, Uncertain},
19 ty::{Ty, TypeCtor}, 20 ty::{utils::all_super_traits, Ty, TypeCtor},
20 AssocItem, Crate, Function, Mutability, Name, Trait, 21 AssocItem, Function,
21}; 22};
22 23
23use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef}; 24use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef};
@@ -68,7 +69,7 @@ impl CrateImplBlocks {
68 if let Some(tr) = 69 if let Some(tr) =
69 TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty)) 70 TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty))
70 { 71 {
71 res.impls_by_trait.entry(tr.trait_.id).or_default().push(impl_id); 72 res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
72 } 73 }
73 } 74 }
74 None => { 75 None => {
@@ -87,8 +88,8 @@ impl CrateImplBlocks {
87 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() 88 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied()
88 } 89 }
89 90
90 pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplId> + '_ { 91 pub fn lookup_impl_blocks_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
91 self.impls_by_trait.get(&tr.id).into_iter().flatten().copied() 92 self.impls_by_trait.get(&tr).into_iter().flatten().copied()
92 } 93 }
93 94
94 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { 95 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
@@ -96,51 +97,56 @@ impl CrateImplBlocks {
96 } 97 }
97} 98}
98 99
99fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { 100impl Ty {
100 // Types like slice can have inherent impls in several crates, (core and alloc). 101 pub(crate) fn def_crates(
101 // The corresponding impls are marked with lang items, so we can use them to find the required crates. 102 &self,
102 macro_rules! lang_item_crate { 103 db: &impl HirDatabase,
104 cur_crate: CrateId,
105 ) -> Option<ArrayVec<[CrateId; 2]>> {
106 // Types like slice can have inherent impls in several crates, (core and alloc).
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 {
103 ($($name:expr),+ $(,)?) => {{ 109 ($($name:expr),+ $(,)?) => {{
104 let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); 110 let mut v = ArrayVec::<[LangItemTarget; 2]>::new();
105 $( 111 $(
106 v.extend(db.lang_item(cur_crate.crate_id, $name.into())); 112 v.extend(db.lang_item(cur_crate, $name.into()));
107 )+ 113 )+
108 v 114 v
109 }}; 115 }};
110 } 116 }
111 117
112 let lang_item_targets = match ty { 118 let lang_item_targets = match self {
113 Ty::Apply(a_ty) => match a_ty.ctor { 119 Ty::Apply(a_ty) => match a_ty.ctor {
114 TypeCtor::Adt(def_id) => { 120 TypeCtor::Adt(def_id) => {
115 return Some(std::iter::once(def_id.module(db).krate.into()).collect()) 121 return Some(std::iter::once(def_id.module(db).krate).collect())
116 } 122 }
117 TypeCtor::Bool => lang_item_crate!("bool"), 123 TypeCtor::Bool => lang_item_crate!("bool"),
118 TypeCtor::Char => lang_item_crate!("char"), 124 TypeCtor::Char => lang_item_crate!("char"),
119 TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { 125 TypeCtor::Float(Uncertain::Known(f)) => match f.bitness {
120 // 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)
121 FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"), 127 FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"),
122 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,
123 }, 136 },
124 TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()),
125 TypeCtor::Str => lang_item_crate!("str_alloc", "str"),
126 TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"),
127 TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"),
128 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
129 _ => return None, 137 _ => return None,
130 }, 138 };
131 _ => return None, 139 let res = lang_item_targets
132 }; 140 .into_iter()
133 let res = lang_item_targets 141 .filter_map(|it| match it {
134 .into_iter() 142 LangItemTarget::ImplBlockId(it) => Some(it),
135 .filter_map(|it| match it { 143 _ => None,
136 LangItemTarget::ImplBlockId(it) => Some(it), 144 })
137 _ => None, 145 .map(|it| it.module(db).krate)
138 }) 146 .collect();
139 .map(|it| it.module(db).krate.into()) 147 Some(res)
140 .collect(); 148 }
141 Some(res)
142} 149}
143
144/// 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
145/// receiver type (but without autoref applied yet). 151/// receiver type (but without autoref applied yet).
146pub(crate) fn lookup_method( 152pub(crate) fn lookup_method(
@@ -193,14 +199,9 @@ pub(crate) fn iterate_method_candidates<T>(
193 let environment = TraitEnvironment::lower(db, resolver); 199 let environment = TraitEnvironment::lower(db, resolver);
194 let ty = InEnvironment { value: ty.clone(), environment }; 200 let ty = InEnvironment { value: ty.clone(), environment };
195 for derefed_ty in autoderef::autoderef(db, resolver.krate(), ty) { 201 for derefed_ty in autoderef::autoderef(db, resolver.krate(), ty) {
196 if let Some(result) = iterate_inherent_methods( 202 if let Some(result) =
197 &derefed_ty, 203 iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback)
198 db, 204 {
199 name,
200 mode,
201 krate.into(),
202 &mut callback,
203 ) {
204 return Some(result); 205 return Some(result);
205 } 206 }
206 if let Some(result) = iterate_trait_method_candidates( 207 if let Some(result) = iterate_trait_method_candidates(
@@ -249,19 +250,18 @@ fn iterate_trait_method_candidates<T>(
249 let traits_from_env = env 250 let traits_from_env = env
250 .trait_predicates_for_self_ty(&ty.value) 251 .trait_predicates_for_self_ty(&ty.value)
251 .map(|tr| tr.trait_) 252 .map(|tr| tr.trait_)
252 .flat_map(|t| t.all_super_traits(db)); 253 .flat_map(|t| all_super_traits(db, t));
253 let traits = inherent_trait 254 let traits =
254 .chain(traits_from_env) 255 inherent_trait.chain(traits_from_env).chain(resolver.traits_in_scope(db).into_iter());
255 .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from));
256 'traits: for t in traits { 256 'traits: for t in traits {
257 let data = db.trait_data(t.id); 257 let data = db.trait_data(t);
258 258
259 // we'll be lazy about checking whether the type implements the 259 // we'll be lazy about checking whether the type implements the
260 // trait, but if we find out it doesn't, we'll skip the rest of the 260 // trait, but if we find out it doesn't, we'll skip the rest of the
261 // iteration 261 // iteration
262 let mut known_implemented = false; 262 let mut known_implemented = false;
263 for &item in data.items.iter() { 263 for (_name, item) in data.items.iter() {
264 if !is_valid_candidate(db, name, mode, item.into()) { 264 if !is_valid_candidate(db, name, mode, (*item).into()) {
265 continue; 265 continue;
266 } 266 }
267 if !known_implemented { 267 if !known_implemented {
@@ -271,7 +271,7 @@ fn iterate_trait_method_candidates<T>(
271 } 271 }
272 } 272 }
273 known_implemented = true; 273 known_implemented = true;
274 if let Some(result) = callback(&ty.value, item.into()) { 274 if let Some(result) = callback(&ty.value, (*item).into()) {
275 return Some(result); 275 return Some(result);
276 } 276 }
277 } 277 }
@@ -284,11 +284,11 @@ fn iterate_inherent_methods<T>(
284 db: &impl HirDatabase, 284 db: &impl HirDatabase,
285 name: Option<&Name>, 285 name: Option<&Name>,
286 mode: LookupMode, 286 mode: LookupMode,
287 krate: Crate, 287 krate: CrateId,
288 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, 288 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
289) -> Option<T> { 289) -> Option<T> {
290 for krate in def_crates(db, krate, &ty.value)? { 290 for krate in ty.value.def_crates(db, krate)? {
291 let impls = db.impls_in_crate(krate.crate_id); 291 let impls = db.impls_in_crate(krate);
292 292
293 for impl_block in impls.lookup_impl_blocks(&ty.value) { 293 for impl_block in impls.lookup_impl_blocks(&ty.value) {
294 for &item in db.impl_data(impl_block).items.iter() { 294 for &item in db.impl_data(impl_block).items.iter() {
@@ -328,8 +328,8 @@ pub(crate) fn implements_trait(
328 ty: &Canonical<Ty>, 328 ty: &Canonical<Ty>,
329 db: &impl HirDatabase, 329 db: &impl HirDatabase,
330 resolver: &Resolver, 330 resolver: &Resolver,
331 krate: Crate, 331 krate: CrateId,
332 trait_: Trait, 332 trait_: TraitId,
333) -> bool { 333) -> bool {
334 if ty.value.inherent_trait() == Some(trait_) { 334 if ty.value.inherent_trait() == Some(trait_) {
335 // FIXME this is a bit of a hack, since Chalk should say the same thing 335 // FIXME this is a bit of a hack, since Chalk should say the same thing
@@ -338,45 +338,21 @@ pub(crate) fn implements_trait(
338 } 338 }
339 let env = TraitEnvironment::lower(db, resolver); 339 let env = TraitEnvironment::lower(db, resolver);
340 let goal = generic_implements_goal(db, env, trait_, ty.clone()); 340 let goal = generic_implements_goal(db, env, trait_, ty.clone());
341 let solution = db.trait_solve(krate, goal); 341 let solution = db.trait_solve(krate.into(), goal);
342 342
343 solution.is_some() 343 solution.is_some()
344} 344}
345 345
346impl Ty {
347 // This would be nicer if it just returned an iterator, but that runs into
348 // lifetime problems, because we need to borrow temp `CrateImplBlocks`.
349 pub fn iterate_impl_items<T>(
350 self,
351 db: &impl HirDatabase,
352 krate: Crate,
353 mut callback: impl FnMut(AssocItem) -> Option<T>,
354 ) -> Option<T> {
355 for krate in def_crates(db, krate, &self)? {
356 let impls = db.impls_in_crate(krate.crate_id);
357
358 for impl_block in impls.lookup_impl_blocks(&self) {
359 for &item in db.impl_data(impl_block).items.iter() {
360 if let Some(result) = callback(item.into()) {
361 return Some(result);
362 }
363 }
364 }
365 }
366 None
367 }
368}
369
370/// 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
371/// for all other parameters, to query Chalk with it. 347/// for all other parameters, to query Chalk with it.
372fn generic_implements_goal( 348fn generic_implements_goal(
373 db: &impl HirDatabase, 349 db: &impl HirDatabase,
374 env: Arc<TraitEnvironment>, 350 env: Arc<TraitEnvironment>,
375 trait_: Trait, 351 trait_: TraitId,
376 self_ty: Canonical<Ty>, 352 self_ty: Canonical<Ty>,
377) -> Canonical<InEnvironment<super::Obligation>> { 353) -> Canonical<InEnvironment<super::Obligation>> {
378 let num_vars = self_ty.num_vars; 354 let num_vars = self_ty.num_vars;
379 let substs = super::Substs::build_for_def(db, trait_.id) 355 let substs = super::Substs::build_for_def(db, trait_)
380 .push(self_ty.value) 356 .push(self_ty.value)
381 .fill_with_bound_vars(num_vars as u32) 357 .fill_with_bound_vars(num_vars as u32)
382 .build(); 358 .build();
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 2eeb03099..637e21e9c 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -2,14 +2,15 @@
2use std::sync::{Arc, Mutex}; 2use std::sync::{Arc, Mutex};
3 3
4use chalk_ir::{cast::Cast, family::ChalkIr}; 4use chalk_ir::{cast::Cast, family::ChalkIr};
5use hir_def::DefWithBodyId; 5use hir_def::{expr::ExprId, DefWithBodyId, TraitId};
6use log::debug; 6use log::debug;
7use ra_db::{impl_intern_key, salsa}; 7use ra_db::{impl_intern_key, salsa, CrateId};
8use ra_prof::profile; 8use ra_prof::profile;
9use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
10 10
11use crate::{db::HirDatabase, Crate, ImplBlock, TypeAlias};
12
11use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
12use crate::{db::HirDatabase, expr::ExprId, Crate, ImplBlock, Trait, TypeAlias};
13 14
14use self::chalk::{from_chalk, ToChalk}; 15use self::chalk::{from_chalk, ToChalk};
15 16
@@ -76,8 +77,8 @@ pub(crate) fn trait_solver_query(
76/// Collects impls for the given trait in the whole dependency tree of `krate`. 77/// Collects impls for the given trait in the whole dependency tree of `krate`.
77pub(crate) fn impls_for_trait_query( 78pub(crate) fn impls_for_trait_query(
78 db: &impl HirDatabase, 79 db: &impl HirDatabase,
79 krate: Crate, 80 krate: CrateId,
80 trait_: Trait, 81 trait_: TraitId,
81) -> Arc<[ImplBlock]> { 82) -> Arc<[ImplBlock]> {
82 let mut impls = FxHashSet::default(); 83 let mut impls = FxHashSet::default();
83 // We call the query recursively here. On the one hand, this means we can 84 // We call the query recursively here. On the one hand, this means we can
@@ -85,10 +86,10 @@ pub(crate) fn impls_for_trait_query(
85 // will only ever get called for a few crates near the root of the tree (the 86 // will only ever get called for a few crates near the root of the tree (the
86 // ones the user is editing), so this may actually be a waste of memory. I'm 87 // ones the user is editing), so this may actually be a waste of memory. I'm
87 // doing it like this mainly for simplicity for now. 88 // doing it like this mainly for simplicity for now.
88 for dep in krate.dependencies(db) { 89 for dep in db.crate_graph().dependencies(krate) {
89 impls.extend(db.impls_for_trait(dep.krate, trait_).iter()); 90 impls.extend(db.impls_for_trait(dep.crate_id, trait_).iter());
90 } 91 }
91 let crate_impl_blocks = db.impls_in_crate(krate.crate_id); 92 let crate_impl_blocks = db.impls_in_crate(krate);
92 impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(trait_).map(ImplBlock::from)); 93 impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(trait_).map(ImplBlock::from));
93 impls.into_iter().collect() 94 impls.into_iter().collect()
94} 95}
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 06388a3ce..d879382a0 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -9,7 +9,9 @@ use chalk_ir::{
9}; 9};
10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11 11
12use hir_def::{lang_item::LangItemTarget, ContainerId, GenericDefId, Lookup, TypeAliasId}; 12use hir_def::{
13 lang_item::LangItemTarget, AstItemDef, ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId,
14};
13use hir_expand::name; 15use hir_expand::name;
14 16
15use ra_db::salsa::{InternId, InternKey}; 17use ra_db::salsa::{InternId, InternKey};
@@ -19,7 +21,7 @@ use crate::{
19 db::HirDatabase, 21 db::HirDatabase,
20 ty::display::HirDisplay, 22 ty::display::HirDisplay,
21 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, 23 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
22 Crate, ImplBlock, Trait, TypeAlias, 24 Crate, ImplBlock, TypeAlias,
23}; 25};
24 26
25/// This represents a trait whose name we could not resolve. 27/// This represents a trait whose name we could not resolve.
@@ -167,15 +169,15 @@ impl ToChalk for TraitRef {
167 } 169 }
168} 170}
169 171
170impl ToChalk for Trait { 172impl ToChalk for TraitId {
171 type Chalk = chalk_ir::TraitId; 173 type Chalk = chalk_ir::TraitId;
172 174
173 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId { 175 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId {
174 chalk_ir::TraitId(id_to_chalk(self.id)) 176 chalk_ir::TraitId(id_to_chalk(self))
175 } 177 }
176 178
177 fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> Trait { 179 fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> TraitId {
178 Trait { id: id_from_chalk(trait_id.0) } 180 id_from_chalk(trait_id.0)
179 } 181 }
180} 182}
181 183
@@ -443,10 +445,10 @@ where
443 if trait_id == UNKNOWN_TRAIT { 445 if trait_id == UNKNOWN_TRAIT {
444 return Vec::new(); 446 return Vec::new();
445 } 447 }
446 let trait_: Trait = from_chalk(self.db, trait_id); 448 let trait_: TraitId = from_chalk(self.db, trait_id);
447 let mut result: Vec<_> = self 449 let mut result: Vec<_> = self
448 .db 450 .db
449 .impls_for_trait(self.krate, trait_) 451 .impls_for_trait(self.krate.crate_id, trait_.into())
450 .iter() 452 .iter()
451 .copied() 453 .copied()
452 .map(Impl::ImplBlock) 454 .map(Impl::ImplBlock)
@@ -516,7 +518,7 @@ pub(crate) fn associated_ty_data_query(
516 where_clauses: vec![], 518 where_clauses: vec![],
517 }; 519 };
518 let datum = AssociatedTyDatum { 520 let datum = AssociatedTyDatum {
519 trait_id: Trait::from(trait_).to_chalk(db), 521 trait_id: trait_.to_chalk(db),
520 id, 522 id,
521 name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()), 523 name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()),
522 binders: make_binders(bound_data, generic_params.count_params_including_parent()), 524 binders: make_binders(bound_data, generic_params.count_params_including_parent()),
@@ -548,29 +550,23 @@ pub(crate) fn trait_datum_query(
548 associated_ty_ids: vec![], 550 associated_ty_ids: vec![],
549 }); 551 });
550 } 552 }
551 let trait_: Trait = from_chalk(db, trait_id); 553 let trait_: TraitId = from_chalk(db, trait_id);
552 debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); 554 let trait_data = db.trait_data(trait_);
553 let generic_params = db.generic_params(trait_.id.into()); 555 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
556 let generic_params = db.generic_params(trait_.into());
554 let bound_vars = Substs::bound_vars(&generic_params); 557 let bound_vars = Substs::bound_vars(&generic_params);
555 let flags = chalk_rust_ir::TraitFlags { 558 let flags = chalk_rust_ir::TraitFlags {
556 auto: trait_.is_auto(db), 559 auto: trait_data.auto,
557 upstream: trait_.module(db).krate() != krate, 560 upstream: trait_.module(db).krate != krate.crate_id,
558 non_enumerable: true, 561 non_enumerable: true,
559 coinductive: false, // only relevant for Chalk testing 562 coinductive: false, // only relevant for Chalk testing
560 // FIXME set these flags correctly 563 // FIXME set these flags correctly
561 marker: false, 564 marker: false,
562 fundamental: false, 565 fundamental: false,
563 }; 566 };
564 let where_clauses = convert_where_clauses(db, trait_.id.into(), &bound_vars); 567 let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
565 let associated_ty_ids = trait_ 568 let associated_ty_ids =
566 .items(db) 569 trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect();
567 .into_iter()
568 .filter_map(|trait_item| match trait_item {
569 crate::AssocItem::TypeAlias(type_alias) => Some(type_alias.id),
570 _ => None,
571 })
572 .map(|type_alias| type_alias.to_chalk(db))
573 .collect();
574 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; 570 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses };
575 let trait_datum = TraitDatum { 571 let trait_datum = TraitDatum {
576 id: trait_id, 572 id: trait_id,
@@ -661,6 +657,7 @@ fn impl_block_datum(
661 }; 657 };
662 658
663 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses }; 659 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses };
660 let trait_data = db.trait_data(trait_);
664 let associated_ty_value_ids = impl_block 661 let associated_ty_value_ids = impl_block
665 .items(db) 662 .items(db)
666 .into_iter() 663 .into_iter()
@@ -670,7 +667,7 @@ fn impl_block_datum(
670 }) 667 })
671 .filter(|type_alias| { 668 .filter(|type_alias| {
672 // don't include associated types that don't exist in the trait 669 // don't include associated types that don't exist in the trait
673 trait_.associated_type_by_name(db, &type_alias.name(db)).is_some() 670 trait_data.associated_type_by_name(&type_alias.name(db)).is_some()
674 }) 671 })
675 .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db)) 672 .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db))
676 .collect(); 673 .collect();
@@ -713,7 +710,7 @@ fn closure_fn_trait_impl_datum(
713 // and don't want to return a valid value only to find out later that FnOnce 710 // and don't want to return a valid value only to find out later that FnOnce
714 // is broken 711 // is broken
715 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; 712 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
716 fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; 713 let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?;
717 714
718 let num_args: u16 = match &db.body(data.def.into())[data.expr] { 715 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
719 crate::expr::Expr::Lambda { args, .. } => args.len() as u16, 716 crate::expr::Expr::Lambda { args, .. } => args.len() as u16,
@@ -735,8 +732,8 @@ fn closure_fn_trait_impl_datum(
735 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); 732 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
736 733
737 let trait_ref = TraitRef { 734 let trait_ref = TraitRef {
738 trait_, 735 trait_: trait_.into(),
739 substs: Substs::build_for_def(db, trait_.id).push(self_ty).push(arg_ty).build(), 736 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
740 }; 737 };
741 738
742 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); 739 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db);
@@ -783,13 +780,13 @@ fn type_alias_associated_ty_value(
783 .target_trait_ref(db) 780 .target_trait_ref(db)
784 .expect("assoc ty value should not exist") // we don't return any assoc ty values if the impl'd trait can't be resolved 781 .expect("assoc ty value should not exist") // we don't return any assoc ty values if the impl'd trait can't be resolved
785 .trait_; 782 .trait_;
786 let assoc_ty = trait_ 783 let assoc_ty = db
787 .associated_type_by_name(db, &type_alias.name(db)) 784 .trait_data(trait_)
788 .expect("assoc ty value should not exist") // validated when building the impl data as well 785 .associated_type_by_name(&type_alias.name(db))
789 .id; 786 .expect("assoc ty value should not exist"); // validated when building the impl data as well
790 let generic_params = db.generic_params(impl_block.id.into()); 787 let generic_params = db.generic_params(impl_block.id.into());
791 let bound_vars = Substs::bound_vars(&generic_params); 788 let bound_vars = Substs::bound_vars(&generic_params);
792 let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); 789 let ty = db.ty(type_alias.id.into()).subst(&bound_vars);
793 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; 790 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
794 let value = chalk_rust_ir::AssociatedTyValue { 791 let value = chalk_rust_ir::AssociatedTyValue {
795 impl_id, 792 impl_id,
@@ -819,10 +816,10 @@ fn closure_fn_trait_output_assoc_ty_value(
819 let fn_once_trait = 816 let fn_once_trait =
820 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); 817 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist");
821 818
822 let output_ty_id = fn_once_trait 819 let output_ty_id = db
823 .associated_type_by_name(db, &name::OUTPUT_TYPE) 820 .trait_data(fn_once_trait)
824 .expect("assoc ty value should not exist") 821 .associated_type_by_name(&name::OUTPUT_TYPE)
825 .id; 822 .expect("assoc ty value should not exist");
826 823
827 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; 824 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) };
828 825
@@ -834,10 +831,10 @@ fn closure_fn_trait_output_assoc_ty_value(
834 Arc::new(value) 831 Arc::new(value)
835} 832}
836 833
837fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { 834fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<TraitId> {
838 let target = db.lang_item(krate.crate_id, fn_trait.lang_item_name().into())?; 835 let target = db.lang_item(krate.crate_id, fn_trait.lang_item_name().into())?;
839 match target { 836 match target {
840 LangItemTarget::TraitId(t) => Some(t.into()), 837 LangItemTarget::TraitId(t) => Some(t),
841 _ => None, 838 _ => None,
842 } 839 }
843} 840}
diff --git a/crates/ra_hir/src/ty/utils.rs b/crates/ra_hir/src/ty/utils.rs
new file mode 100644
index 000000000..80ffceb4b
--- /dev/null
+++ b/crates/ra_hir/src/ty/utils.rs
@@ -0,0 +1,63 @@
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`).
3
4use hir_def::{
5 db::DefDatabase,
6 resolver::{HasResolver, TypeNs},
7 type_ref::TypeRef,
8 TraitId, TypeAliasId,
9};
10use hir_expand::name::{self, Name};
11
12// FIXME: this is wrong, b/c it can't express `trait T: PartialEq<()>`.
13// We should return a `TraitREf` here.
14fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
15 let resolver = trait_.resolver(db);
16 // returning the iterator directly doesn't easily work because of
17 // lifetime problems, but since there usually shouldn't be more than a
18 // few direct traits this should be fine (we could even use some kind of
19 // SmallVec if performance is a concern)
20 db.generic_params(trait_.into())
21 .where_predicates
22 .iter()
23 .filter_map(|pred| match &pred.type_ref {
24 TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
25 _ => None,
26 })
27 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
28 Some(TypeNs::TraitId(t)) => Some(t),
29 _ => None,
30 })
31 .collect()
32}
33
34/// Returns an iterator over the whole super trait hierarchy (including the
35/// trait itself).
36pub(super) fn all_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
37 // we need to take care a bit here to avoid infinite loops in case of cycles
38 // (i.e. if we have `trait A: B; trait B: A;`)
39 let mut result = vec![trait_];
40 let mut i = 0;
41 while i < result.len() {
42 let t = result[i];
43 // yeah this is quadratic, but trait hierarchies should be flat
44 // enough that this doesn't matter
45 for tt in direct_super_traits(db, t) {
46 if !result.contains(&tt) {
47 result.push(tt);
48 }
49 }
50 i += 1;
51 }
52 result
53}
54
55pub(super) fn associated_type_by_name_including_super_traits(
56 db: &impl DefDatabase,
57 trait_: TraitId,
58 name: &Name,
59) -> Option<TypeAliasId> {
60 all_super_traits(db, trait_)
61 .into_iter()
62 .find_map(|t| db.trait_data(t).associated_type_by_name(name))
63}