aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-09-16 13:43:21 +0100
committerGitHub <[email protected]>2019-09-16 13:43:21 +0100
commitba583091e60553633dd3cc9ab37a1d9f64827a1e (patch)
tree41a9b72f46b1119ff32964f77365459fdb46a37d /crates/ra_hir/src
parent6b33b90091b0cecd4c092d34451aba9f2492063c (diff)
parent7ed3be32916facf3b709d5277381408cd3ec134a (diff)
Merge #1817
1817: Support path starting with a type r=matklad a=uHOOCCOOHu The path syntax `<Ty>::foo` Co-authored-by: uHOOCCOOHu <[email protected]>
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/expr/validation.rs12
-rw-r--r--crates/ra_hir/src/name.rs27
-rw-r--r--crates/ra_hir/src/nameres.rs5
-rw-r--r--crates/ra_hir/src/path.rs100
-rw-r--r--crates/ra_hir/src/resolve.rs28
-rw-r--r--crates/ra_hir/src/source_binder.rs12
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs2
-rw-r--r--crates/ra_hir/src/ty/infer.rs127
-rw-r--r--crates/ra_hir/src/ty/tests.rs58
9 files changed, 227 insertions, 144 deletions
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index 030ec53a2..f06e5ec07 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -7,8 +7,7 @@ use crate::{
7 db::HirDatabase, 7 db::HirDatabase,
8 diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr}, 8 diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr},
9 expr::AstPtr, 9 expr::AstPtr,
10 name, 10 path::known,
11 path::{PathKind, PathSegment},
12 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, 11 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
13 Adt, Function, Name, Path, 12 Adt, Function, Name, Path,
14}; 13};
@@ -108,14 +107,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
108 None => return, 107 None => return,
109 }; 108 };
110 109
111 let std_result_path = Path { 110 let std_result_path = known::std_result_result();
112 kind: PathKind::Abs,
113 segments: vec![
114 PathSegment { name: name::STD, args_and_bindings: None },
115 PathSegment { name: name::RESULT_MOD, args_and_bindings: None },
116 PathSegment { name: name::RESULT_TYPE, args_and_bindings: None },
117 ],
118 };
119 111
120 let resolver = self.func.resolver(db); 112 let resolver = self.func.resolver(db);
121 let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { 113 let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) {
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index abdfec296..1bf993ffb 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -85,6 +85,7 @@ impl AsName for ra_db::Dependency {
85 } 85 }
86} 86}
87 87
88// Primitives
88pub(crate) const ISIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"isize")); 89pub(crate) const ISIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"isize"));
89pub(crate) const I8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"i8")); 90pub(crate) const I8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"i8"));
90pub(crate) const I16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i16")); 91pub(crate) const I16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i16"));
@@ -102,24 +103,30 @@ pub(crate) const F64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"f64")
102pub(crate) const BOOL: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"bool")); 103pub(crate) const BOOL: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"bool"));
103pub(crate) const CHAR: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"char")); 104pub(crate) const CHAR: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"char"));
104pub(crate) const STR: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"str")); 105pub(crate) const STR: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"str"));
106
107// Special names
105pub(crate) const SELF_PARAM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"self")); 108pub(crate) const SELF_PARAM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"self"));
106pub(crate) const SELF_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Self")); 109pub(crate) const SELF_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Self"));
107pub(crate) const MACRO_RULES: Name = Name::new(SmolStr::new_inline_from_ascii(11, b"macro_rules")); 110pub(crate) const MACRO_RULES: Name = Name::new(SmolStr::new_inline_from_ascii(11, b"macro_rules"));
111
112// Components of known path (value or mod name)
108pub(crate) const STD: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"std")); 113pub(crate) const STD: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"std"));
109pub(crate) const ITER: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"iter")); 114pub(crate) const ITER: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"iter"));
110pub(crate) const INTO_ITERATOR: Name =
111 Name::new(SmolStr::new_inline_from_ascii(12, b"IntoIterator"));
112pub(crate) const ITEM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Item"));
113pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops")); 115pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops"));
114pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")); 116pub(crate) const FUTURE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future"));
115pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); 117pub(crate) const RESULT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result"));
116pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future")); 118pub(crate) const BOXED: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"boxed"));
119
120// Components of known path (type name)
121pub(crate) const INTO_ITERATOR_TYPE: Name =
122 Name::new(SmolStr::new_inline_from_ascii(12, b"IntoIterator"));
123pub(crate) const ITEM_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Item"));
124pub(crate) const TRY_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try"));
125pub(crate) const OK_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok"));
117pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future")); 126pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future"));
118pub(crate) const RESULT_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result"));
119pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result")); 127pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result"));
120pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); 128pub(crate) const OUTPUT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output"));
121pub(crate) const TARGET: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target")); 129pub(crate) const TARGET_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target"));
122pub(crate) const BOXED_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"boxed"));
123pub(crate) const BOX_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Box")); 130pub(crate) const BOX_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Box"));
124 131
125fn resolve_name(text: &SmolStr) -> SmolStr { 132fn resolve_name(text: &SmolStr) -> SmolStr {
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 7922e3f7e..b808a0c36 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -382,6 +382,11 @@ impl CrateDefMap {
382 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude 382 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
383 } 383 }
384 } 384 }
385 PathKind::Type(_) => {
386 // This is handled in `infer::infer_path_expr`
387 // The result returned here does not matter
388 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
389 }
385 }; 390 };
386 391
387 for (i, segment) in segments { 392 for (i, segment) in segments {
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index d6c78593b..a61161b63 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -1,4 +1,4 @@
1use std::sync::Arc; 1use std::{iter, sync::Arc};
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast::{self, NameOwner, TypeAscriptionOwner}, 4 ast::{self, NameOwner, TypeAscriptionOwner},
@@ -42,7 +42,7 @@ pub enum GenericArg {
42 // or lifetime... 42 // or lifetime...
43} 43}
44 44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 45#[derive(Debug, Clone, PartialEq, Eq, Hash)]
46pub enum PathKind { 46pub enum PathKind {
47 Plain, 47 Plain,
48 Self_, 48 Self_,
@@ -50,6 +50,8 @@ pub enum PathKind {
50 Crate, 50 Crate,
51 // Absolute path 51 // Absolute path
52 Abs, 52 Abs,
53 // Type based path like `<T>::foo`
54 Type(Box<TypeRef>),
53} 55}
54 56
55impl Path { 57impl Path {
@@ -63,6 +65,16 @@ impl Path {
63 } 65 }
64 } 66 }
65 67
68 pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> Path {
69 Path {
70 kind,
71 segments: segments
72 .into_iter()
73 .map(|name| PathSegment { name, args_and_bindings: None })
74 .collect(),
75 }
76 }
77
66 /// Converts an `ast::Path` to `Path`. Works with use trees. 78 /// Converts an `ast::Path` to `Path`. Works with use trees.
67 pub fn from_ast(mut path: ast::Path) -> Option<Path> { 79 pub fn from_ast(mut path: ast::Path) -> Option<Path> {
68 let mut kind = PathKind::Plain; 80 let mut kind = PathKind::Plain;
@@ -92,24 +104,32 @@ impl Path {
92 ast::PathSegmentKind::Type { type_ref, trait_ref } => { 104 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
93 assert!(path.qualifier().is_none()); // this can only occur at the first segment 105 assert!(path.qualifier().is_none()); // this can only occur at the first segment
94 106
95 // FIXME: handle <T> syntax (type segments without trait)
96
97 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
98 let path = Path::from_ast(trait_ref?.path()?)?;
99 kind = path.kind;
100 let mut prefix_segments = path.segments;
101 prefix_segments.reverse();
102 segments.extend(prefix_segments);
103 // Insert the type reference (T in the above example) as Self parameter for the trait
104 let self_type = TypeRef::from_ast(type_ref?); 107 let self_type = TypeRef::from_ast(type_ref?);
105 let mut last_segment = segments.last_mut()?; 108
106 if last_segment.args_and_bindings.is_none() { 109 match trait_ref {
107 last_segment.args_and_bindings = Some(Arc::new(GenericArgs::empty())); 110 // <T>::foo
108 }; 111 None => {
109 let args = last_segment.args_and_bindings.as_mut().unwrap(); 112 kind = PathKind::Type(Box::new(self_type));
110 let mut args_inner = Arc::make_mut(args); 113 }
111 args_inner.has_self_type = true; 114 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
112 args_inner.args.insert(0, GenericArg::Type(self_type)); 115 Some(trait_ref) => {
116 let path = Path::from_ast(trait_ref.path()?)?;
117 kind = path.kind;
118 let mut prefix_segments = path.segments;
119 prefix_segments.reverse();
120 segments.extend(prefix_segments);
121 // Insert the type reference (T in the above example) as Self parameter for the trait
122 let mut last_segment = segments.last_mut()?;
123 if last_segment.args_and_bindings.is_none() {
124 last_segment.args_and_bindings =
125 Some(Arc::new(GenericArgs::empty()));
126 };
127 let args = last_segment.args_and_bindings.as_mut().unwrap();
128 let mut args_inner = Arc::make_mut(args);
129 args_inner.has_self_type = true;
130 args_inner.args.insert(0, GenericArg::Type(self_type));
131 }
132 }
113 } 133 }
114 ast::PathSegmentKind::CrateKw => { 134 ast::PathSegmentKind::CrateKw => {
115 kind = PathKind::Crate; 135 kind = PathKind::Crate;
@@ -214,7 +234,7 @@ impl GenericArgs {
214 } 234 }
215 if let Some(ret_type) = ret_type { 235 if let Some(ret_type) = ret_type {
216 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); 236 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
217 bindings.push((name::OUTPUT, type_ref)) 237 bindings.push((name::OUTPUT_TYPE, type_ref))
218 } 238 }
219 if args.is_empty() && bindings.is_empty() { 239 if args.is_empty() && bindings.is_empty() {
220 None 240 None
@@ -230,10 +250,7 @@ impl GenericArgs {
230 250
231impl From<Name> for Path { 251impl From<Name> for Path {
232 fn from(name: Name) -> Path { 252 fn from(name: Name) -> Path {
233 Path { 253 Path::from_simple_segments(PathKind::Plain, iter::once(name))
234 kind: PathKind::Plain,
235 segments: vec![PathSegment { name, args_and_bindings: None }],
236 }
237 } 254 }
238} 255}
239 256
@@ -287,6 +304,7 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
287 let segment = path.segment()?; 304 let segment = path.segment()?;
288 let res = match segment.kind()? { 305 let res = match segment.kind()? {
289 ast::PathSegmentKind::Name(name) => { 306 ast::PathSegmentKind::Name(name) => {
307 // no type args in use
290 let mut res = prefix 308 let mut res = prefix
291 .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) }); 309 .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) });
292 res.segments.push(PathSegment { 310 res.segments.push(PathSegment {
@@ -299,19 +317,19 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
299 if prefix.is_some() { 317 if prefix.is_some() {
300 return None; 318 return None;
301 } 319 }
302 Path { kind: PathKind::Crate, segments: Vec::new() } 320 Path::from_simple_segments(PathKind::Crate, iter::empty())
303 } 321 }
304 ast::PathSegmentKind::SelfKw => { 322 ast::PathSegmentKind::SelfKw => {
305 if prefix.is_some() { 323 if prefix.is_some() {
306 return None; 324 return None;
307 } 325 }
308 Path { kind: PathKind::Self_, segments: Vec::new() } 326 Path::from_simple_segments(PathKind::Self_, iter::empty())
309 } 327 }
310 ast::PathSegmentKind::SuperKw => { 328 ast::PathSegmentKind::SuperKw => {
311 if prefix.is_some() { 329 if prefix.is_some() {
312 return None; 330 return None;
313 } 331 }
314 Path { kind: PathKind::Super, segments: Vec::new() } 332 Path::from_simple_segments(PathKind::Super, iter::empty())
315 } 333 }
316 ast::PathSegmentKind::Type { .. } => { 334 ast::PathSegmentKind::Type { .. } => {
317 // not allowed in imports 335 // not allowed in imports
@@ -320,3 +338,31 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
320 }; 338 };
321 Some(res) 339 Some(res)
322} 340}
341
342pub mod known {
343 use super::{Path, PathKind};
344 use crate::name;
345
346 pub fn std_iter_into_iterator() -> Path {
347 Path::from_simple_segments(
348 PathKind::Abs,
349 vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE],
350 )
351 }
352
353 pub fn std_ops_try() -> Path {
354 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE])
355 }
356
357 pub fn std_result_result() -> Path {
358 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE])
359 }
360
361 pub fn std_future_future() -> Path {
362 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE])
363 }
364
365 pub fn std_boxed_box() -> Path {
366 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE])
367 }
368}
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 3207b6626..bb6915901 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -15,6 +15,7 @@ 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,
18 Adt, BuiltinType, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct, 19 Adt, BuiltinType, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct,
19 Trait, TypeAlias, 20 Trait, TypeAlias,
20}; 21};
@@ -64,9 +65,10 @@ pub enum TypeNs {
64} 65}
65 66
66#[derive(Debug)] 67#[derive(Debug)]
67pub enum ValueOrPartial { 68pub enum ResolveValueResult<'a> {
68 ValueNs(ValueNs), 69 ValueNs(ValueNs),
69 Partial(TypeNs, usize), 70 Partial(TypeNs, usize),
71 TypeRef(&'a TypeRef),
70} 72}
71 73
72#[derive(Debug)] 74#[derive(Debug)]
@@ -183,11 +185,15 @@ impl Resolver {
183 Some(res) 185 Some(res)
184 } 186 }
185 187
186 pub(crate) fn resolve_path_in_value_ns( 188 pub(crate) fn resolve_path_in_value_ns<'p>(
187 &self, 189 &self,
188 db: &impl HirDatabase, 190 db: &impl HirDatabase,
189 path: &Path, 191 path: &'p Path,
190 ) -> Option<ValueOrPartial> { 192 ) -> Option<ResolveValueResult<'p>> {
193 if let PathKind::Type(type_ref) = &path.kind {
194 return Some(ResolveValueResult::TypeRef(type_ref));
195 }
196
191 let n_segments = path.segments.len(); 197 let n_segments = path.segments.len();
192 let tmp = SELF_PARAM; 198 let tmp = SELF_PARAM;
193 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 };
@@ -208,7 +214,7 @@ impl Resolver {
208 .find(|entry| entry.name() == first_name); 214 .find(|entry| entry.name() == first_name);
209 215
210 if let Some(e) = entry { 216 if let Some(e) = entry {
211 return Some(ValueOrPartial::ValueNs(ValueNs::LocalBinding(e.pat()))); 217 return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(e.pat())));
212 } 218 }
213 } 219 }
214 Scope::ExprScope(_) => continue, 220 Scope::ExprScope(_) => continue,
@@ -216,7 +222,7 @@ impl Resolver {
216 Scope::GenericParams(params) if n_segments > 1 => { 222 Scope::GenericParams(params) if n_segments > 1 => {
217 if let Some(param) = params.find_by_name(first_name) { 223 if let Some(param) = params.find_by_name(first_name) {
218 let ty = TypeNs::GenericParam(param.idx); 224 let ty = TypeNs::GenericParam(param.idx);
219 return Some(ValueOrPartial::Partial(ty, 1)); 225 return Some(ResolveValueResult::Partial(ty, 1));
220 } 226 }
221 } 227 }
222 Scope::GenericParams(_) => continue, 228 Scope::GenericParams(_) => continue,
@@ -224,7 +230,7 @@ impl Resolver {
224 Scope::ImplBlockScope(impl_) if n_segments > 1 => { 230 Scope::ImplBlockScope(impl_) if n_segments > 1 => {
225 if first_name == &SELF_TYPE { 231 if first_name == &SELF_TYPE {
226 let ty = TypeNs::SelfType(*impl_); 232 let ty = TypeNs::SelfType(*impl_);
227 return Some(ValueOrPartial::Partial(ty, 1)); 233 return Some(ResolveValueResult::Partial(ty, 1));
228 } 234 }
229 } 235 }
230 Scope::ImplBlockScope(_) => continue, 236 Scope::ImplBlockScope(_) => continue,
@@ -247,7 +253,7 @@ impl Resolver {
247 | ModuleDef::BuiltinType(_) 253 | ModuleDef::BuiltinType(_)
248 | ModuleDef::Module(_) => return None, 254 | ModuleDef::Module(_) => return None,
249 }; 255 };
250 Some(ValueOrPartial::ValueNs(value)) 256 Some(ResolveValueResult::ValueNs(value))
251 } 257 }
252 Some(idx) => { 258 Some(idx) => {
253 let ty = match module_def.take_types()? { 259 let ty = match module_def.take_types()? {
@@ -262,7 +268,7 @@ impl Resolver {
262 | ModuleDef::Const(_) 268 | ModuleDef::Const(_)
263 | ModuleDef::Static(_) => return None, 269 | ModuleDef::Static(_) => return None,
264 }; 270 };
265 Some(ValueOrPartial::Partial(ty, idx)) 271 Some(ResolveValueResult::Partial(ty, idx))
266 } 272 }
267 }; 273 };
268 } 274 }
@@ -277,8 +283,8 @@ impl Resolver {
277 path: &Path, 283 path: &Path,
278 ) -> Option<ValueNs> { 284 ) -> Option<ValueNs> {
279 match self.resolve_path_in_value_ns(db, path)? { 285 match self.resolve_path_in_value_ns(db, path)? {
280 ValueOrPartial::ValueNs(it) => Some(it), 286 ResolveValueResult::ValueNs(it) => Some(it),
281 ValueOrPartial::Partial(..) => None, 287 ResolveValueResult::Partial(..) | ResolveValueResult::TypeRef(_) => None,
282 } 288 }
283 } 289 }
284 290
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index cff55b640..2a907c9f1 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -25,8 +25,7 @@ use crate::{
25 BodySourceMap, 25 BodySourceMap,
26 }, 26 },
27 ids::LocationCtx, 27 ids::LocationCtx,
28 name, 28 path::known,
29 path::{PathKind, PathSegment},
30 resolve::{ScopeDef, TypeNs, ValueNs}, 29 resolve::{ScopeDef, TypeNs, ValueNs},
31 ty::method_resolution::implements_trait, 30 ty::method_resolution::implements_trait,
32 AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef, 31 AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef,
@@ -433,14 +432,7 @@ impl SourceAnalyzer {
433 /// Checks that particular type `ty` implements `std::future::Future`. 432 /// Checks that particular type `ty` implements `std::future::Future`.
434 /// This function is used in `.await` syntax completion. 433 /// This function is used in `.await` syntax completion.
435 pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool { 434 pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool {
436 let std_future_path = Path { 435 let std_future_path = known::std_future_future();
437 kind: PathKind::Abs,
438 segments: vec![
439 PathSegment { name: name::STD, args_and_bindings: None },
440 PathSegment { name: name::FUTURE_MOD, args_and_bindings: None },
441 PathSegment { name: name::FUTURE_TYPE, args_and_bindings: None },
442 ],
443 };
444 436
445 let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) { 437 let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) {
446 Some(it) => it, 438 Some(it) => it,
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index 5ba7cf2e0..94f8ecdc9 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -42,7 +42,7 @@ fn deref_by_trait(
42 crate::lang_item::LangItemTarget::Trait(t) => t, 42 crate::lang_item::LangItemTarget::Trait(t) => t,
43 _ => return None, 43 _ => return None,
44 }; 44 };
45 let target = deref_trait.associated_type_by_name(db, &name::TARGET)?; 45 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?;
46 46
47 if target.generic_params(db).count_params_including_parent() != 1 { 47 if target.generic_params(db).count_params_including_parent() != 1 {
48 // the Target type + Deref trait should only have one generic parameter, 48 // the Target type + Deref trait should only have one generic parameter,
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 7d9b86752..bf9609d8c 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -44,11 +44,12 @@ use crate::{
44 generics::{GenericParams, HasGenericParams}, 44 generics::{GenericParams, HasGenericParams},
45 name, 45 name,
46 nameres::Namespace, 46 nameres::Namespace,
47 path::{GenericArg, GenericArgs, PathKind, PathSegment}, 47 path::{known, GenericArg, GenericArgs},
48 resolve::{Resolver, TypeNs, ValueNs, ValueOrPartial}, 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, FnData, Function, HasBody, ImplItem, Name, Path, StructField, 51 Adt, ConstData, DefWithBody, Either, FnData, Function, HasBody, ImplItem, Name, Path,
52 StructField,
52}; 53};
53 54
54mod unify; 55mod unify;
@@ -470,9 +471,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
470 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?; 471 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?;
471 472
472 let (value, self_subst) = match value_or_partial { 473 let (value, self_subst) = match value_or_partial {
473 ValueOrPartial::ValueNs(it) => (it, None), 474 ResolveValueResult::ValueNs(it) => (it, None),
474 ValueOrPartial::Partial(def, remaining_index) => { 475 ResolveValueResult::Partial(def, remaining_index) => {
475 self.resolve_assoc_item(def, path, remaining_index, id)? 476 self.resolve_assoc_item(Either::A(def), path, remaining_index, id)?
477 }
478 ResolveValueResult::TypeRef(type_ref) => {
479 let ty = self.make_ty(type_ref);
480 self.resolve_assoc_item(Either::B(ty), path, 0, id)?
476 } 481 }
477 }; 482 };
478 483
@@ -503,7 +508,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
503 508
504 fn resolve_assoc_item( 509 fn resolve_assoc_item(
505 &mut self, 510 &mut self,
506 mut def: TypeNs, 511 mut def_or_ty: Either<TypeNs, Ty>,
507 path: &Path, 512 path: &Path,
508 remaining_index: usize, 513 remaining_index: usize,
509 id: ExprOrPatId, 514 id: ExprOrPatId,
@@ -516,30 +521,33 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
516 // resolve intermediate segments 521 // resolve intermediate segments
517 for (i, segment) in path.segments[remaining_index..].iter().enumerate() { 522 for (i, segment) in path.segments[remaining_index..].iter().enumerate() {
518 let is_last_segment = i == path.segments[remaining_index..].len() - 1; 523 let is_last_segment = i == path.segments[remaining_index..].len() - 1;
519 ty = { 524 ty = match def_or_ty {
520 let typable: TypableDef = match def { 525 Either::A(def) => {
521 TypeNs::Adt(it) => it.into(), 526 let typable: TypableDef = match def {
522 TypeNs::TypeAlias(it) => it.into(), 527 TypeNs::Adt(it) => it.into(),
523 TypeNs::BuiltinType(it) => it.into(), 528 TypeNs::TypeAlias(it) => it.into(),
524 // FIXME associated item of traits, generics, and Self 529 TypeNs::BuiltinType(it) => it.into(),
525 TypeNs::Trait(_) | TypeNs::GenericParam(_) | TypeNs::SelfType(_) => { 530 // FIXME associated item of traits, generics, and Self
526 return None; 531 TypeNs::Trait(_) | TypeNs::GenericParam(_) | TypeNs::SelfType(_) => {
527 } 532 return None;
528 // FIXME: report error here 533 }
529 TypeNs::EnumVariant(_) => return None, 534 // FIXME: report error here
530 }; 535 TypeNs::EnumVariant(_) => return None,
531 536 };
532 let ty = self.db.type_for_def(typable, Namespace::Types);
533 537
534 // For example, this substs will take `Gen::*<u32>*::make` 538 let ty = self.db.type_for_def(typable, Namespace::Types);
535 assert!(remaining_index > 0); 539
536 let substs = Ty::substs_from_path_segment( 540 // For example, this substs will take `Gen::*<u32>*::make`
537 self.db, 541 assert!(remaining_index > 0);
538 &self.resolver, 542 let substs = Ty::substs_from_path_segment(
539 &path.segments[remaining_index + i - 1], 543 self.db,
540 typable, 544 &self.resolver,
541 ); 545 &path.segments[remaining_index + i - 1],
542 ty.subst(&substs) 546 typable,
547 );
548 ty.subst(&substs)
549 }
550 Either::B(ty) => ty,
543 }; 551 };
544 if is_last_segment { 552 if is_last_segment {
545 break; 553 break;
@@ -550,15 +558,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
550 log::debug!("looking for path segment: {:?}", segment); 558 log::debug!("looking for path segment: {:?}", segment);
551 559
552 let ty = mem::replace(&mut ty, Ty::Unknown); 560 let ty = mem::replace(&mut ty, Ty::Unknown);
553 def = ty.iterate_impl_items(self.db, krate, |item| { 561 def_or_ty = ty.iterate_impl_items(self.db, krate, |item| {
554 match item { 562 match item {
555 crate::ImplItem::Method(_) => None, 563 crate::ImplItem::Method(_) => None,
556 crate::ImplItem::Const(_) => None, 564 crate::ImplItem::Const(_) => None,
557 565
558 // FIXME: Resolve associated types 566 // FIXME: Resolve associated types
559 crate::ImplItem::TypeAlias(_) => { 567 crate::ImplItem::TypeAlias(_) => {
560 // Some(TypeNs::TypeAlias(..)) 568 // Some(Either::A(TypeNs::TypeAlias(..)))
561 None::<TypeNs> 569 None
562 } 570 }
563 } 571 }
564 })?; 572 })?;
@@ -1434,57 +1442,26 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1434 } 1442 }
1435 1443
1436 fn resolve_into_iter_item(&self) -> Option<TypeAlias> { 1444 fn resolve_into_iter_item(&self) -> Option<TypeAlias> {
1437 let into_iter_path = Path { 1445 let path = known::std_iter_into_iterator();
1438 kind: PathKind::Abs, 1446 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
1439 segments: vec![ 1447 trait_.associated_type_by_name(self.db, &name::ITEM_TYPE)
1440 PathSegment { name: name::STD, args_and_bindings: None },
1441 PathSegment { name: name::ITER, args_and_bindings: None },
1442 PathSegment { name: name::INTO_ITERATOR, args_and_bindings: None },
1443 ],
1444 };
1445
1446 let trait_ = self.resolver.resolve_known_trait(self.db, &into_iter_path)?;
1447 trait_.associated_type_by_name(self.db, &name::ITEM)
1448 } 1448 }
1449 1449
1450 fn resolve_ops_try_ok(&self) -> Option<TypeAlias> { 1450 fn resolve_ops_try_ok(&self) -> Option<TypeAlias> {
1451 let ops_try_path = Path { 1451 let path = known::std_ops_try();
1452 kind: PathKind::Abs, 1452 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
1453 segments: vec![ 1453 trait_.associated_type_by_name(self.db, &name::OK_TYPE)
1454 PathSegment { name: name::STD, args_and_bindings: None },
1455 PathSegment { name: name::OPS, args_and_bindings: None },
1456 PathSegment { name: name::TRY, args_and_bindings: None },
1457 ],
1458 };
1459
1460 let trait_ = self.resolver.resolve_known_trait(self.db, &ops_try_path)?;
1461 trait_.associated_type_by_name(self.db, &name::OK)
1462 } 1454 }
1463 1455
1464 fn resolve_future_future_output(&self) -> Option<TypeAlias> { 1456 fn resolve_future_future_output(&self) -> Option<TypeAlias> {
1465 let future_future_path = Path { 1457 let path = known::std_future_future();
1466 kind: PathKind::Abs, 1458 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
1467 segments: vec![ 1459 trait_.associated_type_by_name(self.db, &name::OUTPUT_TYPE)
1468 PathSegment { name: name::STD, args_and_bindings: None },
1469 PathSegment { name: name::FUTURE_MOD, args_and_bindings: None },
1470 PathSegment { name: name::FUTURE_TYPE, args_and_bindings: None },
1471 ],
1472 };
1473
1474 let trait_ = self.resolver.resolve_known_trait(self.db, &future_future_path)?;
1475 trait_.associated_type_by_name(self.db, &name::OUTPUT)
1476 } 1460 }
1477 1461
1478 fn resolve_boxed_box(&self) -> Option<Adt> { 1462 fn resolve_boxed_box(&self) -> Option<Adt> {
1479 let boxed_box_path = Path { 1463 let path = known::std_boxed_box();
1480 kind: PathKind::Abs, 1464 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
1481 segments: vec![
1482 PathSegment { name: name::STD, args_and_bindings: None },
1483 PathSegment { name: name::BOXED_MOD, args_and_bindings: None },
1484 PathSegment { name: name::BOX_TYPE, args_and_bindings: None },
1485 ],
1486 };
1487 let struct_ = self.resolver.resolve_known_struct(self.db, &boxed_box_path)?;
1488 Some(Adt::Struct(struct_)) 1465 Some(Adt::Struct(struct_))
1489 } 1466 }
1490} 1467}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f6a2a658f..1bd677cab 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -282,6 +282,64 @@ fn test() {
282} 282}
283 283
284#[test] 284#[test]
285fn infer_path_type() {
286 assert_snapshot!(
287 infer(r#"
288struct S;
289
290impl S {
291 fn foo() -> i32 { 1 }
292}
293
294fn test() {
295 S::foo();
296 <S>::foo();
297}
298"#),
299 @r###"
300 [41; 46) '{ 1 }': i32
301 [43; 44) '1': i32
302 [60; 93) '{ ...o(); }': ()
303 [66; 72) 'S::foo': fn foo() -> i32
304 [66; 74) 'S::foo()': i32
305 [80; 88) '<S>::foo': fn foo() -> i32
306 [80; 90) '<S>::foo()': i32
307"###
308 );
309}
310
311#[test]
312fn infer_slice_method() {
313 assert_snapshot!(
314 infer(r#"
315#[lang = "slice"]
316impl<T> [T] {
317 fn foo(&self) -> T {
318 loop {}
319 }
320}
321
322#[lang = "slice_alloc"]
323impl<T> [T] {}
324
325fn test() {
326 <[_]>::foo(b"foo");
327}
328"#),
329 @r###"
330 [45; 49) 'self': &[T]
331 [56; 79) '{ ... }': !
332 [66; 73) 'loop {}': !
333 [71; 73) '{}': ()
334 [133; 160) '{ ...o"); }': ()
335 [139; 149) '<[_]>::foo': fn foo<u8>(&[T]) -> T
336 [139; 157) '<[_]>:..."foo")': u8
337 [150; 156) 'b"foo"': &[u8]
338"###
339 );
340}
341
342#[test]
285fn infer_struct() { 343fn infer_struct() {
286 assert_snapshot!( 344 assert_snapshot!(
287 infer(r#" 345 infer(r#"