diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-17 22:16:28 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-17 22:16:28 +0100 |
commit | 54379ec6f8f82a470a275771e70825634d3d553b (patch) | |
tree | 498719aafe633f9eb9cb65ba65932076981e4632 /crates/ra_hir/src | |
parent | d505ee968b2a99eed65dfe7be27940ad9b2647c1 (diff) | |
parent | c2f9558e1af8dbf73ff86eeffcb9ea6940947dd6 (diff) |
Merge #1862
1862: Assoc item resolution refactoring (again) r=flodiebold a=flodiebold
This is #1849, with the associated type selection code removed for now. Handling cycles there will need some more thought.
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir/src/impl_block.rs | 28 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/path.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/traits.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 188 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 159 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 98 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 6 |
12 files changed, 336 insertions, 242 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 84e15385c..706d24c32 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -23,7 +23,7 @@ use crate::{ | |||
23 | }, | 23 | }, |
24 | nameres::{CrateModuleId, ImportId, ModuleScope, Namespace}, | 24 | nameres::{CrateModuleId, ImportId, ModuleScope, Namespace}, |
25 | resolve::{Resolver, TypeNs}, | 25 | resolve::{Resolver, TypeNs}, |
26 | traits::{TraitData, TraitItem}, | 26 | traits::TraitData, |
27 | ty::{ | 27 | ty::{ |
28 | primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness}, | 28 | primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness}, |
29 | InferenceResult, TraitRef, | 29 | InferenceResult, TraitRef, |
@@ -269,7 +269,7 @@ impl Module { | |||
269 | 269 | ||
270 | for impl_block in self.impl_blocks(db) { | 270 | for impl_block in self.impl_blocks(db) { |
271 | for item in impl_block.items(db) { | 271 | for item in impl_block.items(db) { |
272 | if let crate::ImplItem::Method(f) = item { | 272 | if let AssocItem::Function(f) = item { |
273 | f.diagnostics(db, sink); | 273 | f.diagnostics(db, sink); |
274 | } | 274 | } |
275 | } | 275 | } |
@@ -749,6 +749,10 @@ impl Const { | |||
749 | db.const_data(self) | 749 | db.const_data(self) |
750 | } | 750 | } |
751 | 751 | ||
752 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { | ||
753 | self.data(db).name().cloned() | ||
754 | } | ||
755 | |||
752 | pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { | 756 | pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { |
753 | db.infer(self.into()) | 757 | db.infer(self.into()) |
754 | } | 758 | } |
@@ -849,7 +853,7 @@ impl Trait { | |||
849 | self.trait_data(db).name().clone() | 853 | self.trait_data(db).name().clone() |
850 | } | 854 | } |
851 | 855 | ||
852 | pub fn items(self, db: &impl DefDatabase) -> Vec<TraitItem> { | 856 | pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> { |
853 | self.trait_data(db).items().to_vec() | 857 | self.trait_data(db).items().to_vec() |
854 | } | 858 | } |
855 | 859 | ||
@@ -902,7 +906,7 @@ impl Trait { | |||
902 | .items() | 906 | .items() |
903 | .iter() | 907 | .iter() |
904 | .filter_map(|item| match item { | 908 | .filter_map(|item| match item { |
905 | TraitItem::TypeAlias(t) => Some(*t), | 909 | AssocItem::TypeAlias(t) => Some(*t), |
906 | _ => None, | 910 | _ => None, |
907 | }) | 911 | }) |
908 | .find(|t| &t.name(db) == name) | 912 | .find(|t| &t.name(db) == name) |
@@ -1019,3 +1023,15 @@ impl Container { | |||
1019 | } | 1023 | } |
1020 | } | 1024 | } |
1021 | } | 1025 | } |
1026 | |||
1027 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||
1028 | pub enum AssocItem { | ||
1029 | Function(Function), | ||
1030 | Const(Const), | ||
1031 | TypeAlias(TypeAlias), | ||
1032 | } | ||
1033 | // FIXME: not every function, ... is actually an assoc item. maybe we should make | ||
1034 | // sure that you can only turn actual assoc items into AssocItems. This would | ||
1035 | // require not implementing From, and instead having some checked way of | ||
1036 | // casting them, and somehow making the constructors private, which would be annoying. | ||
1037 | impl_froms!(AssocItem: Function, Const, TypeAlias); | ||
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index d26a024ed..c463d351c 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -15,7 +15,7 @@ use crate::{ | |||
15 | resolve::Resolver, | 15 | resolve::Resolver, |
16 | ty::Ty, | 16 | ty::Ty, |
17 | type_ref::TypeRef, | 17 | type_ref::TypeRef, |
18 | Const, Function, HasSource, HirFileId, Source, TraitRef, TypeAlias, | 18 | AssocItem, Const, Function, HasSource, HirFileId, Source, TraitRef, TypeAlias, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | #[derive(Debug, Default, PartialEq, Eq)] | 21 | #[derive(Debug, Default, PartialEq, Eq)] |
@@ -56,7 +56,7 @@ impl HasSource for ImplBlock { | |||
56 | impl ImplBlock { | 56 | impl ImplBlock { |
57 | pub(crate) fn containing( | 57 | pub(crate) fn containing( |
58 | module_impl_blocks: Arc<ModuleImplBlocks>, | 58 | module_impl_blocks: Arc<ModuleImplBlocks>, |
59 | item: ImplItem, | 59 | item: AssocItem, |
60 | ) -> Option<ImplBlock> { | 60 | ) -> Option<ImplBlock> { |
61 | let impl_id = *module_impl_blocks.impls_by_def.get(&item)?; | 61 | let impl_id = *module_impl_blocks.impls_by_def.get(&item)?; |
62 | Some(ImplBlock { module: module_impl_blocks.module, impl_id }) | 62 | Some(ImplBlock { module: module_impl_blocks.module, impl_id }) |
@@ -91,7 +91,7 @@ impl ImplBlock { | |||
91 | TraitRef::from_hir(db, &self.resolver(db), &self.target_trait(db)?, Some(target_ty)) | 91 | TraitRef::from_hir(db, &self.resolver(db), &self.target_trait(db)?, Some(target_ty)) |
92 | } | 92 | } |
93 | 93 | ||
94 | pub fn items(&self, db: &impl DefDatabase) -> Vec<ImplItem> { | 94 | pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> { |
95 | db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() | 95 | db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() |
96 | } | 96 | } |
97 | 97 | ||
@@ -113,7 +113,7 @@ impl ImplBlock { | |||
113 | pub struct ImplData { | 113 | pub struct ImplData { |
114 | target_trait: Option<TypeRef>, | 114 | target_trait: Option<TypeRef>, |
115 | target_type: TypeRef, | 115 | target_type: TypeRef, |
116 | items: Vec<ImplItem>, | 116 | items: Vec<AssocItem>, |
117 | negative: bool, | 117 | negative: bool, |
118 | } | 118 | } |
119 | 119 | ||
@@ -151,27 +151,11 @@ impl ImplData { | |||
151 | &self.target_type | 151 | &self.target_type |
152 | } | 152 | } |
153 | 153 | ||
154 | pub fn items(&self) -> &[ImplItem] { | 154 | pub fn items(&self) -> &[AssocItem] { |
155 | &self.items | 155 | &self.items |
156 | } | 156 | } |
157 | } | 157 | } |
158 | 158 | ||
159 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
160 | //FIXME: rename to ImplDef? | ||
161 | pub enum ImplItem { | ||
162 | Method(Function), | ||
163 | Const(Const), | ||
164 | TypeAlias(TypeAlias), | ||
165 | // Existential | ||
166 | } | ||
167 | impl_froms!(ImplItem: Const, TypeAlias); | ||
168 | |||
169 | impl From<Function> for ImplItem { | ||
170 | fn from(func: Function) -> ImplItem { | ||
171 | ImplItem::Method(func) | ||
172 | } | ||
173 | } | ||
174 | |||
175 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 159 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
176 | pub struct ImplId(pub RawId); | 160 | pub struct ImplId(pub RawId); |
177 | impl_arena_id!(ImplId); | 161 | impl_arena_id!(ImplId); |
@@ -185,7 +169,7 @@ impl_arena_id!(ImplId); | |||
185 | pub struct ModuleImplBlocks { | 169 | pub struct ModuleImplBlocks { |
186 | pub(crate) module: Module, | 170 | pub(crate) module: Module, |
187 | pub(crate) impls: Arena<ImplId, ImplData>, | 171 | pub(crate) impls: Arena<ImplId, ImplData>, |
188 | impls_by_def: FxHashMap<ImplItem, ImplId>, | 172 | impls_by_def: FxHashMap<AssocItem, ImplId>, |
189 | } | 173 | } |
190 | 174 | ||
191 | impl ModuleImplBlocks { | 175 | impl ModuleImplBlocks { |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 80cf8d9c0..e7a576aa0 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -69,7 +69,7 @@ pub use self::{ | |||
69 | expr::ExprScopes, | 69 | expr::ExprScopes, |
70 | generics::{GenericParam, GenericParams, HasGenericParams}, | 70 | generics::{GenericParam, GenericParams, HasGenericParams}, |
71 | ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, | 71 | ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, |
72 | impl_block::{ImplBlock, ImplItem}, | 72 | impl_block::ImplBlock, |
73 | name::Name, | 73 | name::Name, |
74 | nameres::{ImportId, Namespace, PerNs}, | 74 | nameres::{ImportId, Namespace, PerNs}, |
75 | path::{Path, PathKind}, | 75 | path::{Path, PathKind}, |
@@ -85,7 +85,7 @@ pub use self::{ | |||
85 | pub use self::code_model::{ | 85 | pub use self::code_model::{ |
86 | docs::{DocDef, Docs, Documentation}, | 86 | docs::{DocDef, Docs, Documentation}, |
87 | src::{HasBodySource, HasSource, Source}, | 87 | src::{HasBodySource, HasSource, Source}, |
88 | Adt, BuiltinType, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum, | 88 | Adt, AssocItem, BuiltinType, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, |
89 | EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, ModuleDef, ModuleSource, | 89 | Enum, EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, ModuleDef, |
90 | Static, Struct, StructField, Trait, TypeAlias, Union, | 90 | ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, |
91 | }; | 91 | }; |
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index a61161b63..39d1b7e46 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs | |||
@@ -190,6 +190,13 @@ impl Path { | |||
190 | pub fn expand_macro_expr(&self) -> Option<Name> { | 190 | pub fn expand_macro_expr(&self) -> Option<Name> { |
191 | self.as_ident().and_then(|name| Some(name.clone())) | 191 | self.as_ident().and_then(|name| Some(name.clone())) |
192 | } | 192 | } |
193 | |||
194 | pub fn is_type_relative(&self) -> bool { | ||
195 | match self.kind { | ||
196 | PathKind::Type(_) => true, | ||
197 | _ => false, | ||
198 | } | ||
199 | } | ||
193 | } | 200 | } |
194 | 201 | ||
195 | impl GenericArgs { | 202 | impl GenericArgs { |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index bb6915901..a23c8792a 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -15,7 +15,6 @@ use crate::{ | |||
15 | name::{Name, SELF_PARAM, SELF_TYPE}, | 15 | name::{Name, SELF_PARAM, SELF_TYPE}, |
16 | nameres::{CrateDefMap, CrateModuleId, PerNs}, | 16 | nameres::{CrateDefMap, CrateModuleId, PerNs}, |
17 | path::{Path, PathKind}, | 17 | path::{Path, PathKind}, |
18 | type_ref::TypeRef, | ||
19 | Adt, BuiltinType, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct, | 18 | Adt, BuiltinType, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct, |
20 | Trait, TypeAlias, | 19 | Trait, TypeAlias, |
21 | }; | 20 | }; |
@@ -50,7 +49,7 @@ pub(crate) enum Scope { | |||
50 | ExprScope(ExprScope), | 49 | ExprScope(ExprScope), |
51 | } | 50 | } |
52 | 51 | ||
53 | #[derive(Debug, Clone, PartialEq, Eq)] | 52 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
54 | pub enum TypeNs { | 53 | pub enum TypeNs { |
55 | SelfType(ImplBlock), | 54 | SelfType(ImplBlock), |
56 | GenericParam(u32), | 55 | GenericParam(u32), |
@@ -59,19 +58,18 @@ pub enum TypeNs { | |||
59 | TypeAlias(TypeAlias), | 58 | TypeAlias(TypeAlias), |
60 | BuiltinType(BuiltinType), | 59 | BuiltinType(BuiltinType), |
61 | Trait(Trait), | 60 | Trait(Trait), |
62 | // Module belong to type ns, but the resovler is used when all module paths | 61 | // Module belong to type ns, but the resolver is used when all module paths |
63 | // are fully resolved. | 62 | // are fully resolved. |
64 | // Module(Module) | 63 | // Module(Module) |
65 | } | 64 | } |
66 | 65 | ||
67 | #[derive(Debug)] | 66 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
68 | pub enum ResolveValueResult<'a> { | 67 | pub enum ResolveValueResult { |
69 | ValueNs(ValueNs), | 68 | ValueNs(ValueNs), |
70 | Partial(TypeNs, usize), | 69 | Partial(TypeNs, usize), |
71 | TypeRef(&'a TypeRef), | ||
72 | } | 70 | } |
73 | 71 | ||
74 | #[derive(Debug)] | 72 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
75 | pub enum ValueNs { | 73 | pub enum ValueNs { |
76 | LocalBinding(PatId), | 74 | LocalBinding(PatId), |
77 | Function(Function), | 75 | Function(Function), |
@@ -131,6 +129,9 @@ impl Resolver { | |||
131 | db: &impl HirDatabase, | 129 | db: &impl HirDatabase, |
132 | path: &Path, | 130 | path: &Path, |
133 | ) -> Option<(TypeNs, Option<usize>)> { | 131 | ) -> Option<(TypeNs, Option<usize>)> { |
132 | if path.is_type_relative() { | ||
133 | return None; | ||
134 | } | ||
134 | let first_name = &path.segments.first()?.name; | 135 | let first_name = &path.segments.first()?.name; |
135 | let skip_to_mod = path.kind != PathKind::Plain; | 136 | let skip_to_mod = path.kind != PathKind::Plain; |
136 | for scope in self.scopes.iter().rev() { | 137 | for scope in self.scopes.iter().rev() { |
@@ -189,11 +190,10 @@ impl Resolver { | |||
189 | &self, | 190 | &self, |
190 | db: &impl HirDatabase, | 191 | db: &impl HirDatabase, |
191 | path: &'p Path, | 192 | path: &'p Path, |
192 | ) -> Option<ResolveValueResult<'p>> { | 193 | ) -> Option<ResolveValueResult> { |
193 | if let PathKind::Type(type_ref) = &path.kind { | 194 | if path.is_type_relative() { |
194 | return Some(ResolveValueResult::TypeRef(type_ref)); | 195 | return None; |
195 | } | 196 | } |
196 | |||
197 | let n_segments = path.segments.len(); | 197 | let n_segments = path.segments.len(); |
198 | let tmp = SELF_PARAM; | 198 | let tmp = SELF_PARAM; |
199 | let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; | 199 | let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; |
@@ -284,7 +284,7 @@ impl Resolver { | |||
284 | ) -> Option<ValueNs> { | 284 | ) -> Option<ValueNs> { |
285 | match self.resolve_path_in_value_ns(db, path)? { | 285 | match self.resolve_path_in_value_ns(db, path)? { |
286 | ResolveValueResult::ValueNs(it) => Some(it), | 286 | ResolveValueResult::ValueNs(it) => Some(it), |
287 | ResolveValueResult::Partial(..) | ResolveValueResult::TypeRef(_) => None, | 287 | ResolveValueResult::Partial(..) => None, |
288 | } | 288 | } |
289 | } | 289 | } |
290 | 290 | ||
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 2a907c9f1..4d895f0a1 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -190,7 +190,7 @@ pub enum PathResolution { | |||
190 | GenericParam(u32), | 190 | GenericParam(u32), |
191 | SelfType(crate::ImplBlock), | 191 | SelfType(crate::ImplBlock), |
192 | Macro(MacroDef), | 192 | Macro(MacroDef), |
193 | AssocItem(crate::ImplItem), | 193 | AssocItem(crate::AssocItem), |
194 | } | 194 | } |
195 | 195 | ||
196 | #[derive(Debug, Clone, PartialEq, Eq)] | 196 | #[derive(Debug, Clone, PartialEq, Eq)] |
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs index 4c2f7980d..e39511518 100644 --- a/crates/ra_hir/src/traits.rs +++ b/crates/ra_hir/src/traits.rs | |||
@@ -9,13 +9,13 @@ use crate::{ | |||
9 | db::{AstDatabase, DefDatabase}, | 9 | db::{AstDatabase, DefDatabase}, |
10 | ids::LocationCtx, | 10 | ids::LocationCtx, |
11 | name::AsName, | 11 | name::AsName, |
12 | Const, Function, HasSource, Module, Name, Trait, TypeAlias, | 12 | AssocItem, Const, Function, HasSource, Module, Name, Trait, TypeAlias, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | #[derive(Debug, Clone, PartialEq, Eq)] | 15 | #[derive(Debug, Clone, PartialEq, Eq)] |
16 | pub struct TraitData { | 16 | pub struct TraitData { |
17 | name: Option<Name>, | 17 | name: Option<Name>, |
18 | items: Vec<TraitItem>, | 18 | items: Vec<AssocItem>, |
19 | auto: bool, | 19 | auto: bool, |
20 | } | 20 | } |
21 | 21 | ||
@@ -48,7 +48,7 @@ impl TraitData { | |||
48 | &self.name | 48 | &self.name |
49 | } | 49 | } |
50 | 50 | ||
51 | pub(crate) fn items(&self) -> &[TraitItem] { | 51 | pub(crate) fn items(&self) -> &[AssocItem] { |
52 | &self.items | 52 | &self.items |
53 | } | 53 | } |
54 | 54 | ||
@@ -57,22 +57,9 @@ impl TraitData { | |||
57 | } | 57 | } |
58 | } | 58 | } |
59 | 59 | ||
60 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
61 | pub enum TraitItem { | ||
62 | Function(Function), | ||
63 | Const(Const), | ||
64 | TypeAlias(TypeAlias), | ||
65 | // Existential | ||
66 | } | ||
67 | // FIXME: not every function, ... is actually a trait item. maybe we should make | ||
68 | // sure that you can only turn actual trait items into TraitItems. This would | ||
69 | // require not implementing From, and instead having some checked way of | ||
70 | // casting them. | ||
71 | impl_froms!(TraitItem: Function, Const, TypeAlias); | ||
72 | |||
73 | #[derive(Debug, Clone, PartialEq, Eq)] | 60 | #[derive(Debug, Clone, PartialEq, Eq)] |
74 | pub struct TraitItemsIndex { | 61 | pub struct TraitItemsIndex { |
75 | traits_by_def: FxHashMap<TraitItem, Trait>, | 62 | traits_by_def: FxHashMap<AssocItem, Trait>, |
76 | } | 63 | } |
77 | 64 | ||
78 | impl TraitItemsIndex { | 65 | impl TraitItemsIndex { |
@@ -88,7 +75,7 @@ impl TraitItemsIndex { | |||
88 | index | 75 | index |
89 | } | 76 | } |
90 | 77 | ||
91 | pub(crate) fn get_parent_trait(&self, item: TraitItem) -> Option<Trait> { | 78 | pub(crate) fn get_parent_trait(&self, item: AssocItem) -> Option<Trait> { |
92 | self.traits_by_def.get(&item).cloned() | 79 | self.traits_by_def.get(&item).cloned() |
93 | } | 80 | } |
94 | } | 81 | } |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index bf9609d8c..70da7f311 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -48,8 +48,7 @@ use crate::{ | |||
48 | resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, | 48 | resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, |
49 | ty::infer::diagnostics::InferenceDiagnostic, | 49 | ty::infer::diagnostics::InferenceDiagnostic, |
50 | type_ref::{Mutability, TypeRef}, | 50 | type_ref::{Mutability, TypeRef}, |
51 | Adt, ConstData, DefWithBody, Either, FnData, Function, HasBody, ImplItem, Name, Path, | 51 | Adt, AssocItem, ConstData, DefWithBody, FnData, Function, HasBody, Name, Path, StructField, |
52 | StructField, | ||
53 | }; | 52 | }; |
54 | 53 | ||
55 | mod unify; | 54 | mod unify; |
@@ -121,7 +120,7 @@ pub struct InferenceResult { | |||
121 | /// For each struct literal, records the variant it resolves to. | 120 | /// For each struct literal, records the variant it resolves to. |
122 | variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>, | 121 | variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>, |
123 | /// For each associated item record what it resolves to | 122 | /// For each associated item record what it resolves to |
124 | assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, | 123 | assoc_resolutions: FxHashMap<ExprOrPatId, AssocItem>, |
125 | diagnostics: Vec<InferenceDiagnostic>, | 124 | diagnostics: Vec<InferenceDiagnostic>, |
126 | pub(super) type_of_expr: ArenaMap<ExprId, Ty>, | 125 | pub(super) type_of_expr: ArenaMap<ExprId, Ty>, |
127 | pub(super) type_of_pat: ArenaMap<PatId, Ty>, | 126 | pub(super) type_of_pat: ArenaMap<PatId, Ty>, |
@@ -141,10 +140,10 @@ impl InferenceResult { | |||
141 | pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantDef> { | 140 | pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantDef> { |
142 | self.variant_resolutions.get(&id.into()).copied() | 141 | self.variant_resolutions.get(&id.into()).copied() |
143 | } | 142 | } |
144 | pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<ImplItem> { | 143 | pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<AssocItem> { |
145 | self.assoc_resolutions.get(&id.into()).copied() | 144 | self.assoc_resolutions.get(&id.into()).copied() |
146 | } | 145 | } |
147 | pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> { | 146 | pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<AssocItem> { |
148 | self.assoc_resolutions.get(&id.into()).copied() | 147 | self.assoc_resolutions.get(&id.into()).copied() |
149 | } | 148 | } |
150 | pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> { | 149 | pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> { |
@@ -235,7 +234,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
235 | self.result.variant_resolutions.insert(id, variant); | 234 | self.result.variant_resolutions.insert(id, variant); |
236 | } | 235 | } |
237 | 236 | ||
238 | fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: ImplItem) { | 237 | fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: AssocItem) { |
239 | self.result.assoc_resolutions.insert(id, item); | 238 | self.result.assoc_resolutions.insert(id, item); |
240 | } | 239 | } |
241 | 240 | ||
@@ -468,16 +467,27 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
468 | } | 467 | } |
469 | 468 | ||
470 | fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option<Ty> { | 469 | fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option<Ty> { |
471 | let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?; | 470 | let (value, self_subst) = if let crate::PathKind::Type(type_ref) = &path.kind { |
472 | 471 | if path.segments.is_empty() { | |
473 | let (value, self_subst) = match value_or_partial { | 472 | // This can't actually happen syntax-wise |
474 | ResolveValueResult::ValueNs(it) => (it, None), | 473 | return None; |
475 | ResolveValueResult::Partial(def, remaining_index) => { | ||
476 | self.resolve_assoc_item(Either::A(def), path, remaining_index, id)? | ||
477 | } | 474 | } |
478 | ResolveValueResult::TypeRef(type_ref) => { | 475 | let ty = self.make_ty(type_ref); |
479 | let ty = self.make_ty(type_ref); | 476 | let remaining_segments_for_ty = &path.segments[..path.segments.len() - 1]; |
480 | self.resolve_assoc_item(Either::B(ty), path, 0, id)? | 477 | let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); |
478 | self.resolve_ty_assoc_item( | ||
479 | ty, | ||
480 | path.segments.last().expect("path had at least one segment"), | ||
481 | id, | ||
482 | )? | ||
483 | } else { | ||
484 | let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?; | ||
485 | |||
486 | match value_or_partial { | ||
487 | ResolveValueResult::ValueNs(it) => (it, None), | ||
488 | ResolveValueResult::Partial(def, remaining_index) => { | ||
489 | self.resolve_assoc_item(def, path, remaining_index, id)? | ||
490 | } | ||
481 | } | 491 | } |
482 | }; | 492 | }; |
483 | 493 | ||
@@ -508,101 +518,91 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
508 | 518 | ||
509 | fn resolve_assoc_item( | 519 | fn resolve_assoc_item( |
510 | &mut self, | 520 | &mut self, |
511 | mut def_or_ty: Either<TypeNs, Ty>, | 521 | def: TypeNs, |
512 | path: &Path, | 522 | path: &Path, |
513 | remaining_index: usize, | 523 | remaining_index: usize, |
514 | id: ExprOrPatId, | 524 | id: ExprOrPatId, |
515 | ) -> Option<(ValueNs, Option<Substs>)> { | 525 | ) -> Option<(ValueNs, Option<Substs>)> { |
516 | assert!(remaining_index < path.segments.len()); | 526 | assert!(remaining_index < path.segments.len()); |
517 | let krate = self.resolver.krate()?; | 527 | // there may be more intermediate segments between the resolved one and |
518 | 528 | // the end. Only the last segment needs to be resolved to a value; from | |
519 | let mut ty = Ty::Unknown; | 529 | // the segments before that, we need to get either a type or a trait ref. |
520 | 530 | ||
521 | // resolve intermediate segments | 531 | let resolved_segment = &path.segments[remaining_index - 1]; |
522 | for (i, segment) in path.segments[remaining_index..].iter().enumerate() { | 532 | let remaining_segments = &path.segments[remaining_index..]; |
523 | let is_last_segment = i == path.segments[remaining_index..].len() - 1; | 533 | let is_before_last = remaining_segments.len() == 1; |
524 | ty = match def_or_ty { | 534 | |
525 | Either::A(def) => { | 535 | match (def, is_before_last) { |
526 | let typable: TypableDef = match def { | 536 | (TypeNs::Trait(_trait), true) => { |
527 | TypeNs::Adt(it) => it.into(), | 537 | // FIXME Associated item of trait, e.g. `Default::default` |
528 | TypeNs::TypeAlias(it) => it.into(), | 538 | None |
529 | TypeNs::BuiltinType(it) => it.into(), | ||
530 | // FIXME associated item of traits, generics, and Self | ||
531 | TypeNs::Trait(_) | TypeNs::GenericParam(_) | TypeNs::SelfType(_) => { | ||
532 | return None; | ||
533 | } | ||
534 | // FIXME: report error here | ||
535 | TypeNs::EnumVariant(_) => return None, | ||
536 | }; | ||
537 | |||
538 | let ty = self.db.type_for_def(typable, Namespace::Types); | ||
539 | |||
540 | // For example, this substs will take `Gen::*<u32>*::make` | ||
541 | assert!(remaining_index > 0); | ||
542 | let substs = Ty::substs_from_path_segment( | ||
543 | self.db, | ||
544 | &self.resolver, | ||
545 | &path.segments[remaining_index + i - 1], | ||
546 | typable, | ||
547 | ); | ||
548 | ty.subst(&substs) | ||
549 | } | ||
550 | Either::B(ty) => ty, | ||
551 | }; | ||
552 | if is_last_segment { | ||
553 | break; | ||
554 | } | 539 | } |
540 | (def, _) => { | ||
541 | // Either we already have a type (e.g. `Vec::new`), or we have a | ||
542 | // trait but it's not the last segment, so the next segment | ||
543 | // should resolve to an associated type of that trait (e.g. `<T | ||
544 | // as Iterator>::Item::default`) | ||
545 | let remaining_segments_for_ty = &remaining_segments[..remaining_segments.len() - 1]; | ||
546 | let ty = Ty::from_partly_resolved_hir_path( | ||
547 | self.db, | ||
548 | &self.resolver, | ||
549 | def, | ||
550 | resolved_segment, | ||
551 | remaining_segments_for_ty, | ||
552 | ); | ||
553 | if let Ty::Unknown = ty { | ||
554 | return None; | ||
555 | } | ||
555 | 556 | ||
556 | // Attempt to find an impl_item for the type which has a name matching | 557 | let segment = |
557 | // the current segment | 558 | remaining_segments.last().expect("there should be at least one segment here"); |
558 | log::debug!("looking for path segment: {:?}", segment); | ||
559 | 559 | ||
560 | let ty = mem::replace(&mut ty, Ty::Unknown); | 560 | self.resolve_ty_assoc_item(ty, segment, id) |
561 | def_or_ty = ty.iterate_impl_items(self.db, krate, |item| { | 561 | } |
562 | match item { | 562 | } |
563 | crate::ImplItem::Method(_) => None, | 563 | } |
564 | crate::ImplItem::Const(_) => None, | ||
565 | 564 | ||
566 | // FIXME: Resolve associated types | 565 | fn resolve_ty_assoc_item( |
567 | crate::ImplItem::TypeAlias(_) => { | 566 | &mut self, |
568 | // Some(Either::A(TypeNs::TypeAlias(..))) | 567 | ty: Ty, |
569 | None | 568 | segment: &crate::path::PathSegment, |
570 | } | 569 | id: ExprOrPatId, |
571 | } | 570 | ) -> Option<(ValueNs, Option<Substs>)> { |
572 | })?; | 571 | if let Ty::Unknown = ty { |
572 | return None; | ||
573 | } | 573 | } |
574 | 574 | ||
575 | let segment = path.segments.last().unwrap(); | 575 | let krate = self.resolver.krate()?; |
576 | let def = ty.clone().iterate_impl_items(self.db, krate, |item| { | ||
577 | let matching_def: Option<ValueNs> = match item { | ||
578 | crate::ImplItem::Method(func) => { | ||
579 | if segment.name == func.name(self.db) { | ||
580 | Some(ValueNs::Function(func)) | ||
581 | } else { | ||
582 | None | ||
583 | } | ||
584 | } | ||
585 | 576 | ||
586 | crate::ImplItem::Const(konst) => { | 577 | // Find impl |
587 | let data = konst.data(self.db); | 578 | // FIXME: consider trait candidates |
588 | if Some(&segment.name) == data.name() { | 579 | let item = ty.clone().iterate_impl_items(self.db, krate, |item| match item { |
589 | Some(ValueNs::Const(konst)) | 580 | AssocItem::Function(func) => { |
590 | } else { | 581 | if segment.name == func.name(self.db) { |
591 | None | 582 | Some(AssocItem::Function(func)) |
592 | } | 583 | } else { |
584 | None | ||
593 | } | 585 | } |
594 | crate::ImplItem::TypeAlias(_) => None, | 586 | } |
595 | }; | 587 | |
596 | match matching_def { | 588 | AssocItem::Const(konst) => { |
597 | Some(_) => { | 589 | if konst.name(self.db).map_or(false, |n| n == segment.name) { |
598 | self.write_assoc_resolution(id, item); | 590 | Some(AssocItem::Const(konst)) |
599 | matching_def | 591 | } else { |
592 | None | ||
600 | } | 593 | } |
601 | None => None, | ||
602 | } | 594 | } |
595 | AssocItem::TypeAlias(_) => None, | ||
603 | })?; | 596 | })?; |
604 | let self_types = self.find_self_types(&def, ty); | 597 | let def = match item { |
605 | Some((def, self_types)) | 598 | AssocItem::Function(f) => ValueNs::Function(f), |
599 | AssocItem::Const(c) => ValueNs::Const(c), | ||
600 | AssocItem::TypeAlias(_) => unreachable!(), | ||
601 | }; | ||
602 | let substs = self.find_self_types(&def, ty); | ||
603 | |||
604 | self.write_assoc_resolution(id, item); | ||
605 | Some((def, substs)) | ||
606 | } | 606 | } |
607 | 607 | ||
608 | fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { | 608 | fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 6ead3846a..a83842b0f 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -86,78 +86,125 @@ impl Ty { | |||
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { | 89 | pub(crate) fn from_type_relative_path( |
90 | // Resolve the path (in type namespace) | 90 | db: &impl HirDatabase, |
91 | let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) { | 91 | resolver: &Resolver, |
92 | Some(it) => it, | 92 | ty: Ty, |
93 | None => return Ty::Unknown, | 93 | remaining_segments: &[PathSegment], |
94 | }; | 94 | ) -> Ty { |
95 | if remaining_segments.len() == 1 { | ||
96 | // resolve unselected assoc types | ||
97 | let segment = &remaining_segments[0]; | ||
98 | Ty::select_associated_type(db, resolver, ty, segment) | ||
99 | } else if remaining_segments.len() > 1 { | ||
100 | // FIXME report error (ambiguous associated type) | ||
101 | Ty::Unknown | ||
102 | } else { | ||
103 | ty | ||
104 | } | ||
105 | } | ||
95 | 106 | ||
96 | let typable: TypableDef = match resolution { | 107 | pub(crate) fn from_partly_resolved_hir_path( |
108 | db: &impl HirDatabase, | ||
109 | resolver: &Resolver, | ||
110 | resolution: TypeNs, | ||
111 | resolved_segment: &PathSegment, | ||
112 | remaining_segments: &[PathSegment], | ||
113 | ) -> Ty { | ||
114 | let ty = match resolution { | ||
97 | TypeNs::Trait(trait_) => { | 115 | TypeNs::Trait(trait_) => { |
98 | let segment = match remaining_index { | 116 | let trait_ref = |
99 | None => path.segments.last().expect("resolved path has at least one element"), | 117 | TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); |
100 | Some(i) => &path.segments[i - 1], | 118 | return if remaining_segments.len() == 1 { |
101 | }; | 119 | let segment = &remaining_segments[0]; |
102 | let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, segment, None); | 120 | match trait_ref |
103 | return if let Some(remaining_index) = remaining_index { | 121 | .trait_ |
104 | if remaining_index == path.segments.len() - 1 { | 122 | .associated_type_by_name_including_super_traits(db, &segment.name) |
105 | let segment = &path.segments[remaining_index]; | 123 | { |
106 | match trait_ref | 124 | Some(associated_ty) => { |
107 | .trait_ | 125 | // FIXME handle type parameters on the segment |
108 | .associated_type_by_name_including_super_traits(db, &segment.name) | 126 | Ty::Projection(ProjectionTy { |
109 | { | 127 | associated_ty, |
110 | Some(associated_ty) => { | 128 | parameters: trait_ref.substs, |
111 | // FIXME handle type parameters on the segment | 129 | }) |
112 | Ty::Projection(ProjectionTy { | 130 | } |
113 | associated_ty, | 131 | None => { |
114 | parameters: trait_ref.substs, | 132 | // FIXME: report error (associated type not found) |
115 | }) | 133 | Ty::Unknown |
116 | } | ||
117 | None => { | ||
118 | // associated type not found | ||
119 | Ty::Unknown | ||
120 | } | ||
121 | } | 134 | } |
122 | } else { | ||
123 | // FIXME more than one segment remaining, is this possible? | ||
124 | Ty::Unknown | ||
125 | } | 135 | } |
136 | } else if remaining_segments.len() > 1 { | ||
137 | // FIXME report error (ambiguous associated type) | ||
138 | Ty::Unknown | ||
126 | } else { | 139 | } else { |
127 | Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) | 140 | Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) |
128 | }; | 141 | }; |
129 | } | 142 | } |
130 | TypeNs::GenericParam(idx) => { | 143 | TypeNs::GenericParam(idx) => { |
131 | if remaining_index.is_some() { | 144 | // FIXME: maybe return name in resolution? |
132 | // e.g. T::Item | 145 | let name = resolved_segment.name.clone(); |
133 | return Ty::Unknown; | 146 | Ty::Param { idx, name } |
134 | } | ||
135 | return Ty::Param { | ||
136 | idx, | ||
137 | // FIXME: maybe return name in resolution? | ||
138 | name: path | ||
139 | .as_ident() | ||
140 | .expect("generic param should be single-segment path") | ||
141 | .clone(), | ||
142 | }; | ||
143 | } | ||
144 | TypeNs::SelfType(impl_block) => { | ||
145 | if remaining_index.is_some() { | ||
146 | // e.g. Self::Item | ||
147 | return Ty::Unknown; | ||
148 | } | ||
149 | return impl_block.target_ty(db); | ||
150 | } | 147 | } |
148 | TypeNs::SelfType(impl_block) => impl_block.target_ty(db), | ||
151 | 149 | ||
152 | TypeNs::Adt(it) => it.into(), | 150 | TypeNs::Adt(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), |
153 | TypeNs::BuiltinType(it) => it.into(), | 151 | TypeNs::BuiltinType(it) => { |
154 | TypeNs::TypeAlias(it) => it.into(), | 152 | Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) |
153 | } | ||
154 | TypeNs::TypeAlias(it) => { | ||
155 | Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) | ||
156 | } | ||
155 | // FIXME: report error | 157 | // FIXME: report error |
156 | TypeNs::EnumVariant(_) => return Ty::Unknown, | 158 | TypeNs::EnumVariant(_) => return Ty::Unknown, |
157 | }; | 159 | }; |
158 | 160 | ||
161 | Ty::from_type_relative_path(db, resolver, ty, remaining_segments) | ||
162 | } | ||
163 | |||
164 | pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { | ||
165 | // Resolve the path (in type namespace) | ||
166 | if let crate::PathKind::Type(type_ref) = &path.kind { | ||
167 | let ty = Ty::from_hir(db, resolver, &type_ref); | ||
168 | let remaining_segments = &path.segments[..]; | ||
169 | return Ty::from_type_relative_path(db, resolver, ty, remaining_segments); | ||
170 | } | ||
171 | let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) { | ||
172 | Some(it) => it, | ||
173 | None => return Ty::Unknown, | ||
174 | }; | ||
175 | let (resolved_segment, remaining_segments) = match remaining_index { | ||
176 | None => ( | ||
177 | path.segments.last().expect("resolved path has at least one element"), | ||
178 | &[] as &[PathSegment], | ||
179 | ), | ||
180 | Some(i) => (&path.segments[i - 1], &path.segments[i..]), | ||
181 | }; | ||
182 | Ty::from_partly_resolved_hir_path( | ||
183 | db, | ||
184 | resolver, | ||
185 | resolution, | ||
186 | resolved_segment, | ||
187 | remaining_segments, | ||
188 | ) | ||
189 | } | ||
190 | |||
191 | fn select_associated_type( | ||
192 | _db: &impl HirDatabase, | ||
193 | _resolver: &Resolver, | ||
194 | _self_ty: Ty, | ||
195 | _segment: &PathSegment, | ||
196 | ) -> Ty { | ||
197 | Ty::Unknown | ||
198 | } | ||
199 | |||
200 | fn from_hir_path_inner( | ||
201 | db: &impl HirDatabase, | ||
202 | resolver: &Resolver, | ||
203 | segment: &PathSegment, | ||
204 | typable: TypableDef, | ||
205 | ) -> Ty { | ||
159 | let ty = db.type_for_def(typable, Namespace::Types); | 206 | let ty = db.type_for_def(typable, Namespace::Types); |
160 | let substs = Ty::substs_from_path(db, resolver, path, typable); | 207 | let substs = Ty::substs_from_path_segment(db, resolver, segment, typable); |
161 | ty.subst(&substs) | 208 | ty.subst(&substs) |
162 | } | 209 | } |
163 | 210 | ||
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index be63806d4..8b46b11a9 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -11,13 +11,12 @@ use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitR | |||
11 | use crate::{ | 11 | use crate::{ |
12 | db::HirDatabase, | 12 | db::HirDatabase, |
13 | generics::HasGenericParams, | 13 | generics::HasGenericParams, |
14 | impl_block::{ImplBlock, ImplId, ImplItem}, | 14 | impl_block::{ImplBlock, ImplId}, |
15 | nameres::CrateModuleId, | 15 | nameres::CrateModuleId, |
16 | resolve::Resolver, | 16 | resolve::Resolver, |
17 | traits::TraitItem, | ||
18 | ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy}, | 17 | ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy}, |
19 | ty::{Ty, TypeCtor}, | 18 | ty::{Ty, TypeCtor}, |
20 | Crate, Function, Module, Name, Trait, | 19 | AssocItem, Crate, Function, Module, Name, Trait, |
21 | }; | 20 | }; |
22 | 21 | ||
23 | /// This is used as a key for indexing impls. | 22 | /// This is used as a key for indexing impls. |
@@ -232,7 +231,7 @@ fn iterate_trait_method_candidates<T>( | |||
232 | // iteration | 231 | // iteration |
233 | let mut known_implemented = inherently_implemented; | 232 | let mut known_implemented = inherently_implemented; |
234 | for item in data.items() { | 233 | for item in data.items() { |
235 | if let TraitItem::Function(m) = *item { | 234 | if let AssocItem::Function(m) = *item { |
236 | let data = m.data(db); | 235 | let data = m.data(db); |
237 | if name.map_or(true, |name| data.name() == name) && data.has_self_param() { | 236 | if name.map_or(true, |name| data.name() == name) && data.has_self_param() { |
238 | if !known_implemented { | 237 | if !known_implemented { |
@@ -264,7 +263,7 @@ fn iterate_inherent_methods<T>( | |||
264 | 263 | ||
265 | for impl_block in impls.lookup_impl_blocks(&ty.value) { | 264 | for impl_block in impls.lookup_impl_blocks(&ty.value) { |
266 | for item in impl_block.items(db) { | 265 | for item in impl_block.items(db) { |
267 | if let ImplItem::Method(f) = item { | 266 | if let AssocItem::Function(f) = item { |
268 | let data = f.data(db); | 267 | let data = f.data(db); |
269 | if name.map_or(true, |name| data.name() == name) && data.has_self_param() { | 268 | if name.map_or(true, |name| data.name() == name) && data.has_self_param() { |
270 | if let Some(result) = callback(&ty.value, f) { | 269 | if let Some(result) = callback(&ty.value, f) { |
@@ -304,7 +303,7 @@ impl Ty { | |||
304 | self, | 303 | self, |
305 | db: &impl HirDatabase, | 304 | db: &impl HirDatabase, |
306 | krate: Crate, | 305 | krate: Crate, |
307 | mut callback: impl FnMut(ImplItem) -> Option<T>, | 306 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
308 | ) -> Option<T> { | 307 | ) -> Option<T> { |
309 | for krate in def_crates(db, krate, &self)? { | 308 | for krate in def_crates(db, krate, &self)? { |
310 | let impls = db.impls_in_crate(krate); | 309 | let impls = db.impls_in_crate(krate); |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 1bd677cab..09c17fdf4 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2613,18 +2613,18 @@ fn infer_call_trait_method_on_generic_param_1() { | |||
2613 | assert_snapshot!( | 2613 | assert_snapshot!( |
2614 | infer(r#" | 2614 | infer(r#" |
2615 | trait Trait { | 2615 | trait Trait { |
2616 | fn method() -> u32; | 2616 | fn method(&self) -> u32; |
2617 | } | 2617 | } |
2618 | fn test<T: Trait>(t: T) { | 2618 | fn test<T: Trait>(t: T) { |
2619 | t.method(); | 2619 | t.method(); |
2620 | } | 2620 | } |
2621 | "#), | 2621 | "#), |
2622 | @r###" | 2622 | @r###" |
2623 | 2623 | [30; 34) 'self': &Self | |
2624 | [59; 60) 't': T | 2624 | [64; 65) 't': T |
2625 | [65; 84) '{ ...d(); }': () | 2625 | [70; 89) '{ ...d(); }': () |
2626 | [71; 72) 't': T | 2626 | [76; 77) 't': T |
2627 | [71; 81) 't.method()': {unknown} | 2627 | [76; 86) 't.method()': u32 |
2628 | "### | 2628 | "### |
2629 | ); | 2629 | ); |
2630 | } | 2630 | } |
@@ -2634,18 +2634,18 @@ fn infer_call_trait_method_on_generic_param_2() { | |||
2634 | assert_snapshot!( | 2634 | assert_snapshot!( |
2635 | infer(r#" | 2635 | infer(r#" |
2636 | trait Trait<T> { | 2636 | trait Trait<T> { |
2637 | fn method() -> T; | 2637 | fn method(&self) -> T; |
2638 | } | 2638 | } |
2639 | fn test<U, T: Trait<U>>(t: T) { | 2639 | fn test<U, T: Trait<U>>(t: T) { |
2640 | t.method(); | 2640 | t.method(); |
2641 | } | 2641 | } |
2642 | "#), | 2642 | "#), |
2643 | @r###" | 2643 | @r###" |
2644 | 2644 | [33; 37) 'self': &Self | |
2645 | [66; 67) 't': T | 2645 | [71; 72) 't': T |
2646 | [72; 91) '{ ...d(); }': () | 2646 | [77; 96) '{ ...d(); }': () |
2647 | [78; 79) 't': T | 2647 | [83; 84) 't': T |
2648 | [78; 88) 't.method()': {unknown} | 2648 | [83; 93) 't.method()': [missing name] |
2649 | "### | 2649 | "### |
2650 | ); | 2650 | ); |
2651 | } | 2651 | } |
@@ -2685,6 +2685,7 @@ fn test() { | |||
2685 | 2685 | ||
2686 | #[test] | 2686 | #[test] |
2687 | fn infer_project_associated_type() { | 2687 | fn infer_project_associated_type() { |
2688 | // y, z, a don't yet work because of https://github.com/rust-lang/chalk/issues/234 | ||
2688 | assert_snapshot!( | 2689 | assert_snapshot!( |
2689 | infer(r#" | 2690 | infer(r#" |
2690 | trait Iterable { | 2691 | trait Iterable { |
@@ -2696,16 +2697,19 @@ fn test<T: Iterable>() { | |||
2696 | let x: <S as Iterable>::Item = 1; | 2697 | let x: <S as Iterable>::Item = 1; |
2697 | let y: <T as Iterable>::Item = no_matter; | 2698 | let y: <T as Iterable>::Item = no_matter; |
2698 | let z: T::Item = no_matter; | 2699 | let z: T::Item = no_matter; |
2700 | let a: <T>::Item = no_matter; | ||
2699 | } | 2701 | } |
2700 | "#), | 2702 | "#), |
2701 | @r###" | 2703 | @r###" |
2702 | [108; 227) '{ ...ter; }': () | 2704 | [108; 261) '{ ...ter; }': () |
2703 | [118; 119) 'x': u32 | 2705 | [118; 119) 'x': u32 |
2704 | [145; 146) '1': u32 | 2706 | [145; 146) '1': u32 |
2705 | [156; 157) 'y': {unknown} | 2707 | [156; 157) 'y': {unknown} |
2706 | [183; 192) 'no_matter': {unknown} | 2708 | [183; 192) 'no_matter': {unknown} |
2707 | [202; 203) 'z': {unknown} | 2709 | [202; 203) 'z': {unknown} |
2708 | [215; 224) 'no_matter': {unknown} | 2710 | [215; 224) 'no_matter': {unknown} |
2711 | [234; 235) 'a': {unknown} | ||
2712 | [249; 258) 'no_matter': {unknown} | ||
2709 | "### | 2713 | "### |
2710 | ); | 2714 | ); |
2711 | } | 2715 | } |
@@ -2721,9 +2725,11 @@ struct S; | |||
2721 | impl Iterable for S { type Item = u32; } | 2725 | impl Iterable for S { type Item = u32; } |
2722 | fn foo1<T: Iterable>(t: T) -> T::Item {} | 2726 | fn foo1<T: Iterable>(t: T) -> T::Item {} |
2723 | fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} | 2727 | fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} |
2728 | fn foo3<T: Iterable>(t: T) -> <T>::Item {} | ||
2724 | fn test() { | 2729 | fn test() { |
2725 | let x = foo1(S); | 2730 | let x = foo1(S); |
2726 | let y = foo2(S); | 2731 | let y = foo2(S); |
2732 | let z = foo3(S); | ||
2727 | } | 2733 | } |
2728 | "#), | 2734 | "#), |
2729 | @r###" | 2735 | @r###" |
@@ -2731,15 +2737,21 @@ fn test() { | |||
2731 | [123; 125) '{}': () | 2737 | [123; 125) '{}': () |
2732 | [147; 148) 't': T | 2738 | [147; 148) 't': T |
2733 | [178; 180) '{}': () | 2739 | [178; 180) '{}': () |
2734 | [191; 236) '{ ...(S); }': () | 2740 | [202; 203) 't': T |
2735 | [201; 202) 'x': {unknown} | 2741 | [221; 223) '{}': () |
2736 | [205; 209) 'foo1': fn foo1<S>(T) -> {unknown} | 2742 | [234; 300) '{ ...(S); }': () |
2737 | [205; 212) 'foo1(S)': {unknown} | 2743 | [244; 245) 'x': {unknown} |
2738 | [210; 211) 'S': S | 2744 | [248; 252) 'foo1': fn foo1<S>(T) -> {unknown} |
2739 | [222; 223) 'y': u32 | 2745 | [248; 255) 'foo1(S)': {unknown} |
2740 | [226; 230) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item | 2746 | [253; 254) 'S': S |
2741 | [226; 233) 'foo2(S)': u32 | 2747 | [265; 266) 'y': u32 |
2742 | [231; 232) 'S': S | 2748 | [269; 273) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item |
2749 | [269; 276) 'foo2(S)': u32 | ||
2750 | [274; 275) 'S': S | ||
2751 | [286; 287) 'z': {unknown} | ||
2752 | [290; 294) 'foo3': fn foo3<S>(T) -> {unknown} | ||
2753 | [290; 297) 'foo3(S)': {unknown} | ||
2754 | [295; 296) 'S': S | ||
2743 | "### | 2755 | "### |
2744 | ); | 2756 | ); |
2745 | } | 2757 | } |
@@ -4050,6 +4062,48 @@ fn test<F: FnOnce(u32) -> u64>(f: F) { | |||
4050 | ); | 4062 | ); |
4051 | } | 4063 | } |
4052 | 4064 | ||
4065 | #[test] | ||
4066 | fn unselected_projection_in_trait_env() { | ||
4067 | let t = type_at( | ||
4068 | r#" | ||
4069 | //- /main.rs | ||
4070 | trait Trait { | ||
4071 | type Item; | ||
4072 | } | ||
4073 | |||
4074 | trait Trait2 { | ||
4075 | fn foo(&self) -> u32; | ||
4076 | } | ||
4077 | |||
4078 | fn test<T: Trait>() where T::Item: Trait2 { | ||
4079 | let x: T::Item = no_matter; | ||
4080 | x.foo()<|>; | ||
4081 | } | ||
4082 | "#, | ||
4083 | ); | ||
4084 | assert_eq!(t, "u32"); | ||
4085 | } | ||
4086 | |||
4087 | #[test] | ||
4088 | fn unselected_projection_in_trait_env_cycle() { | ||
4089 | let t = type_at( | ||
4090 | r#" | ||
4091 | //- /main.rs | ||
4092 | trait Trait { | ||
4093 | type Item; | ||
4094 | } | ||
4095 | |||
4096 | trait Trait2<T> {} | ||
4097 | |||
4098 | fn test<T: Trait>() where T: Trait2<T::Item> { | ||
4099 | let x: T::Item = no_matter<|>; | ||
4100 | } | ||
4101 | "#, | ||
4102 | ); | ||
4103 | // this is a legitimate cycle | ||
4104 | assert_eq!(t, "{unknown}"); | ||
4105 | } | ||
4106 | |||
4053 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 4107 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { |
4054 | let file = db.parse(pos.file_id).ok().unwrap(); | 4108 | let file = db.parse(pos.file_id).ok().unwrap(); |
4055 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); | 4109 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index c748e9d84..693d9b28f 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 21 | ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, |
22 | TypeWalk, | 22 | TypeWalk, |
23 | }, | 23 | }, |
24 | Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias, | 24 | AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | /// This represents a trait whose name we could not resolve. | 27 | /// This represents a trait whose name we could not resolve. |
@@ -496,7 +496,7 @@ pub(crate) fn trait_datum_query( | |||
496 | .items(db) | 496 | .items(db) |
497 | .into_iter() | 497 | .into_iter() |
498 | .filter_map(|trait_item| match trait_item { | 498 | .filter_map(|trait_item| match trait_item { |
499 | crate::traits::TraitItem::TypeAlias(type_alias) => Some(type_alias), | 499 | crate::AssocItem::TypeAlias(type_alias) => Some(type_alias), |
500 | _ => None, | 500 | _ => None, |
501 | }) | 501 | }) |
502 | .map(|type_alias| type_alias.to_chalk(db)) | 502 | .map(|type_alias| type_alias.to_chalk(db)) |
@@ -616,7 +616,7 @@ pub(crate) fn impl_datum_query( | |||
616 | .items(db) | 616 | .items(db) |
617 | .into_iter() | 617 | .into_iter() |
618 | .filter_map(|item| match item { | 618 | .filter_map(|item| match item { |
619 | ImplItem::TypeAlias(t) => Some(t), | 619 | AssocItem::TypeAlias(t) => Some(t), |
620 | _ => None, | 620 | _ => None, |
621 | }) | 621 | }) |
622 | .filter_map(|t| { | 622 | .filter_map(|t| { |