aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model.rs24
-rw-r--r--crates/ra_hir/src/impl_block.rs28
-rw-r--r--crates/ra_hir/src/lib.rs8
-rw-r--r--crates/ra_hir/src/path.rs7
-rw-r--r--crates/ra_hir/src/resolve.rs24
-rw-r--r--crates/ra_hir/src/source_binder.rs2
-rw-r--r--crates/ra_hir/src/traits.rs23
-rw-r--r--crates/ra_hir/src/ty/infer.rs188
-rw-r--r--crates/ra_hir/src/ty/lower.rs159
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs11
-rw-r--r--crates/ra_hir/src/ty/tests.rs98
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs6
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)]
1028pub 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.
1037impl_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 {
56impl ImplBlock { 56impl 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 {
113pub struct ImplData { 113pub 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?
161pub enum ImplItem {
162 Method(Function),
163 Const(Const),
164 TypeAlias(TypeAlias),
165 // Existential
166}
167impl_froms!(ImplItem: Const, TypeAlias);
168
169impl 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)]
176pub struct ImplId(pub RawId); 160pub struct ImplId(pub RawId);
177impl_arena_id!(ImplId); 161impl_arena_id!(ImplId);
@@ -185,7 +169,7 @@ impl_arena_id!(ImplId);
185pub struct ModuleImplBlocks { 169pub 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
191impl ModuleImplBlocks { 175impl 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::{
85pub use self::code_model::{ 85pub 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
195impl GenericArgs { 202impl 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)]
54pub enum TypeNs { 53pub 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)]
68pub enum ResolveValueResult<'a> { 67pub 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)]
75pub enum ValueNs { 73pub 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)]
16pub struct TraitData { 16pub 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)]
61pub 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.
71impl_froms!(TraitItem: Function, Const, TypeAlias);
72
73#[derive(Debug, Clone, PartialEq, Eq)] 60#[derive(Debug, Clone, PartialEq, Eq)]
74pub struct TraitItemsIndex { 61pub struct TraitItemsIndex {
75 traits_by_def: FxHashMap<TraitItem, Trait>, 62 traits_by_def: FxHashMap<AssocItem, Trait>,
76} 63}
77 64
78impl TraitItemsIndex { 65impl 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
55mod unify; 54mod 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
11use crate::{ 11use 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#"
2615trait Trait { 2615trait Trait {
2616 fn method() -> u32; 2616 fn method(&self) -> u32;
2617} 2617}
2618fn test<T: Trait>(t: T) { 2618fn 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#"
2636trait Trait<T> { 2636trait Trait<T> {
2637 fn method() -> T; 2637 fn method(&self) -> T;
2638} 2638}
2639fn test<U, T: Trait<U>>(t: T) { 2639fn 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]
2687fn infer_project_associated_type() { 2687fn 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#"
2690trait Iterable { 2691trait 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;
2721impl Iterable for S { type Item = u32; } 2725impl Iterable for S { type Item = u32; }
2722fn foo1<T: Iterable>(t: T) -> T::Item {} 2726fn foo1<T: Iterable>(t: T) -> T::Item {}
2723fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} 2727fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {}
2728fn foo3<T: Iterable>(t: T) -> <T>::Item {}
2724fn test() { 2729fn 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]
4066fn unselected_projection_in_trait_env() {
4067 let t = type_at(
4068 r#"
4069//- /main.rs
4070trait Trait {
4071 type Item;
4072}
4073
4074trait Trait2 {
4075 fn foo(&self) -> u32;
4076}
4077
4078fn 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]
4088fn unselected_projection_in_trait_env_cycle() {
4089 let t = type_at(
4090 r#"
4091//- /main.rs
4092trait Trait {
4093 type Item;
4094}
4095
4096trait Trait2<T> {}
4097
4098fn 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
4053fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 4107fn 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| {