diff options
26 files changed, 552 insertions, 548 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)] |
1044 | pub struct Type { | 984 | pub 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 | ||
1049 | 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 | |||
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 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{GenericDefId, LocalStructFieldId, TraitId, VariantId}; | ||
5 | use ra_arena::map::ArenaMap; | 6 | use ra_arena::map::ArenaMap; |
6 | use ra_db::{salsa, CrateId}; | 7 | use 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 | ||
18 | pub use hir_def::{ | 19 | pub 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 | }; |
29 | pub use hir_expand::db::{ | 26 | pub 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 | ||
18 | pub use hir_def::{ | 18 | pub 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 | }; |
16 | use hir_expand::{ | 16 | use 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 | }; |
20 | use ra_syntax::{ | 19 | use 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; | |||
9 | mod lower; | 9 | mod lower; |
10 | mod infer; | 10 | mod infer; |
11 | pub(crate) mod display; | 11 | pub(crate) mod display; |
12 | pub(crate) mod utils; | ||
12 | 13 | ||
13 | #[cfg(test)] | 14 | #[cfg(test)] |
14 | mod tests; | 15 | mod tests; |
@@ -18,14 +19,17 @@ use std::sync::Arc; | |||
18 | use std::{fmt, iter, mem}; | 19 | use std::{fmt, iter, mem}; |
19 | 20 | ||
20 | use hir_def::{ | 21 | use 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 | }; |
25 | use hir_expand::name::Name; | ||
24 | use ra_db::{impl_intern_key, salsa}; | 26 | use ra_db::{impl_intern_key, salsa}; |
25 | 27 | ||
26 | use crate::{ | 28 | use 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 | }; |
30 | use display::{HirDisplay, HirFormatter}; | 34 | use display::{HirDisplay, HirFormatter}; |
31 | 35 | ||
@@ -34,8 +38,8 @@ pub(crate) use infer::{infer_query, InferTy, InferenceResult}; | |||
34 | pub use lower::CallableDef; | 38 | pub use lower::CallableDef; |
35 | pub(crate) use lower::{ | 39 | pub(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 | }; |
40 | pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; | 44 | pub(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)] |
445 | pub struct TraitRef { | 449 | pub 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; | |||
10 | use log::{info, warn}; | 10 | use log::{info, warn}; |
11 | use ra_db::CrateId; | 11 | use ra_db::CrateId; |
12 | 12 | ||
13 | use crate::{db::HirDatabase, Trait}; | 13 | use crate::db::HirDatabase; |
14 | 14 | ||
15 | use super::{ | 15 | use 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 | ||
36 | use super::{ | 36 | use 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 | }; |
41 | use crate::{ | 41 | use 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 | ||
49 | macro_rules! ty_app { | 49 | macro_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 | ||
8 | use crate::{ | 8 | use 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 | }; |
20 | use ra_arena::map::ArenaMap; | 20 | use ra_arena::map::ArenaMap; |
21 | use ra_db::CrateId; | 21 | use 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)] | ||
42 | pub 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 | |||
49 | impl Ty { | 38 | impl 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. | ||
528 | pub(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). |
552 | pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { | 504 | pub(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. |
649 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | 601 | fn 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. |
656 | fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { | 608 | fn 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. |
664 | fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { | 616 | fn 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. |
695 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | 647 | fn 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 | ||
705 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { | 657 | fn 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. |
721 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { | 673 | fn 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 | ||
731 | fn type_for_adt(db: &impl HirDatabase, adt: impl Into<Adt>) -> Ty { | 684 | fn 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 | ||
738 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { | 689 | fn 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)] | ||
763 | pub enum TyDefId { | ||
764 | BuiltinType(BuiltinType), | ||
765 | AdtId(AdtId), | ||
766 | TypeAliasId(TypeAliasId), | ||
767 | } | ||
768 | impl_froms!(TyDefId: BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId); | ||
769 | |||
770 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
771 | pub enum ValueTyDefId { | ||
772 | FunctionId(FunctionId), | ||
773 | StructId(StructId), | ||
774 | EnumVariantId(EnumVariantId), | ||
775 | ConstId(ConstId), | ||
776 | StaticId(StaticId), | ||
777 | } | ||
778 | impl_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. | ||
784 | pub(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 | } | ||
791 | pub(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 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::{ | 8 | use 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 | }; |
12 | use hir_expand::name::Name; | ||
12 | use ra_db::CrateId; | 13 | use ra_db::CrateId; |
13 | use ra_prof::profile; | 14 | use ra_prof::profile; |
14 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::FxHashMap; |
@@ -16,8 +17,8 @@ use rustc_hash::FxHashMap; | |||
16 | use crate::{ | 17 | use 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 | ||
23 | use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef}; | 24 | use 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 | ||
99 | fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { | 100 | impl 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). |
146 | pub(crate) fn lookup_method( | 152 | pub(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 | ||
346 | impl 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. |
372 | fn generic_implements_goal( | 348 | fn 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 @@ | |||
2 | use std::sync::{Arc, Mutex}; | 2 | use std::sync::{Arc, Mutex}; |
3 | 3 | ||
4 | use chalk_ir::{cast::Cast, family::ChalkIr}; | 4 | use chalk_ir::{cast::Cast, family::ChalkIr}; |
5 | use hir_def::DefWithBodyId; | 5 | use hir_def::{expr::ExprId, DefWithBodyId, TraitId}; |
6 | use log::debug; | 6 | use log::debug; |
7 | use ra_db::{impl_intern_key, salsa}; | 7 | use ra_db::{impl_intern_key, salsa, CrateId}; |
8 | use ra_prof::profile; | 8 | use ra_prof::profile; |
9 | use rustc_hash::FxHashSet; | 9 | use rustc_hash::FxHashSet; |
10 | 10 | ||
11 | use crate::{db::HirDatabase, Crate, ImplBlock, TypeAlias}; | ||
12 | |||
11 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; | 13 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; |
12 | use crate::{db::HirDatabase, expr::ExprId, Crate, ImplBlock, Trait, TypeAlias}; | ||
13 | 14 | ||
14 | use self::chalk::{from_chalk, ToChalk}; | 15 | use 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`. |
77 | pub(crate) fn impls_for_trait_query( | 78 | pub(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 | }; |
10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; |
11 | 11 | ||
12 | use hir_def::{lang_item::LangItemTarget, ContainerId, GenericDefId, Lookup, TypeAliasId}; | 12 | use hir_def::{ |
13 | lang_item::LangItemTarget, AstItemDef, ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, | ||
14 | }; | ||
13 | use hir_expand::name; | 15 | use hir_expand::name; |
14 | 16 | ||
15 | use ra_db::salsa::{InternId, InternKey}; | 17 | use 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 | ||
170 | impl ToChalk for Trait { | 172 | impl 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 | ||
837 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { | 834 | fn 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 | |||
4 | use hir_def::{ | ||
5 | db::DefDatabase, | ||
6 | resolver::{HasResolver, TypeNs}, | ||
7 | type_ref::TypeRef, | ||
8 | TraitId, TypeAliasId, | ||
9 | }; | ||
10 | use 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. | ||
14 | fn 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). | ||
36 | pub(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 | |||
55 | pub(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 | } | ||
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index d77ccb272..78a532bdd 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -6,8 +6,7 @@ pub mod scope; | |||
6 | use std::{ops::Index, sync::Arc}; | 6 | use std::{ops::Index, sync::Arc}; |
7 | 7 | ||
8 | use hir_expand::{ | 8 | use hir_expand::{ |
9 | either::Either, hygiene::Hygiene, AstId, HirFileId, MacroCallLoc, MacroDefId, MacroFileKind, | 9 | either::Either, hygiene::Hygiene, AstId, HirFileId, MacroDefId, MacroFileKind, Source, |
10 | Source, | ||
11 | }; | 10 | }; |
12 | use ra_arena::{map::ArenaMap, Arena}; | 11 | use ra_arena::{map::ArenaMap, Arena}; |
13 | use ra_syntax::{ast, AstNode, AstPtr}; | 12 | use ra_syntax::{ast, AstNode, AstPtr}; |
@@ -47,7 +46,7 @@ impl Expander { | |||
47 | 46 | ||
48 | if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { | 47 | if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { |
49 | if let Some(def) = self.resolve_path_as_macro(db, &path) { | 48 | if let Some(def) = self.resolve_path_as_macro(db, &path) { |
50 | let call_id = db.intern_macro(MacroCallLoc { def, ast_id }); | 49 | let call_id = def.as_call_id(db, ast_id); |
51 | let file_id = call_id.as_file(MacroFileKind::Expr); | 50 | let file_id = call_id.as_file(MacroFileKind::Expr); |
52 | if let Some(node) = db.parse_or_expand(file_id) { | 51 | if let Some(node) = db.parse_or_expand(file_id) { |
53 | if let Some(expr) = ast::Expr::cast(node) { | 52 | if let Some(expr) = ast::Expr::cast(node) { |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 68bea34df..813099a05 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -87,7 +87,7 @@ impl TypeAliasData { | |||
87 | #[derive(Debug, Clone, PartialEq, Eq)] | 87 | #[derive(Debug, Clone, PartialEq, Eq)] |
88 | pub struct TraitData { | 88 | pub struct TraitData { |
89 | pub name: Option<Name>, | 89 | pub name: Option<Name>, |
90 | pub items: Vec<AssocItemId>, | 90 | pub items: Vec<(Name, AssocItemId)>, |
91 | pub auto: bool, | 91 | pub auto: bool, |
92 | } | 92 | } |
93 | 93 | ||
@@ -97,28 +97,42 @@ impl TraitData { | |||
97 | let name = src.value.name().map(|n| n.as_name()); | 97 | let name = src.value.name().map(|n| n.as_name()); |
98 | let auto = src.value.is_auto(); | 98 | let auto = src.value.is_auto(); |
99 | let ast_id_map = db.ast_id_map(src.file_id); | 99 | let ast_id_map = db.ast_id_map(src.file_id); |
100 | |||
101 | let container = ContainerId::TraitId(tr); | ||
100 | let items = if let Some(item_list) = src.value.item_list() { | 102 | let items = if let Some(item_list) = src.value.item_list() { |
101 | item_list | 103 | item_list |
102 | .impl_items() | 104 | .impl_items() |
103 | .map(|item_node| match item_node { | 105 | .map(|item_node| match item_node { |
104 | ast::ImplItem::FnDef(it) => FunctionLoc { | 106 | ast::ImplItem::FnDef(it) => { |
105 | container: ContainerId::TraitId(tr), | 107 | let name = it.name().map(|it| it.as_name()).unwrap_or_else(Name::missing); |
106 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | 108 | let def = FunctionLoc { |
109 | container, | ||
110 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | ||
111 | } | ||
112 | .intern(db) | ||
113 | .into(); | ||
114 | (name, def) | ||
107 | } | 115 | } |
108 | .intern(db) | 116 | ast::ImplItem::ConstDef(it) => { |
109 | .into(), | 117 | let name = it.name().map(|it| it.as_name()).unwrap_or_else(Name::missing); |
110 | ast::ImplItem::ConstDef(it) => ConstLoc { | 118 | let def = ConstLoc { |
111 | container: ContainerId::TraitId(tr), | 119 | container, |
112 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | 120 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), |
121 | } | ||
122 | .intern(db) | ||
123 | .into(); | ||
124 | (name, def) | ||
113 | } | 125 | } |
114 | .intern(db) | 126 | ast::ImplItem::TypeAliasDef(it) => { |
115 | .into(), | 127 | let name = it.name().map(|it| it.as_name()).unwrap_or_else(Name::missing); |
116 | ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc { | 128 | let def = TypeAliasLoc { |
117 | container: ContainerId::TraitId(tr), | 129 | container, |
118 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | 130 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), |
131 | } | ||
132 | .intern(db) | ||
133 | .into(); | ||
134 | (name, def) | ||
119 | } | 135 | } |
120 | .intern(db) | ||
121 | .into(), | ||
122 | }) | 136 | }) |
123 | .collect() | 137 | .collect() |
124 | } else { | 138 | } else { |
@@ -128,11 +142,18 @@ impl TraitData { | |||
128 | } | 142 | } |
129 | 143 | ||
130 | pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { | 144 | pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { |
131 | self.items.iter().filter_map(|item| match item { | 145 | self.items.iter().filter_map(|(_name, item)| match item { |
132 | AssocItemId::TypeAliasId(t) => Some(*t), | 146 | AssocItemId::TypeAliasId(t) => Some(*t), |
133 | _ => None, | 147 | _ => None, |
134 | }) | 148 | }) |
135 | } | 149 | } |
150 | |||
151 | pub fn associated_type_by_name(&self, name: &Name) -> Option<TypeAliasId> { | ||
152 | self.items.iter().find_map(|(item_name, item)| match item { | ||
153 | AssocItemId::TypeAliasId(t) if item_name == name => Some(*t), | ||
154 | _ => None, | ||
155 | }) | ||
156 | } | ||
136 | } | 157 | } |
137 | 158 | ||
138 | #[derive(Debug, Clone, PartialEq, Eq)] | 159 | #[derive(Debug, Clone, PartialEq, Eq)] |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 4ff6f72cf..ea3abfdae 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -6,7 +6,7 @@ | |||
6 | use hir_expand::{ | 6 | use hir_expand::{ |
7 | builtin_macro::find_builtin_macro, | 7 | builtin_macro::find_builtin_macro, |
8 | name::{self, AsName, Name}, | 8 | name::{self, AsName, Name}, |
9 | HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, MacroFileKind, | 9 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, MacroFileKind, |
10 | }; | 10 | }; |
11 | use ra_cfg::CfgOptions; | 11 | use ra_cfg::CfgOptions; |
12 | use ra_db::{CrateId, FileId}; | 12 | use ra_db::{CrateId, FileId}; |
@@ -480,7 +480,7 @@ where | |||
480 | ); | 480 | ); |
481 | 481 | ||
482 | if let Some(def) = resolved_res.resolved_def.take_macros() { | 482 | if let Some(def) = resolved_res.resolved_def.take_macros() { |
483 | let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id: *ast_id }); | 483 | let call_id = def.as_call_id(self.db, *ast_id); |
484 | resolved.push((*module_id, call_id, def)); | 484 | resolved.push((*module_id, call_id, def)); |
485 | res = ReachedFixedPoint::No; | 485 | res = ReachedFixedPoint::No; |
486 | return false; | 486 | return false; |
@@ -773,8 +773,7 @@ where | |||
773 | if let Some(macro_def) = mac.path.as_ident().and_then(|name| { | 773 | if let Some(macro_def) = mac.path.as_ident().and_then(|name| { |
774 | self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) | 774 | self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) |
775 | }) { | 775 | }) { |
776 | let macro_call_id = | 776 | let macro_call_id = macro_def.as_call_id(self.def_collector.db, ast_id); |
777 | self.def_collector.db.intern_macro(MacroCallLoc { def: macro_def, ast_id }); | ||
778 | 777 | ||
779 | self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def); | 778 | self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def); |
780 | return; | 779 | return; |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 95b3c926d..5155365cc 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -61,6 +61,8 @@ pub enum TypeNs { | |||
61 | GenericParam(u32), | 61 | GenericParam(u32), |
62 | AdtId(AdtId), | 62 | AdtId(AdtId), |
63 | AdtSelfType(AdtId), | 63 | AdtSelfType(AdtId), |
64 | // Yup, enum variants are added to the types ns, but any usage of variant as | ||
65 | // type is an error. | ||
64 | EnumVariantId(EnumVariantId), | 66 | EnumVariantId(EnumVariantId), |
65 | TypeAliasId(TypeAliasId), | 67 | TypeAliasId(TypeAliasId), |
66 | BuiltinType(BuiltinType), | 68 | BuiltinType(BuiltinType), |
@@ -482,7 +484,7 @@ impl Resolver { | |||
482 | } | 484 | } |
483 | } | 485 | } |
484 | 486 | ||
485 | pub trait HasResolver { | 487 | pub trait HasResolver: Copy { |
486 | /// Builds a resolver for type references inside this def. | 488 | /// Builds a resolver for type references inside this def. |
487 | fn resolver(self, db: &impl DefDatabase) -> Resolver; | 489 | fn resolver(self, db: &impl DefDatabase) -> Resolver; |
488 | } | 490 | } |
@@ -500,7 +502,7 @@ impl HasResolver for TraitId { | |||
500 | } | 502 | } |
501 | } | 503 | } |
502 | 504 | ||
503 | impl<T: Into<AdtId>> HasResolver for T { | 505 | impl<T: Into<AdtId> + Copy> HasResolver for T { |
504 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | 506 | fn resolver(self, db: &impl DefDatabase) -> Resolver { |
505 | let def = self.into(); | 507 | let def = self.into(); |
506 | def.module(db) | 508 | def.module(db) |
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 4f3ccf1d0..b6a739cda 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -135,6 +135,16 @@ pub struct MacroDefId { | |||
135 | pub kind: MacroDefKind, | 135 | pub kind: MacroDefKind, |
136 | } | 136 | } |
137 | 137 | ||
138 | impl MacroDefId { | ||
139 | pub fn as_call_id( | ||
140 | self, | ||
141 | db: &dyn db::AstDatabase, | ||
142 | ast_id: AstId<ast::MacroCall>, | ||
143 | ) -> MacroCallId { | ||
144 | db.intern_macro(MacroCallLoc { def: self, ast_id }) | ||
145 | } | ||
146 | } | ||
147 | |||
138 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 148 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
139 | pub enum MacroDefKind { | 149 | pub enum MacroDefKind { |
140 | Declarative, | 150 | Declarative, |
@@ -143,8 +153,8 @@ pub enum MacroDefKind { | |||
143 | 153 | ||
144 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 154 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
145 | pub struct MacroCallLoc { | 155 | pub struct MacroCallLoc { |
146 | pub def: MacroDefId, | 156 | pub(crate) def: MacroDefId, |
147 | pub ast_id: AstId<ast::MacroCall>, | 157 | pub(crate) ast_id: AstId<ast::MacroCall>, |
148 | } | 158 | } |
149 | 159 | ||
150 | impl MacroCallId { | 160 | impl MacroCallId { |
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs index 84340aff8..4a76d1dd8 100644 --- a/crates/ra_ide_api/src/change.rs +++ b/crates/ra_ide_api/src/change.rs | |||
@@ -323,7 +323,8 @@ impl RootDatabase { | |||
323 | hir::db::DocumentationQuery | 323 | hir::db::DocumentationQuery |
324 | hir::db::ExprScopesQuery | 324 | hir::db::ExprScopesQuery |
325 | hir::db::InferQuery | 325 | hir::db::InferQuery |
326 | hir::db::TypeForDefQuery | 326 | hir::db::TyQuery |
327 | hir::db::ValueTyQuery | ||
327 | hir::db::FieldTypesQuery | 328 | hir::db::FieldTypesQuery |
328 | hir::db::CallableItemSignatureQuery | 329 | hir::db::CallableItemSignatureQuery |
329 | hir::db::GenericPredicatesQuery | 330 | hir::db::GenericPredicatesQuery |
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) { |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index b6c72efdf..c10a6c844 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -71,10 +71,11 @@ pub(crate) fn reference_definition( | |||
71 | Some(nav) => return Exact(nav), | 71 | Some(nav) => return Exact(nav), |
72 | None => return Approximate(vec![]), | 72 | None => return Approximate(vec![]), |
73 | }, | 73 | }, |
74 | Some(SelfType(ty)) => { | 74 | Some(SelfType(imp)) => { |
75 | if let Some((adt, _)) = ty.as_adt() { | 75 | // FIXME: ideally, this should point to the type in the impl, and |
76 | return Exact(adt.to_nav(db)); | 76 | // not at the whole impl. And goto **type** definition should bring |
77 | } | 77 | // us to the actual type |
78 | return Exact(imp.to_nav(db)); | ||
78 | } | 79 | } |
79 | Some(Local(local)) => return Exact(local.to_nav(db)), | 80 | Some(Local(local)) => return Exact(local.to_nav(db)), |
80 | Some(GenericParam(_)) => { | 81 | Some(GenericParam(_)) => { |
@@ -503,7 +504,7 @@ mod tests { | |||
503 | } | 504 | } |
504 | } | 505 | } |
505 | ", | 506 | ", |
506 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | 507 | "impl IMPL_BLOCK FileId(1) [12; 73)", |
507 | ); | 508 | ); |
508 | 509 | ||
509 | check_goto( | 510 | check_goto( |
@@ -516,7 +517,7 @@ mod tests { | |||
516 | } | 517 | } |
517 | } | 518 | } |
518 | ", | 519 | ", |
519 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | 520 | "impl IMPL_BLOCK FileId(1) [12; 73)", |
520 | ); | 521 | ); |
521 | 522 | ||
522 | check_goto( | 523 | check_goto( |
@@ -529,7 +530,7 @@ mod tests { | |||
529 | } | 530 | } |
530 | } | 531 | } |
531 | ", | 532 | ", |
532 | "Foo ENUM_DEF FileId(1) [0; 14) [5; 8)", | 533 | "impl IMPL_BLOCK FileId(1) [15; 75)", |
533 | ); | 534 | ); |
534 | 535 | ||
535 | check_goto( | 536 | check_goto( |
@@ -541,7 +542,7 @@ mod tests { | |||
541 | } | 542 | } |
542 | } | 543 | } |
543 | ", | 544 | ", |
544 | "Foo ENUM_DEF FileId(1) [0; 14) [5; 8)", | 545 | "impl IMPL_BLOCK FileId(1) [15; 62)", |
545 | ); | 546 | ); |
546 | } | 547 | } |
547 | 548 | ||
@@ -560,7 +561,7 @@ mod tests { | |||
560 | } | 561 | } |
561 | } | 562 | } |
562 | ", | 563 | ", |
563 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | 564 | "impl IMPL_BLOCK FileId(1) [49; 115)", |
564 | ); | 565 | ); |
565 | 566 | ||
566 | check_goto( | 567 | check_goto( |
@@ -572,11 +573,11 @@ mod tests { | |||
572 | } | 573 | } |
573 | impl Make for Foo { | 574 | impl Make for Foo { |
574 | fn new() -> Self<|> { | 575 | fn new() -> Self<|> { |
575 | Self{} | 576 | Self {} |
576 | } | 577 | } |
577 | } | 578 | } |
578 | ", | 579 | ", |
579 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | 580 | "impl IMPL_BLOCK FileId(1) [49; 115)", |
580 | ); | 581 | ); |
581 | } | 582 | } |
582 | 583 | ||
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 9839be985..260a7b869 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -133,20 +133,12 @@ fn hover_text_from_name_kind( | |||
133 | hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), | 133 | hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), |
134 | hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), | 134 | hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), |
135 | }, | 135 | }, |
136 | SelfType(ty) => match ty.as_adt() { | ||
137 | Some((adt_def, _)) => match adt_def { | ||
138 | hir::Adt::Struct(it) => from_def_source(db, it), | ||
139 | hir::Adt::Union(it) => from_def_source(db, it), | ||
140 | hir::Adt::Enum(it) => from_def_source(db, it), | ||
141 | }, | ||
142 | _ => None, | ||
143 | }, | ||
144 | Local(_) => { | 136 | Local(_) => { |
145 | // Hover for these shows type names | 137 | // Hover for these shows type names |
146 | *no_fallback = true; | 138 | *no_fallback = true; |
147 | None | 139 | None |
148 | } | 140 | } |
149 | GenericParam(_) => { | 141 | GenericParam(_) | SelfType(_) => { |
150 | // FIXME: Hover for generic param | 142 | // FIXME: Hover for generic param |
151 | None | 143 | None |
152 | } | 144 | } |
@@ -622,49 +614,52 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
622 | ", | 614 | ", |
623 | ); | 615 | ); |
624 | let hover = analysis.hover(position).unwrap().unwrap(); | 616 | let hover = analysis.hover(position).unwrap().unwrap(); |
625 | assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing")); | 617 | assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); |
626 | assert_eq!(hover.info.is_exact(), true); | ||
627 | |||
628 | let (analysis, position) = single_file_with_position( | ||
629 | " | ||
630 | struct Thing { x: u32 } | ||
631 | impl Thing { | ||
632 | fn new() -> Self<|> { | ||
633 | Self { x: 0 } | ||
634 | } | ||
635 | } | ||
636 | ", | ||
637 | ); | ||
638 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
639 | assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing")); | ||
640 | assert_eq!(hover.info.is_exact(), true); | ||
641 | |||
642 | let (analysis, position) = single_file_with_position( | ||
643 | " | ||
644 | enum Thing { A } | ||
645 | impl Thing { | ||
646 | pub fn new() -> Self<|> { | ||
647 | Thing::A | ||
648 | } | ||
649 | } | ||
650 | ", | ||
651 | ); | ||
652 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
653 | assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); | ||
654 | assert_eq!(hover.info.is_exact(), true); | 618 | assert_eq!(hover.info.is_exact(), true); |
655 | 619 | ||
656 | let (analysis, position) = single_file_with_position( | 620 | /* FIXME: revive these tests |
657 | " | 621 | let (analysis, position) = single_file_with_position( |
658 | enum Thing { A } | 622 | " |
659 | impl Thing { | 623 | struct Thing { x: u32 } |
660 | pub fn thing(a: Self<|>) { | 624 | impl Thing { |
661 | } | 625 | fn new() -> Self<|> { |
662 | } | 626 | Self { x: 0 } |
663 | ", | 627 | } |
664 | ); | 628 | } |
665 | let hover = analysis.hover(position).unwrap().unwrap(); | 629 | ", |
666 | assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); | 630 | ); |
667 | assert_eq!(hover.info.is_exact(), true); | 631 | |
632 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
633 | assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); | ||
634 | assert_eq!(hover.info.is_exact(), true); | ||
635 | |||
636 | let (analysis, position) = single_file_with_position( | ||
637 | " | ||
638 | enum Thing { A } | ||
639 | impl Thing { | ||
640 | pub fn new() -> Self<|> { | ||
641 | Thing::A | ||
642 | } | ||
643 | } | ||
644 | ", | ||
645 | ); | ||
646 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
647 | assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); | ||
648 | assert_eq!(hover.info.is_exact(), true); | ||
649 | |||
650 | let (analysis, position) = single_file_with_position( | ||
651 | " | ||
652 | enum Thing { A } | ||
653 | impl Thing { | ||
654 | pub fn thing(a: Self<|>) { | ||
655 | } | ||
656 | } | ||
657 | ", | ||
658 | ); | ||
659 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
660 | assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); | ||
661 | assert_eq!(hover.info.is_exact(), true); | ||
662 | */ | ||
668 | } | 663 | } |
669 | 664 | ||
670 | #[test] | 665 | #[test] |
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index cb343e59a..21a1ea69e 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs | |||
@@ -83,10 +83,7 @@ pub(crate) fn find_all_refs( | |||
83 | NameKind::Field(field) => field.to_nav(db), | 83 | NameKind::Field(field) => field.to_nav(db), |
84 | NameKind::AssocItem(assoc) => assoc.to_nav(db), | 84 | NameKind::AssocItem(assoc) => assoc.to_nav(db), |
85 | NameKind::Def(def) => NavigationTarget::from_def(db, def)?, | 85 | NameKind::Def(def) => NavigationTarget::from_def(db, def)?, |
86 | NameKind::SelfType(ref ty) => match ty.as_adt() { | 86 | NameKind::SelfType(imp) => imp.to_nav(db), |
87 | Some((adt, _)) => adt.to_nav(db), | ||
88 | None => return None, | ||
89 | }, | ||
90 | NameKind::Local(local) => local.to_nav(db), | 87 | NameKind::Local(local) => local.to_nav(db), |
91 | NameKind::GenericParam(_) => return None, | 88 | NameKind::GenericParam(_) => return None, |
92 | }; | 89 | }; |
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 227737ad2..5cea805ec 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs | |||
@@ -178,8 +178,7 @@ pub(crate) fn classify_name_ref( | |||
178 | Some(NameDefinition { kind, container, visibility }) | 178 | Some(NameDefinition { kind, container, visibility }) |
179 | } | 179 | } |
180 | PathResolution::SelfType(impl_block) => { | 180 | PathResolution::SelfType(impl_block) => { |
181 | let ty = impl_block.target_ty(db); | 181 | let kind = NameKind::SelfType(impl_block); |
182 | let kind = NameKind::SelfType(ty); | ||
183 | let container = impl_block.module(db); | 182 | let container = impl_block.module(db); |
184 | Some(NameDefinition { kind, container, visibility }) | 183 | Some(NameDefinition { kind, container, visibility }) |
185 | } | 184 | } |
diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs index cf12db066..10d3a2364 100644 --- a/crates/ra_ide_api/src/references/name_definition.rs +++ b/crates/ra_ide_api/src/references/name_definition.rs | |||
@@ -4,8 +4,8 @@ | |||
4 | //! Note that the reference search is possible for not all of the classified items. | 4 | //! Note that the reference search is possible for not all of the classified items. |
5 | 5 | ||
6 | use hir::{ | 6 | use hir::{ |
7 | Adt, AssocItem, GenericParam, HasSource, Local, MacroDef, Module, ModuleDef, StructField, Ty, | 7 | Adt, AssocItem, GenericParam, HasSource, ImplBlock, Local, MacroDef, Module, ModuleDef, |
8 | VariantDef, | 8 | StructField, VariantDef, |
9 | }; | 9 | }; |
10 | use ra_syntax::{ast, ast::VisibilityOwner}; | 10 | use ra_syntax::{ast, ast::VisibilityOwner}; |
11 | 11 | ||
@@ -17,7 +17,7 @@ pub enum NameKind { | |||
17 | Field(StructField), | 17 | Field(StructField), |
18 | AssocItem(AssocItem), | 18 | AssocItem(AssocItem), |
19 | Def(ModuleDef), | 19 | Def(ModuleDef), |
20 | SelfType(Ty), | 20 | SelfType(ImplBlock), |
21 | Local(Local), | 21 | Local(Local), |
22 | GenericParam(GenericParam), | 22 | GenericParam(GenericParam), |
23 | } | 23 | } |