aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-11-02 12:43:57 +0000
committerSeivan Heidari <[email protected]>2019-11-02 12:43:57 +0000
commit1d8bb4c6c1fef1f8ea513e07d0a7d4c5483129d2 (patch)
tree055ee515dfaad62af5d2a92bb4ab921a88ee09de
parent1b6c68e51fcbba59c2e99c31d1400cbd6d44f928 (diff)
parenteb8f76a86fe88fcad370577b344f397dd6118cfd (diff)
Merge branch 'master' into feature/themes
-rw-r--r--crates/ra_hir/src/code_model.rs9
-rw-r--r--crates/ra_hir/src/generics.rs3
-rw-r--r--crates/ra_hir/src/source_binder.rs40
-rw-r--r--crates/ra_hir/src/ty.rs19
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs82
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs141
-rw-r--r--crates/ra_hir/src/ty/tests.rs173
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs142
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs74
-rw-r--r--crates/ra_syntax/src/ast.rs14
-rw-r--r--crates/ra_syntax/src/parsing/text_tree_sink.rs2
-rw-r--r--xtask/src/lib.rs9
12 files changed, 605 insertions, 103 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index ae6ef7606..c97ea18a2 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1053,4 +1053,13 @@ impl AssocItem {
1053 AssocItem::TypeAlias(t) => t.module(db), 1053 AssocItem::TypeAlias(t) => t.module(db),
1054 } 1054 }
1055 } 1055 }
1056
1057 pub fn container(self, db: &impl DefDatabase) -> Container {
1058 match self {
1059 AssocItem::Function(f) => f.container(db),
1060 AssocItem::Const(c) => c.container(db),
1061 AssocItem::TypeAlias(t) => t.container(db),
1062 }
1063 .expect("AssocItem without container")
1064 }
1056} 1065}
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 52e1fbf29..9c261eda9 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -77,9 +77,10 @@ impl GenericParams {
77 let parent = match def { 77 let parent = match def {
78 GenericDef::Function(it) => it.container(db).map(GenericDef::from), 78 GenericDef::Function(it) => it.container(db).map(GenericDef::from),
79 GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), 79 GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from),
80 GenericDef::Const(it) => it.container(db).map(GenericDef::from),
80 GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()), 81 GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()),
81 GenericDef::Adt(_) | GenericDef::Trait(_) => None, 82 GenericDef::Adt(_) | GenericDef::Trait(_) => None,
82 GenericDef::ImplBlock(_) | GenericDef::Const(_) => None, 83 GenericDef::ImplBlock(_) => None,
83 }; 84 };
84 let mut generics = GenericParams { 85 let mut generics = GenericParams {
85 def, 86 def,
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 152bc71bd..a4ca59bba 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -27,9 +27,9 @@ use crate::{
27 }, 27 },
28 ids::LocationCtx, 28 ids::LocationCtx,
29 resolve::{ScopeDef, TypeNs, ValueNs}, 29 resolve::{ScopeDef, TypeNs, ValueNs},
30 ty::method_resolution::implements_trait, 30 ty::method_resolution::{self, implements_trait},
31 Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, MacroDef, Module, 31 AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId,
32 Name, Path, Resolver, Static, Struct, Ty, 32 MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty,
33}; 33};
34 34
35fn try_get_resolver_for_node( 35fn try_get_resolver_for_node(
@@ -255,7 +255,9 @@ impl SourceAnalyzer {
255 255
256 let items = 256 let items =
257 self.resolver.resolve_module_path(db, &path).take_types().map(PathResolution::Def); 257 self.resolver.resolve_module_path(db, &path).take_types().map(PathResolution::Def);
258 types.or(values).or(items) 258 types.or(values).or(items).or_else(|| {
259 self.resolver.resolve_path_as_macro(db, &path).map(|def| PathResolution::Macro(def))
260 })
259 } 261 }
260 262
261 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> { 263 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> {
@@ -325,16 +327,42 @@ impl SourceAnalyzer {
325 db: &impl HirDatabase, 327 db: &impl HirDatabase,
326 ty: Ty, 328 ty: Ty,
327 name: Option<&Name>, 329 name: Option<&Name>,
328 callback: impl FnMut(&Ty, Function) -> Option<T>, 330 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
331 ) -> Option<T> {
332 // There should be no inference vars in types passed here
333 // FIXME check that?
334 // FIXME replace Unknown by bound vars here
335 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
336 method_resolution::iterate_method_candidates(
337 &canonical,
338 db,
339 &self.resolver,
340 name,
341 method_resolution::LookupMode::MethodCall,
342 |ty, it| match it {
343 AssocItem::Function(f) => callback(ty, f),
344 _ => None,
345 },
346 )
347 }
348
349 pub fn iterate_path_candidates<T>(
350 &self,
351 db: &impl HirDatabase,
352 ty: Ty,
353 name: Option<&Name>,
354 callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
329 ) -> Option<T> { 355 ) -> Option<T> {
330 // There should be no inference vars in types passed here 356 // There should be no inference vars in types passed here
331 // FIXME check that? 357 // FIXME check that?
358 // FIXME replace Unknown by bound vars here
332 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; 359 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
333 crate::ty::method_resolution::iterate_method_candidates( 360 method_resolution::iterate_method_candidates(
334 &canonical, 361 &canonical,
335 db, 362 db,
336 &self.resolver, 363 &self.resolver,
337 name, 364 name,
365 method_resolution::LookupMode::Path,
338 callback, 366 callback,
339 ) 367 )
340 } 368 }
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index d2bfcdc7d..d1a9d7411 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -385,13 +385,22 @@ impl SubstsBuilder {
385 self.param_count - self.vec.len() 385 self.param_count - self.vec.len()
386 } 386 }
387 387
388 pub fn fill_with_bound_vars(mut self, starting_from: u32) -> Self { 388 pub fn fill_with_bound_vars(self, starting_from: u32) -> Self {
389 self.vec.extend((starting_from..starting_from + self.remaining() as u32).map(Ty::Bound)); 389 self.fill((starting_from..).map(Ty::Bound))
390 self 390 }
391
392 pub fn fill_with_params(self) -> Self {
393 let start = self.vec.len() as u32;
394 self.fill((start..).map(|idx| Ty::Param { idx, name: Name::missing() }))
395 }
396
397 pub fn fill_with_unknown(self) -> Self {
398 self.fill(iter::repeat(Ty::Unknown))
391 } 399 }
392 400
393 pub fn fill_with_unknown(mut self) -> Self { 401 pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self {
394 self.vec.extend(iter::repeat(Ty::Unknown).take(self.remaining())); 402 self.vec.extend(filler.take(self.remaining()));
403 assert_eq!(self.remaining(), 0);
395 self 404 self
396 } 405 }
397 406
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 77aa35ce1..59b7f7eb6 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -6,8 +6,8 @@ use super::{ExprOrPatId, InferenceContext, TraitRef};
6use crate::{ 6use crate::{
7 db::HirDatabase, 7 db::HirDatabase,
8 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 8 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs},
9 ty::{Substs, Ty, TypableDef, TypeWalk}, 9 ty::{method_resolution, Substs, Ty, TypableDef, TypeWalk},
10 AssocItem, HasGenericParams, Namespace, Path, 10 AssocItem, Container, HasGenericParams, Name, Namespace, Path,
11}; 11};
12 12
13impl<'a, D: HirDatabase> InferenceContext<'a, D> { 13impl<'a, D: HirDatabase> InferenceContext<'a, D> {
@@ -39,7 +39,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
39 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); 39 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty);
40 self.resolve_ty_assoc_item( 40 self.resolve_ty_assoc_item(
41 ty, 41 ty,
42 path.segments.last().expect("path had at least one segment"), 42 &path.segments.last().expect("path had at least one segment").name,
43 id, 43 id,
44 )? 44 )?
45 } else { 45 } else {
@@ -122,10 +122,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
122 return None; 122 return None;
123 } 123 }
124 124
125 let ty = self.insert_type_vars(ty);
126 let ty = self.normalize_associated_types_in(ty);
127
125 let segment = 128 let segment =
126 remaining_segments.last().expect("there should be at least one segment here"); 129 remaining_segments.last().expect("there should be at least one segment here");
127 130
128 self.resolve_ty_assoc_item(ty, segment, id) 131 self.resolve_ty_assoc_item(ty, &segment.name, id)
129 } 132 }
130 } 133 }
131 } 134 }
@@ -162,7 +165,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
162 }; 165 };
163 let substs = Substs::build_for_def(self.db, item) 166 let substs = Substs::build_for_def(self.db, item)
164 .use_parent_substs(&trait_ref.substs) 167 .use_parent_substs(&trait_ref.substs)
165 .fill_with_unknown() 168 .fill_with_params()
166 .build(); 169 .build();
167 170
168 self.write_assoc_resolution(id, item); 171 self.write_assoc_resolution(id, item);
@@ -172,44 +175,51 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
172 fn resolve_ty_assoc_item( 175 fn resolve_ty_assoc_item(
173 &mut self, 176 &mut self,
174 ty: Ty, 177 ty: Ty,
175 segment: &PathSegment, 178 name: &Name,
176 id: ExprOrPatId, 179 id: ExprOrPatId,
177 ) -> Option<(ValueNs, Option<Substs>)> { 180 ) -> Option<(ValueNs, Option<Substs>)> {
178 if let Ty::Unknown = ty { 181 if let Ty::Unknown = ty {
179 return None; 182 return None;
180 } 183 }
181 184
182 let krate = self.resolver.krate()?; 185 let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone());
183 186
184 // Find impl 187 method_resolution::iterate_method_candidates(
185 // FIXME: consider trait candidates 188 &canonical_ty.value,
186 let item = ty.clone().iterate_impl_items(self.db, krate, |item| match item { 189 self.db,
187 AssocItem::Function(func) => { 190 &self.resolver.clone(),
188 if segment.name == func.name(self.db) { 191 Some(name),
189 Some(AssocItem::Function(func)) 192 method_resolution::LookupMode::Path,
190 } else { 193 move |_ty, item| {
191 None 194 let def = match item {
192 } 195 AssocItem::Function(f) => ValueNs::Function(f),
193 } 196 AssocItem::Const(c) => ValueNs::Const(c),
194 197 AssocItem::TypeAlias(_) => unreachable!(),
195 AssocItem::Const(konst) => { 198 };
196 if konst.name(self.db).map_or(false, |n| n == segment.name) { 199 let substs = match item.container(self.db) {
197 Some(AssocItem::Const(konst)) 200 Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()),
198 } else { 201 Container::Trait(t) => {
199 None 202 // we're picking this method
200 } 203 let trait_substs = Substs::build_for_def(self.db, t)
201 } 204 .push(ty.clone())
202 AssocItem::TypeAlias(_) => None, 205 .fill(std::iter::repeat_with(|| self.new_type_var()))
203 })?; 206 .build();
204 let def = match item { 207 let substs = Substs::build_for_def(self.db, item)
205 AssocItem::Function(f) => ValueNs::Function(f), 208 .use_parent_substs(&trait_substs)
206 AssocItem::Const(c) => ValueNs::Const(c), 209 .fill_with_params()
207 AssocItem::TypeAlias(_) => unreachable!(), 210 .build();
208 }; 211 self.obligations.push(super::Obligation::Trait(TraitRef {
209 let substs = self.find_self_types(&def, ty); 212 trait_: t,
213 substs: trait_substs,
214 }));
215 Some(substs)
216 }
217 };
210 218
211 self.write_assoc_resolution(id, item); 219 self.write_assoc_resolution(id, item);
212 Some((def, substs)) 220 Some((def, substs))
221 },
222 )
213 } 223 }
214 224
215 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { 225 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index eb69344f6..8c3d32d09 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -166,37 +166,78 @@ pub(crate) fn lookup_method(
166 name: &Name, 166 name: &Name,
167 resolver: &Resolver, 167 resolver: &Resolver,
168) -> Option<(Ty, Function)> { 168) -> Option<(Ty, Function)> {
169 iterate_method_candidates(ty, db, resolver, Some(name), |ty, f| Some((ty.clone(), f))) 169 iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f
170 {
171 AssocItem::Function(f) => Some((ty.clone(), f)),
172 _ => None,
173 })
174}
175
176/// Whether we're looking up a dotted method call (like `v.len()`) or a path
177/// (like `Vec::new`).
178#[derive(Copy, Clone, Debug, PartialEq, Eq)]
179pub enum LookupMode {
180 /// Looking up a method call like `v.len()`: We only consider candidates
181 /// that have a `self` parameter, and do autoderef.
182 MethodCall,
183 /// Looking up a path like `Vec::new` or `Vec::default`: We consider all
184 /// candidates including associated constants, but don't do autoderef.
185 Path,
170} 186}
171 187
172// This would be nicer if it just returned an iterator, but that runs into 188// This would be nicer if it just returned an iterator, but that runs into
173// lifetime problems, because we need to borrow temp `CrateImplBlocks`. 189// lifetime problems, because we need to borrow temp `CrateImplBlocks`.
190// FIXME add a context type here?
174pub(crate) fn iterate_method_candidates<T>( 191pub(crate) fn iterate_method_candidates<T>(
175 ty: &Canonical<Ty>, 192 ty: &Canonical<Ty>,
176 db: &impl HirDatabase, 193 db: &impl HirDatabase,
177 resolver: &Resolver, 194 resolver: &Resolver,
178 name: Option<&Name>, 195 name: Option<&Name>,
179 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 196 mode: LookupMode,
197 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
180) -> Option<T> { 198) -> Option<T> {
181 // For method calls, rust first does any number of autoderef, and then one 199 let krate = resolver.krate()?;
182 // autoref (i.e. when the method takes &self or &mut self). We just ignore 200 match mode {
183 // the autoref currently -- when we find a method matching the given name, 201 LookupMode::MethodCall => {
184 // we assume it fits. 202 // For method calls, rust first does any number of autoderef, and then one
203 // autoref (i.e. when the method takes &self or &mut self). We just ignore
204 // the autoref currently -- when we find a method matching the given name,
205 // we assume it fits.
185 206
186 // Also note that when we've got a receiver like &S, even if the method we 207 // Also note that when we've got a receiver like &S, even if the method we
187 // find in the end takes &self, we still do the autoderef step (just as 208 // find in the end takes &self, we still do the autoderef step (just as
188 // rustc does an autoderef and then autoref again). 209 // rustc does an autoderef and then autoref again).
189 210
190 let krate = resolver.krate()?; 211 for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) {
191 for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { 212 if let Some(result) =
192 if let Some(result) = iterate_inherent_methods(&derefed_ty, db, name, krate, &mut callback) 213 iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback)
193 { 214 {
194 return Some(result); 215 return Some(result);
216 }
217 if let Some(result) = iterate_trait_method_candidates(
218 &derefed_ty,
219 db,
220 resolver,
221 name,
222 mode,
223 &mut callback,
224 ) {
225 return Some(result);
226 }
227 }
195 } 228 }
196 if let Some(result) = 229 LookupMode::Path => {
197 iterate_trait_method_candidates(&derefed_ty, db, resolver, name, &mut callback) 230 // No autoderef for path lookups
198 { 231 if let Some(result) =
199 return Some(result); 232 iterate_inherent_methods(&ty, db, name, mode, krate, &mut callback)
233 {
234 return Some(result);
235 }
236 if let Some(result) =
237 iterate_trait_method_candidates(&ty, db, resolver, name, mode, &mut callback)
238 {
239 return Some(result);
240 }
200 } 241 }
201 } 242 }
202 None 243 None
@@ -207,7 +248,8 @@ fn iterate_trait_method_candidates<T>(
207 db: &impl HirDatabase, 248 db: &impl HirDatabase,
208 resolver: &Resolver, 249 resolver: &Resolver,
209 name: Option<&Name>, 250 name: Option<&Name>,
210 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 251 mode: LookupMode,
252 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
211) -> Option<T> { 253) -> Option<T> {
212 let krate = resolver.krate()?; 254 let krate = resolver.krate()?;
213 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) 255 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
@@ -231,22 +273,20 @@ fn iterate_trait_method_candidates<T>(
231 // trait, but if we find out it doesn't, we'll skip the rest of the 273 // trait, but if we find out it doesn't, we'll skip the rest of the
232 // iteration 274 // iteration
233 let mut known_implemented = inherently_implemented; 275 let mut known_implemented = inherently_implemented;
234 for item in data.items() { 276 for &item in data.items() {
235 if let AssocItem::Function(m) = *item { 277 if !is_valid_candidate(db, name, mode, item) {
236 let data = m.data(db); 278 continue;
237 if name.map_or(true, |name| data.name() == name) && data.has_self_param() { 279 }
238 if !known_implemented { 280 if !known_implemented {
239 let goal = generic_implements_goal(db, env.clone(), t, ty.clone()); 281 let goal = generic_implements_goal(db, env.clone(), t, ty.clone());
240 if db.trait_solve(krate, goal).is_none() { 282 if db.trait_solve(krate, goal).is_none() {
241 continue 'traits; 283 continue 'traits;
242 }
243 }
244 known_implemented = true;
245 if let Some(result) = callback(&ty.value, m) {
246 return Some(result);
247 }
248 } 284 }
249 } 285 }
286 known_implemented = true;
287 if let Some(result) = callback(&ty.value, item) {
288 return Some(result);
289 }
250 } 290 }
251 } 291 }
252 None 292 None
@@ -256,21 +296,20 @@ fn iterate_inherent_methods<T>(
256 ty: &Canonical<Ty>, 296 ty: &Canonical<Ty>,
257 db: &impl HirDatabase, 297 db: &impl HirDatabase,
258 name: Option<&Name>, 298 name: Option<&Name>,
299 mode: LookupMode,
259 krate: Crate, 300 krate: Crate,
260 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 301 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
261) -> Option<T> { 302) -> Option<T> {
262 for krate in def_crates(db, krate, &ty.value)? { 303 for krate in def_crates(db, krate, &ty.value)? {
263 let impls = db.impls_in_crate(krate); 304 let impls = db.impls_in_crate(krate);
264 305
265 for impl_block in impls.lookup_impl_blocks(&ty.value) { 306 for impl_block in impls.lookup_impl_blocks(&ty.value) {
266 for item in impl_block.items(db) { 307 for item in impl_block.items(db) {
267 if let AssocItem::Function(f) = item { 308 if !is_valid_candidate(db, name, mode, item) {
268 let data = f.data(db); 309 continue;
269 if name.map_or(true, |name| data.name() == name) && data.has_self_param() { 310 }
270 if let Some(result) = callback(&ty.value, f) { 311 if let Some(result) = callback(&ty.value, item) {
271 return Some(result); 312 return Some(result);
272 }
273 }
274 } 313 }
275 } 314 }
276 } 315 }
@@ -278,6 +317,26 @@ fn iterate_inherent_methods<T>(
278 None 317 None
279} 318}
280 319
320fn is_valid_candidate(
321 db: &impl HirDatabase,
322 name: Option<&Name>,
323 mode: LookupMode,
324 item: AssocItem,
325) -> bool {
326 match item {
327 AssocItem::Function(m) => {
328 let data = m.data(db);
329 name.map_or(true, |name| data.name() == name)
330 && (data.has_self_param() || mode == LookupMode::Path)
331 }
332 AssocItem::Const(c) => {
333 name.map_or(true, |name| Some(name) == c.name(db).as_ref())
334 && (mode == LookupMode::Path)
335 }
336 _ => false,
337 }
338}
339
281pub(crate) fn implements_trait( 340pub(crate) fn implements_trait(
282 ty: &Canonical<Ty>, 341 ty: &Canonical<Ty>,
283 db: &impl HirDatabase, 342 db: &impl HirDatabase,
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index c12326643..bfef48b16 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1841,8 +1841,8 @@ fn test() {
1841 [243; 254) 'Struct::FOO': u32 1841 [243; 254) 'Struct::FOO': u32
1842 [264; 265) 'y': u32 1842 [264; 265) 'y': u32
1843 [268; 277) 'Enum::BAR': u32 1843 [268; 277) 'Enum::BAR': u32
1844 [287; 288) 'z': {unknown} 1844 [287; 288) 'z': u32
1845 [291; 304) 'TraitTest::ID': {unknown} 1845 [291; 304) 'TraitTest::ID': u32
1846 "### 1846 "###
1847 ); 1847 );
1848} 1848}
@@ -2782,9 +2782,9 @@ fn test() {
2782 [97; 99) 's1': S 2782 [97; 99) 's1': S
2783 [105; 121) 'Defaul...efault': fn default<S>() -> Self 2783 [105; 121) 'Defaul...efault': fn default<S>() -> Self
2784 [105; 123) 'Defaul...ault()': S 2784 [105; 123) 'Defaul...ault()': S
2785 [133; 135) 's2': {unknown} 2785 [133; 135) 's2': S
2786 [138; 148) 'S::default': {unknown} 2786 [138; 148) 'S::default': fn default<S>() -> Self
2787 [138; 150) 'S::default()': {unknown} 2787 [138; 150) 'S::default()': S
2788 [160; 162) 's3': S 2788 [160; 162) 's3': S
2789 [165; 188) '<S as ...efault': fn default<S>() -> Self 2789 [165; 188) '<S as ...efault': fn default<S>() -> Self
2790 [165; 190) '<S as ...ault()': S 2790 [165; 190) '<S as ...ault()': S
@@ -2793,6 +2793,153 @@ fn test() {
2793} 2793}
2794 2794
2795#[test] 2795#[test]
2796fn infer_trait_assoc_method_generics_1() {
2797 assert_snapshot!(
2798 infer(r#"
2799trait Trait<T> {
2800 fn make() -> T;
2801}
2802struct S;
2803impl Trait<u32> for S {}
2804struct G<T>;
2805impl<T> Trait<T> for G<T> {}
2806fn test() {
2807 let a = S::make();
2808 let b = G::<u64>::make();
2809 let c: f64 = G::make();
2810}
2811"#),
2812 @r###"
2813 [127; 211) '{ ...e(); }': ()
2814 [137; 138) 'a': u32
2815 [141; 148) 'S::make': fn make<S, u32>() -> T
2816 [141; 150) 'S::make()': u32
2817 [160; 161) 'b': u64
2818 [164; 178) 'G::<u64>::make': fn make<G<u64>, u64>() -> T
2819 [164; 180) 'G::<u6...make()': u64
2820 [190; 191) 'c': f64
2821 [199; 206) 'G::make': fn make<G<f64>, f64>() -> T
2822 [199; 208) 'G::make()': f64
2823 "###
2824 );
2825}
2826
2827#[test]
2828fn infer_trait_assoc_method_generics_2() {
2829 assert_snapshot!(
2830 infer(r#"
2831trait Trait<T> {
2832 fn make<U>() -> (T, U);
2833}
2834struct S;
2835impl Trait<u32> for S {}
2836struct G<T>;
2837impl<T> Trait<T> for G<T> {}
2838fn test() {
2839 let a = S::make::<i64>();
2840 let b: (_, i64) = S::make();
2841 let c = G::<u32>::make::<i64>();
2842 let d: (u32, _) = G::make::<i64>();
2843 let e: (u32, i64) = G::make();
2844}
2845"#),
2846 @r###"
2847 [135; 313) '{ ...e(); }': ()
2848 [145; 146) 'a': (u32, i64)
2849 [149; 163) 'S::make::<i64>': fn make<S, u32, i64>() -> (T, U)
2850 [149; 165) 'S::mak...i64>()': (u32, i64)
2851 [175; 176) 'b': (u32, i64)
2852 [189; 196) 'S::make': fn make<S, u32, i64>() -> (T, U)
2853 [189; 198) 'S::make()': (u32, i64)
2854 [208; 209) 'c': (u32, i64)
2855 [212; 233) 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
2856 [212; 235) 'G::<u3...i64>()': (u32, i64)
2857 [245; 246) 'd': (u32, i64)
2858 [259; 273) 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
2859 [259; 275) 'G::mak...i64>()': (u32, i64)
2860 [285; 286) 'e': (u32, i64)
2861 [301; 308) 'G::make': fn make<G<u32>, u32, i64>() -> (T, U)
2862 [301; 310) 'G::make()': (u32, i64)
2863 "###
2864 );
2865}
2866
2867#[test]
2868fn infer_trait_assoc_method_generics_3() {
2869 assert_snapshot!(
2870 infer(r#"
2871trait Trait<T> {
2872 fn make() -> (Self, T);
2873}
2874struct S<T>;
2875impl Trait<i64> for S<i32> {}
2876fn test() {
2877 let a = S::make();
2878}
2879"#),
2880 @r###"
2881 [101; 127) '{ ...e(); }': ()
2882 [111; 112) 'a': (S<i32>, i64)
2883 [115; 122) 'S::make': fn make<S<i32>, i64>() -> (Self, T)
2884 [115; 124) 'S::make()': (S<i32>, i64)
2885 "###
2886 );
2887}
2888
2889#[test]
2890fn infer_trait_assoc_method_generics_4() {
2891 assert_snapshot!(
2892 infer(r#"
2893trait Trait<T> {
2894 fn make() -> (Self, T);
2895}
2896struct S<T>;
2897impl Trait<i64> for S<u64> {}
2898impl Trait<i32> for S<u32> {}
2899fn test() {
2900 let a: (S<u64>, _) = S::make();
2901 let b: (_, i32) = S::make();
2902}
2903"#),
2904 @r###"
2905 [131; 203) '{ ...e(); }': ()
2906 [141; 142) 'a': (S<u64>, i64)
2907 [158; 165) 'S::make': fn make<S<u64>, i64>() -> (Self, T)
2908 [158; 167) 'S::make()': (S<u64>, i64)
2909 [177; 178) 'b': (S<u32>, i32)
2910 [191; 198) 'S::make': fn make<S<u32>, i32>() -> (Self, T)
2911 [191; 200) 'S::make()': (S<u32>, i32)
2912 "###
2913 );
2914}
2915
2916#[test]
2917fn infer_trait_assoc_method_generics_5() {
2918 assert_snapshot!(
2919 infer(r#"
2920trait Trait<T> {
2921 fn make<U>() -> (Self, T, U);
2922}
2923struct S<T>;
2924impl Trait<i64> for S<u64> {}
2925fn test() {
2926 let a = <S as Trait<i64>>::make::<u8>();
2927 let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>();
2928}
2929"#),
2930 @r###"
2931 [107; 211) '{ ...>(); }': ()
2932 [117; 118) 'a': (S<u64>, i64, u8)
2933 [121; 150) '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
2934 [121; 152) '<S as ...<u8>()': (S<u64>, i64, u8)
2935 [162; 163) 'b': (S<u64>, i64, u8)
2936 [182; 206) 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
2937 [182; 208) 'Trait:...<u8>()': (S<u64>, i64, u8)
2938 "###
2939 );
2940}
2941
2942#[test]
2796fn infer_from_bound_1() { 2943fn infer_from_bound_1() {
2797 assert_snapshot!( 2944 assert_snapshot!(
2798 infer(r#" 2945 infer(r#"
@@ -3303,6 +3450,22 @@ fn test() { S.foo()<|>; }
3303 assert_eq!(t, "u128"); 3450 assert_eq!(t, "u128");
3304} 3451}
3305 3452
3453#[ignore]
3454#[test]
3455fn method_resolution_by_value_before_autoref() {
3456 let t = type_at(
3457 r#"
3458//- /main.rs
3459trait Clone { fn clone(&self) -> Self; }
3460struct S;
3461impl Clone for S {}
3462impl Clone for &S {}
3463fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; }
3464"#,
3465 );
3466 assert_eq!(t, "(S, S, &S)");
3467}
3468
3306#[test] 3469#[test]
3307fn method_resolution_trait_before_autoderef() { 3470fn method_resolution_trait_before_autoderef() {
3308 let t = type_at( 3471 let t = type_at(
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index a58fdc036..9ac9768af 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -50,23 +50,46 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
50 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), 50 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
51 _ => unreachable!(), 51 _ => unreachable!(),
52 }; 52 };
53 ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| {
54 match item {
55 hir::AssocItem::Function(func) => {
56 let data = func.data(ctx.db);
57 if !data.has_self_param() {
58 acc.add_function(ctx, func);
59 }
60 }
61 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
62 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
63 }
64 None::<()>
65 });
66 // Iterate assoc types separately
67 // FIXME: complete T::AssocType
53 let krate = ctx.module.map(|m| m.krate()); 68 let krate = ctx.module.map(|m| m.krate());
54 if let Some(krate) = krate { 69 if let Some(krate) = krate {
55 ty.iterate_impl_items(ctx.db, krate, |item| { 70 ty.iterate_impl_items(ctx.db, krate, |item| {
56 match item { 71 match item {
57 hir::AssocItem::Function(func) => { 72 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
58 let data = func.data(ctx.db);
59 if !data.has_self_param() {
60 acc.add_function(ctx, func);
61 }
62 }
63 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
64 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), 73 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
65 } 74 }
66 None::<()> 75 None::<()>
67 }); 76 });
68 } 77 }
69 } 78 }
79 hir::ModuleDef::Trait(t) => {
80 for item in t.items(ctx.db) {
81 match item {
82 hir::AssocItem::Function(func) => {
83 let data = func.data(ctx.db);
84 if !data.has_self_param() {
85 acc.add_function(ctx, func);
86 }
87 }
88 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
89 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
90 }
91 }
92 }
70 _ => {} 93 _ => {}
71 }; 94 };
72} 95}
@@ -559,6 +582,111 @@ mod tests {
559 } 582 }
560 583
561 #[test] 584 #[test]
585 fn completes_trait_associated_method_1() {
586 assert_debug_snapshot!(
587 do_reference_completion(
588 "
589 //- /lib.rs
590 trait Trait {
591 /// A trait method
592 fn m();
593 }
594
595 fn foo() { let _ = Trait::<|> }
596 "
597 ),
598 @r###"
599 [
600 CompletionItem {
601 label: "m()",
602 source_range: [73; 73),
603 delete: [73; 73),
604 insert: "m()$0",
605 kind: Function,
606 lookup: "m",
607 detail: "fn m()",
608 documentation: Documentation(
609 "A trait method",
610 ),
611 },
612 ]
613 "###
614 );
615 }
616
617 #[test]
618 fn completes_trait_associated_method_2() {
619 assert_debug_snapshot!(
620 do_reference_completion(
621 "
622 //- /lib.rs
623 trait Trait {
624 /// A trait method
625 fn m();
626 }
627
628 struct S;
629 impl Trait for S {}
630
631 fn foo() { let _ = S::<|> }
632 "
633 ),
634 @r###"
635 [
636 CompletionItem {
637 label: "m()",
638 source_range: [99; 99),
639 delete: [99; 99),
640 insert: "m()$0",
641 kind: Function,
642 lookup: "m",
643 detail: "fn m()",
644 documentation: Documentation(
645 "A trait method",
646 ),
647 },
648 ]
649 "###
650 );
651 }
652
653 #[test]
654 fn completes_trait_associated_method_3() {
655 assert_debug_snapshot!(
656 do_reference_completion(
657 "
658 //- /lib.rs
659 trait Trait {
660 /// A trait method
661 fn m();
662 }
663
664 struct S;
665 impl Trait for S {}
666
667 fn foo() { let _ = <S as Trait>::<|> }
668 "
669 ),
670 @r###"
671 [
672 CompletionItem {
673 label: "m()",
674 source_range: [110; 110),
675 delete: [110; 110),
676 insert: "m()$0",
677 kind: Function,
678 lookup: "m",
679 detail: "fn m()",
680 documentation: Documentation(
681 "A trait method",
682 ),
683 },
684 ]
685 "###
686 );
687 }
688
689 #[test]
562 fn completes_type_alias() { 690 fn completes_type_alias() {
563 assert_debug_snapshot!( 691 assert_debug_snapshot!(
564 do_reference_completion( 692 do_reference_completion(
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 1f3fa6c57..c1ce54bea 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -316,6 +316,25 @@ mod tests {
316 } 316 }
317 317
318 #[test] 318 #[test]
319 fn goto_definition_works_for_macros_in_use_tree() {
320 check_goto(
321 "
322 //- /lib.rs
323 use foo::foo<|>;
324
325 //- /foo/lib.rs
326 #[macro_export]
327 macro_rules! foo {
328 () => {
329 {}
330 };
331 }
332 ",
333 "foo MACRO_CALL FileId(2) [0; 66) [29; 32)",
334 );
335 }
336
337 #[test]
319 fn goto_definition_works_for_methods() { 338 fn goto_definition_works_for_methods() {
320 covers!(goto_definition_works_for_methods); 339 covers!(goto_definition_works_for_methods);
321 check_goto( 340 check_goto(
@@ -371,6 +390,61 @@ mod tests {
371 "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", 390 "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)",
372 ); 391 );
373 } 392 }
393
394 #[test]
395 fn goto_definition_works_for_ufcs_inherent_methods() {
396 check_goto(
397 "
398 //- /lib.rs
399 struct Foo;
400 impl Foo {
401 fn frobnicate() { }
402 }
403
404 fn bar(foo: &Foo) {
405 Foo::frobnicate<|>();
406 }
407 ",
408 "frobnicate FN_DEF FileId(1) [27; 47) [30; 40)",
409 );
410 }
411
412 #[test]
413 fn goto_definition_works_for_ufcs_trait_methods_through_traits() {
414 check_goto(
415 "
416 //- /lib.rs
417 trait Foo {
418 fn frobnicate();
419 }
420
421 fn bar() {
422 Foo::frobnicate<|>();
423 }
424 ",
425 "frobnicate FN_DEF FileId(1) [16; 32) [19; 29)",
426 );
427 }
428
429 #[test]
430 fn goto_definition_works_for_ufcs_trait_methods_through_self() {
431 check_goto(
432 "
433 //- /lib.rs
434 struct Foo;
435 trait Trait {
436 fn frobnicate();
437 }
438 impl Trait for Foo {}
439
440 fn bar() {
441 Foo::frobnicate<|>();
442 }
443 ",
444 "frobnicate FN_DEF FileId(1) [30; 46) [33; 43)",
445 );
446 }
447
374 #[test] 448 #[test]
375 fn goto_definition_on_self() { 449 fn goto_definition_on_self() {
376 check_goto( 450 check_goto(
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index a12da5be2..1ec9881b9 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -113,6 +113,20 @@ fn test_doc_comment_of_items() {
113} 113}
114 114
115#[test] 115#[test]
116fn test_doc_comment_of_statics() {
117 let file = SourceFile::parse(
118 r#"
119 /// Number of levels
120 static LEVELS: i32 = 0;
121 "#,
122 )
123 .ok()
124 .unwrap();
125 let st = file.syntax().descendants().find_map(StaticDef::cast).unwrap();
126 assert_eq!("Number of levels", st.doc_comment_text().unwrap());
127}
128
129#[test]
116fn test_doc_comment_preserves_indents() { 130fn test_doc_comment_preserves_indents() {
117 let file = SourceFile::parse( 131 let file = SourceFile::parse(
118 r#" 132 r#"
diff --git a/crates/ra_syntax/src/parsing/text_tree_sink.rs b/crates/ra_syntax/src/parsing/text_tree_sink.rs
index 142164316..c36756d6c 100644
--- a/crates/ra_syntax/src/parsing/text_tree_sink.rs
+++ b/crates/ra_syntax/src/parsing/text_tree_sink.rs
@@ -147,7 +147,7 @@ fn n_attached_trivias<'a>(
147) -> usize { 147) -> usize {
148 match kind { 148 match kind {
149 MACRO_CALL | CONST_DEF | TYPE_ALIAS_DEF | STRUCT_DEF | ENUM_DEF | ENUM_VARIANT | FN_DEF 149 MACRO_CALL | CONST_DEF | TYPE_ALIAS_DEF | STRUCT_DEF | ENUM_DEF | ENUM_VARIANT | FN_DEF
150 | TRAIT_DEF | MODULE | RECORD_FIELD_DEF => { 150 | TRAIT_DEF | MODULE | RECORD_FIELD_DEF | STATIC_DEF => {
151 let mut res = 0; 151 let mut res = 0;
152 for (i, (kind, text)) in trivias.enumerate() { 152 for (i, (kind, text)) in trivias.enumerate() {
153 match kind { 153 match kind {
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs
index cc69463a9..bae4c4650 100644
--- a/xtask/src/lib.rs
+++ b/xtask/src/lib.rs
@@ -3,6 +3,7 @@
3pub mod codegen; 3pub mod codegen;
4 4
5use std::{ 5use std::{
6 env,
6 error::Error, 7 error::Error,
7 fs, 8 fs,
8 io::{Error as IoError, ErrorKind}, 9 io::{Error as IoError, ErrorKind},
@@ -17,7 +18,13 @@ pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
17const TOOLCHAIN: &str = "stable"; 18const TOOLCHAIN: &str = "stable";
18 19
19pub fn project_root() -> PathBuf { 20pub fn project_root() -> PathBuf {
20 Path::new(&env!("CARGO_MANIFEST_DIR")).ancestors().nth(1).unwrap().to_path_buf() 21 Path::new(
22 &env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
23 )
24 .ancestors()
25 .nth(1)
26 .unwrap()
27 .to_path_buf()
21} 28}
22 29
23pub struct Cmd<'a> { 30pub struct Cmd<'a> {