aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model_api.rs36
-rw-r--r--crates/ra_hir/src/code_model_impl/function.rs13
-rw-r--r--crates/ra_hir/src/expr.rs9
-rw-r--r--crates/ra_hir/src/generics.rs42
-rw-r--r--crates/ra_hir/src/ids.rs3
-rw-r--r--crates/ra_hir/src/impl_block.rs20
-rw-r--r--crates/ra_hir/src/path.rs2
-rw-r--r--crates/ra_hir/src/ty.rs65
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs12
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap54
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap39
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap16
-rw-r--r--crates/ra_hir/src/ty/tests.rs52
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs2
-rw-r--r--crates/ra_syntax/src/ast/generated.rs5
-rw-r--r--crates/ra_syntax/src/grammar.ron4
16 files changed, 290 insertions, 84 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 99f004905..26ebc445b 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -463,7 +463,7 @@ impl Function {
463 self.id.source(db) 463 self.id.source(db)
464 } 464 }
465 465
466 pub fn module(&self, db: &impl HirDatabase) -> Module { 466 pub fn module(&self, db: &impl PersistentHirDatabase) -> Module {
467 self.id.module(db) 467 self.id.module(db)
468 } 468 }
469 469
@@ -497,6 +497,12 @@ impl Function {
497 db.generic_params((*self).into()) 497 db.generic_params((*self).into())
498 } 498 }
499 499
500 /// The containing impl block, if this is a method.
501 pub fn impl_block(&self, db: &impl PersistentHirDatabase) -> Option<ImplBlock> {
502 let module_impls = db.impls_in_module(self.module(db));
503 ImplBlock::containing(module_impls, (*self).into())
504 }
505
500 // TODO: move to a more general type for 'body-having' items 506 // TODO: move to a more general type for 'body-having' items
501 /// Builds a resolver for code inside this item. 507 /// Builds a resolver for code inside this item.
502 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 508 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
@@ -527,6 +533,16 @@ impl Const {
527 pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) { 533 pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) {
528 self.id.source(db) 534 self.id.source(db)
529 } 535 }
536
537 pub fn module(&self, db: &impl PersistentHirDatabase) -> Module {
538 self.id.module(db)
539 }
540
541 /// The containing impl block, if this is a method.
542 pub fn impl_block(&self, db: &impl PersistentHirDatabase) -> Option<ImplBlock> {
543 let module_impls = db.impls_in_module(self.module(db));
544 ImplBlock::containing(module_impls, (*self).into())
545 }
530} 546}
531 547
532impl Docs for Const { 548impl Docs for Const {
@@ -544,6 +560,10 @@ impl Static {
544 pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) { 560 pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) {
545 self.id.source(db) 561 self.id.source(db)
546 } 562 }
563
564 pub fn module(&self, db: &impl PersistentHirDatabase) -> Module {
565 self.id.module(db)
566 }
547} 567}
548 568
549impl Docs for Static { 569impl Docs for Static {
@@ -562,6 +582,10 @@ impl Trait {
562 self.id.source(db) 582 self.id.source(db)
563 } 583 }
564 584
585 pub fn module(&self, db: &impl PersistentHirDatabase) -> Module {
586 self.id.module(db)
587 }
588
565 pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> { 589 pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> {
566 db.generic_params((*self).into()) 590 db.generic_params((*self).into())
567 } 591 }
@@ -586,6 +610,16 @@ impl Type {
586 pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> { 610 pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> {
587 db.generic_params((*self).into()) 611 db.generic_params((*self).into())
588 } 612 }
613
614 pub fn module(&self, db: &impl PersistentHirDatabase) -> Module {
615 self.id.module(db)
616 }
617
618 /// The containing impl block, if this is a method.
619 pub fn impl_block(&self, db: &impl PersistentHirDatabase) -> Option<ImplBlock> {
620 let module_impls = db.impls_in_module(self.module(db));
621 ImplBlock::containing(module_impls, (*self).into())
622 }
589} 623}
590 624
591impl Docs for Type { 625impl Docs for Type {
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs
index b9438fdb7..c401528c6 100644
--- a/crates/ra_hir/src/code_model_impl/function.rs
+++ b/crates/ra_hir/src/code_model_impl/function.rs
@@ -3,22 +3,11 @@ use std::sync::Arc;
3use ra_syntax::ast::{self, NameOwner}; 3use ra_syntax::ast::{self, NameOwner};
4 4
5use crate::{ 5use crate::{
6 HirDatabase, Name, AsName, Function, FnSignature, 6 Name, AsName, Function, FnSignature,
7 type_ref::{TypeRef, Mutability}, 7 type_ref::{TypeRef, Mutability},
8 PersistentHirDatabase, 8 PersistentHirDatabase,
9 impl_block::ImplBlock,
10}; 9};
11 10
12impl Function {
13 // TODO impl_block should probably also be part of the code model API?
14
15 /// The containing impl block, if this is a method.
16 pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> {
17 let module_impls = db.impls_in_module(self.module(db));
18 ImplBlock::containing(module_impls, (*self).into())
19 }
20}
21
22impl FnSignature { 11impl FnSignature {
23 pub(crate) fn fn_signature_query( 12 pub(crate) fn fn_signature_query(
24 db: &impl PersistentHirDatabase, 13 db: &impl PersistentHirDatabase,
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 4e73590d0..e9db8282f 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -14,7 +14,7 @@ use crate::{
14 name::AsName, 14 name::AsName,
15 type_ref::{Mutability, TypeRef}, 15 type_ref::{Mutability, TypeRef},
16}; 16};
17use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; 17use crate::{ path::GenericArgs, ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}};
18 18
19pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; 19pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
20 20
@@ -193,6 +193,7 @@ pub enum Expr {
193 receiver: ExprId, 193 receiver: ExprId,
194 method_name: Name, 194 method_name: Name,
195 args: Vec<ExprId>, 195 args: Vec<ExprId>,
196 generic_args: Option<GenericArgs>,
196 }, 197 },
197 Match { 198 Match {
198 expr: ExprId, 199 expr: ExprId,
@@ -597,7 +598,11 @@ impl ExprCollector {
597 Vec::new() 598 Vec::new()
598 }; 599 };
599 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 600 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
600 self.alloc_expr(Expr::MethodCall { receiver, method_name, args }, syntax_ptr) 601 let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast);
602 self.alloc_expr(
603 Expr::MethodCall { receiver, method_name, args, generic_args },
604 syntax_ptr,
605 )
601 } 606 }
602 ast::ExprKind::MatchExpr(e) => { 607 ast::ExprKind::MatchExpr(e) => {
603 let expr = self.collect_expr_opt(e.expr()); 608 let expr = self.collect_expr_opt(e.expr());
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index c72360f44..fcc513353 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -7,7 +7,7 @@ use std::sync::Arc;
7 7
8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; 8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner};
9 9
10use crate::{db::PersistentHirDatabase, Name, AsName, Function, Struct, Enum, Trait, Type}; 10use crate::{db::PersistentHirDatabase, Name, AsName, Function, Struct, Enum, Trait, Type, ImplBlock};
11 11
12/// Data about a generic parameter (to a function, struct, impl, ...). 12/// Data about a generic parameter (to a function, struct, impl, ...).
13#[derive(Clone, PartialEq, Eq, Debug)] 13#[derive(Clone, PartialEq, Eq, Debug)]
@@ -20,6 +20,7 @@ pub struct GenericParam {
20/// Data about the generic parameters of a function, struct, impl, etc. 20/// Data about the generic parameters of a function, struct, impl, etc.
21#[derive(Clone, PartialEq, Eq, Debug, Default)] 21#[derive(Clone, PartialEq, Eq, Debug, Default)]
22pub struct GenericParams { 22pub struct GenericParams {
23 pub(crate) parent_params: Option<Arc<GenericParams>>,
23 pub(crate) params: Vec<GenericParam>, 24 pub(crate) params: Vec<GenericParam>,
24} 25}
25 26
@@ -30,8 +31,9 @@ pub enum GenericDef {
30 Enum(Enum), 31 Enum(Enum),
31 Trait(Trait), 32 Trait(Trait),
32 Type(Type), 33 Type(Type),
34 ImplBlock(ImplBlock),
33} 35}
34impl_froms!(GenericDef: Function, Struct, Enum, Trait, Type); 36impl_froms!(GenericDef: Function, Struct, Enum, Trait, Type, ImplBlock);
35 37
36impl GenericParams { 38impl GenericParams {
37 pub(crate) fn generic_params_query( 39 pub(crate) fn generic_params_query(
@@ -39,27 +41,36 @@ impl GenericParams {
39 def: GenericDef, 41 def: GenericDef,
40 ) -> Arc<GenericParams> { 42 ) -> Arc<GenericParams> {
41 let mut generics = GenericParams::default(); 43 let mut generics = GenericParams::default();
44 let parent = match def {
45 GenericDef::Function(it) => it.impl_block(db),
46 GenericDef::Type(it) => it.impl_block(db),
47 GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None,
48 GenericDef::ImplBlock(_) => None,
49 };
50 generics.parent_params = parent.map(|p| p.generic_params(db));
51 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
42 match def { 52 match def {
43 GenericDef::Function(it) => generics.fill(&*it.source(db).1), 53 GenericDef::Function(it) => generics.fill(&*it.source(db).1, start),
44 GenericDef::Struct(it) => generics.fill(&*it.source(db).1), 54 GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start),
45 GenericDef::Enum(it) => generics.fill(&*it.source(db).1), 55 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start),
46 GenericDef::Trait(it) => generics.fill(&*it.source(db).1), 56 GenericDef::Trait(it) => generics.fill(&*it.source(db).1, start),
47 GenericDef::Type(it) => generics.fill(&*it.source(db).1), 57 GenericDef::Type(it) => generics.fill(&*it.source(db).1, start),
58 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start),
48 } 59 }
49 60
50 Arc::new(generics) 61 Arc::new(generics)
51 } 62 }
52 63
53 fn fill(&mut self, node: &impl TypeParamsOwner) { 64 fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) {
54 if let Some(params) = node.type_param_list() { 65 if let Some(params) = node.type_param_list() {
55 self.fill_params(params) 66 self.fill_params(params, start)
56 } 67 }
57 } 68 }
58 69
59 fn fill_params(&mut self, params: &ast::TypeParamList) { 70 fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) {
60 for (idx, type_param) in params.type_params().enumerate() { 71 for (idx, type_param) in params.type_params().enumerate() {
61 let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing); 72 let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing);
62 let param = GenericParam { idx: idx as u32, name }; 73 let param = GenericParam { idx: idx as u32 + start, name };
63 self.params.push(param); 74 self.params.push(param);
64 } 75 }
65 } 76 }
@@ -67,4 +78,13 @@ impl GenericParams {
67 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { 78 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
68 self.params.iter().find(|p| &p.name == name) 79 self.params.iter().find(|p| &p.name == name)
69 } 80 }
81
82 pub fn count_parent_params(&self) -> usize {
83 self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0)
84 }
85
86 pub fn count_params_including_parent(&self) -> usize {
87 let parent_count = self.count_parent_params();
88 parent_count + self.params.len()
89 }
70} 90}
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 3e11dd6ad..6df037859 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -9,7 +9,6 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, SyntaxNodePtr, ast};
9use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; 9use ra_arena::{Arena, RawId, ArenaId, impl_arena_id};
10 10
11use crate::{ 11use crate::{
12 HirDatabase,
13 Module, 12 Module,
14 PersistentHirDatabase, 13 PersistentHirDatabase,
15}; 14};
@@ -215,7 +214,7 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
215 N::cast(&syntax).unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)).to_owned(); 214 N::cast(&syntax).unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)).to_owned();
216 (loc.raw.file_id, ast) 215 (loc.raw.file_id, ast)
217 } 216 }
218 fn module(self, db: &impl HirDatabase) -> Module { 217 fn module(self, db: &impl PersistentHirDatabase) -> Module {
219 let int = Self::interner(db.as_ref()); 218 let int = Self::interner(db.as_ref());
220 let loc = int.id2loc(self); 219 let loc = int.id2loc(self);
221 loc.module 220 loc.module
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 4d8bdf33a..7ecf8c368 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -13,7 +13,7 @@ use crate::{
13 type_ref::TypeRef, 13 type_ref::TypeRef,
14 ids::LocationCtx, 14 ids::LocationCtx,
15 resolve::Resolver, 15 resolve::Resolver,
16 ty::Ty, 16 ty::Ty, generics::GenericParams
17}; 17};
18 18
19use crate::code_model_api::{Module, ModuleSource}; 19use crate::code_model_api::{Module, ModuleSource};
@@ -38,7 +38,7 @@ impl ImplSourceMap {
38 } 38 }
39} 39}
40 40
41#[derive(Debug, Clone, Copy, PartialEq, Eq)] 41#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
42pub struct ImplBlock { 42pub struct ImplBlock {
43 module: Module, 43 module: Module,
44 impl_id: ImplId, 44 impl_id: ImplId,
@@ -58,7 +58,7 @@ impl ImplBlock {
58 } 58 }
59 59
60 /// Returns the syntax of the impl block 60 /// Returns the syntax of the impl block
61 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::ImplBlock>) { 61 pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::ImplBlock>) {
62 let source_map = db.impls_in_module_source_map(self.module); 62 let source_map = db.impls_in_module_source_map(self.module);
63 let (file_id, source) = self.module.definition_source(db); 63 let (file_id, source) = self.module.definition_source(db);
64 (file_id, source_map.get(&source, self.impl_id)) 64 (file_id, source_map.get(&source, self.impl_id))
@@ -72,11 +72,11 @@ impl ImplBlock {
72 self.module 72 self.module
73 } 73 }
74 74
75 pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option<TypeRef> { 75 pub fn target_trait_ref(&self, db: &impl PersistentHirDatabase) -> Option<TypeRef> {
76 db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned() 76 db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned()
77 } 77 }
78 78
79 pub fn target_type(&self, db: &impl HirDatabase) -> TypeRef { 79 pub fn target_type(&self, db: &impl PersistentHirDatabase) -> TypeRef {
80 db.impls_in_module(self.module).impls[self.impl_id].target_type().clone() 80 db.impls_in_module(self.module).impls[self.impl_id].target_type().clone()
81 } 81 }
82 82
@@ -96,13 +96,19 @@ impl ImplBlock {
96 None 96 None
97 } 97 }
98 98
99 pub fn items(&self, db: &impl HirDatabase) -> Vec<ImplItem> { 99 pub fn items(&self, db: &impl PersistentHirDatabase) -> Vec<ImplItem> {
100 db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() 100 db.impls_in_module(self.module).impls[self.impl_id].items().to_vec()
101 } 101 }
102 102
103 pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> {
104 db.generic_params((*self).into())
105 }
106
103 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 107 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
104 let r = self.module().resolver(db); 108 let r = self.module().resolver(db);
105 // TODO: add generics 109 // add generic params, if present
110 let p = self.generic_params(db);
111 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
106 let r = r.push_impl_block_scope(self.clone()); 112 let r = r.push_impl_block_scope(self.clone());
107 r 113 r
108 } 114 }
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index 8ed54607a..6ca373e34 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -129,7 +129,7 @@ impl Path {
129} 129}
130 130
131impl GenericArgs { 131impl GenericArgs {
132 fn from_ast(node: &ast::TypeArgList) -> Option<GenericArgs> { 132 pub(crate) fn from_ast(node: &ast::TypeArgList) -> Option<GenericArgs> {
133 let mut args = Vec::new(); 133 let mut args = Vec::new();
134 for type_arg in node.type_args() { 134 for type_arg in node.type_args() {
135 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); 135 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index f28a7e731..562ad1f49 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -165,6 +165,17 @@ impl Substs {
165 pub fn empty() -> Substs { 165 pub fn empty() -> Substs {
166 Substs(Arc::new([])) 166 Substs(Arc::new([]))
167 } 167 }
168
169 /// Replaces the end of the substitutions by other ones.
170 pub(crate) fn replace_tail(self, replace_by: Vec<Ty>) -> Substs {
171 // again missing Arc::make_mut_slice...
172 let len = replace_by.len().min(self.0.len());
173 let parent_len = self.0.len() - len;
174 let mut result = Vec::with_capacity(parent_len + len);
175 result.extend(self.0.iter().take(parent_len).cloned());
176 result.extend(replace_by);
177 Substs(result.into())
178 }
168} 179}
169 180
170/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). 181/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
@@ -421,7 +432,8 @@ impl Ty {
421 (var.parent_enum(db).generic_params(db), segment) 432 (var.parent_enum(db).generic_params(db), segment)
422 } 433 }
423 }; 434 };
424 // substs_from_path 435 let parent_param_count = def_generics.count_parent_params();
436 substs.extend((0..parent_param_count).map(|_| Ty::Unknown));
425 if let Some(generic_args) = &segment.args_and_bindings { 437 if let Some(generic_args) = &segment.args_and_bindings {
426 // if args are provided, it should be all of them, but we can't rely on that 438 // if args are provided, it should be all of them, but we can't rely on that
427 let param_count = def_generics.params.len(); 439 let param_count = def_generics.params.len();
@@ -436,9 +448,8 @@ impl Ty {
436 } 448 }
437 // add placeholders for args that were not provided 449 // add placeholders for args that were not provided
438 // TODO: handle defaults 450 // TODO: handle defaults
439 let supplied_params = 451 let supplied_params = substs.len();
440 segment.args_and_bindings.as_ref().map(|ga| ga.args.len()).unwrap_or(0); 452 for _ in supplied_params..def_generics.count_params_including_parent() {
441 for _ in supplied_params..def_generics.params.len() {
442 substs.push(Ty::Unknown); 453 substs.push(Ty::Unknown);
443 } 454 }
444 assert_eq!(substs.len(), def_generics.params.len()); 455 assert_eq!(substs.len(), def_generics.params.len());
@@ -666,7 +677,12 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
666} 677}
667 678
668fn make_substs(generics: &GenericParams) -> Substs { 679fn make_substs(generics: &GenericParams) -> Substs {
669 Substs(generics.params.iter().map(|_p| Ty::Unknown).collect::<Vec<_>>().into()) 680 Substs(
681 (0..generics.count_params_including_parent())
682 .map(|_p| Ty::Unknown)
683 .collect::<Vec<_>>()
684 .into(),
685 )
670} 686}
671 687
672fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 688fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
@@ -1362,15 +1378,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1362 } 1378 }
1363 ret_ty 1379 ret_ty
1364 } 1380 }
1365 Expr::MethodCall { receiver, args, method_name } => { 1381 Expr::MethodCall { receiver, args, method_name, generic_args } => {
1366 let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); 1382 let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
1367 let resolved = receiver_ty.clone().lookup_method(self.db, method_name); 1383 let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
1368 let method_ty = match resolved { 1384 let (derefed_receiver_ty, method_ty, def_generics) = match resolved {
1369 Some(func) => { 1385 Some((ty, func)) => {
1370 self.write_method_resolution(tgt_expr, func); 1386 self.write_method_resolution(tgt_expr, func);
1371 self.db.type_for_def(func.into()) 1387 (ty, self.db.type_for_def(func.into()), Some(func.generic_params(self.db)))
1388 }
1389 None => (Ty::Unknown, receiver_ty, None),
1390 };
1391 // handle provided type arguments
1392 let method_ty = if let Some(generic_args) = generic_args {
1393 // if args are provided, it should be all of them, but we can't rely on that
1394 let param_count = def_generics.map(|g| g.params.len()).unwrap_or(0);
1395 let mut new_substs = Vec::with_capacity(generic_args.args.len());
1396 for arg in generic_args.args.iter().take(param_count) {
1397 match arg {
1398 GenericArg::Type(type_ref) => {
1399 let ty = self.make_ty(type_ref);
1400 new_substs.push(ty);
1401 }
1402 }
1372 } 1403 }
1373 None => Ty::Unknown, 1404 let substs = method_ty.substs().unwrap_or_else(Substs::empty);
1405 let substs = substs.replace_tail(new_substs);
1406 method_ty.apply_substs(substs)
1407 } else {
1408 method_ty
1374 }; 1409 };
1375 let method_ty = self.insert_type_vars(method_ty); 1410 let method_ty = self.insert_type_vars(method_ty);
1376 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { 1411 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
@@ -1394,9 +1429,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1394 } 1429 }
1395 _ => (Ty::Unknown, Vec::new(), Ty::Unknown), 1430 _ => (Ty::Unknown, Vec::new(), Ty::Unknown),
1396 }; 1431 };
1397 // TODO we would have to apply the autoderef/autoref steps here 1432 // Apply autoref so the below unification works correctly
1398 // to get the correct receiver type to unify... 1433 let actual_receiver_ty = match expected_receiver_ty {
1399 self.unify(&expected_receiver_ty, &receiver_ty); 1434 Ty::Ref(_, mutability) => Ty::Ref(Arc::new(derefed_receiver_ty), mutability),
1435 _ => derefed_receiver_ty,
1436 };
1437 self.unify(&expected_receiver_ty, &actual_receiver_ty);
1438
1400 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); 1439 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
1401 for (arg, param) in args.iter().zip(param_iter) { 1440 for (arg, param) in args.iter().zip(param_iter) {
1402 self.infer_expr(*arg, &Expectation::has_type(param)); 1441 self.infer_expr(*arg, &Expectation::has_type(param));
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 8d1076774..94b757af2 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -118,11 +118,13 @@ impl Ty {
118 // TODO: cache this as a query? 118 // TODO: cache this as a query?
119 // - if so, what signature? (TyFingerprint, Name)? 119 // - if so, what signature? (TyFingerprint, Name)?
120 // - or maybe cache all names and def_ids of methods per fingerprint? 120 // - or maybe cache all names and def_ids of methods per fingerprint?
121 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<Function> { 121 /// Look up the method with the given name, returning the actual autoderefed
122 self.iterate_methods(db, |f| { 122 /// receiver type (but without autoref applied yet).
123 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<(Ty, Function)> {
124 self.iterate_methods(db, |ty, f| {
123 let sig = f.signature(db); 125 let sig = f.signature(db);
124 if sig.name() == name && sig.has_self_param() { 126 if sig.name() == name && sig.has_self_param() {
125 Some(f) 127 Some((ty.clone(), f))
126 } else { 128 } else {
127 None 129 None
128 } 130 }
@@ -134,7 +136,7 @@ impl Ty {
134 pub fn iterate_methods<T>( 136 pub fn iterate_methods<T>(
135 self, 137 self,
136 db: &impl HirDatabase, 138 db: &impl HirDatabase,
137 mut callback: impl FnMut(Function) -> Option<T>, 139 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
138 ) -> Option<T> { 140 ) -> Option<T> {
139 // For method calls, rust first does any number of autoderef, and then one 141 // For method calls, rust first does any number of autoderef, and then one
140 // autoref (i.e. when the method takes &self or &mut self). We just ignore 142 // autoref (i.e. when the method takes &self or &mut self). We just ignore
@@ -156,7 +158,7 @@ impl Ty {
156 for item in impl_block.items(db) { 158 for item in impl_block.items(db) {
157 match item { 159 match item {
158 ImplItem::Method(f) => { 160 ImplItem::Method(f) => {
159 if let Some(result) = callback(f) { 161 if let Some(result) = callback(&derefed_ty, f) {
160 return Some(result); 162 return Some(result);
161 } 163 }
162 } 164 }
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
index 626f31252..d1ce87b0a 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
@@ -1,36 +1,36 @@
1--- 1---
2created: "2019-01-27T14:52:29.938713255+00:00" 2created: "2019-02-16T20:53:59.655361804Z"
3creator: [email protected] 3creator: [email protected]
4expression: "&result"
5source: crates/ra_hir/src/ty/tests.rs 4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result"
6--- 6---
7[53; 57) 'self': A<[unknown]> 7[53; 57) 'self': A<T2>
8[65; 87) '{ ... }': [unknown] 8[65; 87) '{ ... }': T2
9[75; 79) 'self': A<[unknown]> 9[75; 79) 'self': A<T2>
10[75; 81) 'self.x': [unknown] 10[75; 81) 'self.x': T2
11[99; 100) 't': T 11[99; 100) 't': T
12[110; 115) '{ t }': T 12[110; 115) '{ t }': T
13[112; 113) 't': T 13[112; 113) 't': T
14[135; 261) '{ ....x() }': i128 14[135; 261) '{ ....x() }': i128
15[146; 147) 'x': i32 15[146; 147) 'x': i128
16[150; 151) '1': i32 16[150; 151) '1': i128
17[162; 163) 'y': i32 17[162; 163) 'y': i128
18[166; 168) 'id': fn id<i32>(T) -> T 18[166; 168) 'id': fn id<i128>(T) -> T
19[166; 171) 'id(x)': i32 19[166; 171) 'id(x)': i128
20[169; 170) 'x': i32 20[169; 170) 'x': i128
21[182; 183) 'a': A<i32> 21[182; 183) 'a': A<i128>
22[186; 200) 'A { x: id(y) }': A<i32> 22[186; 200) 'A { x: id(y) }': A<i128>
23[193; 195) 'id': fn id<i32>(T) -> T 23[193; 195) 'id': fn id<i128>(T) -> T
24[193; 198) 'id(y)': i32 24[193; 198) 'id(y)': i128
25[196; 197) 'y': i32 25[196; 197) 'y': i128
26[211; 212) 'z': i32 26[211; 212) 'z': i128
27[215; 217) 'id': fn id<i32>(T) -> T 27[215; 217) 'id': fn id<i128>(T) -> T
28[215; 222) 'id(a.x)': i32 28[215; 222) 'id(a.x)': i128
29[218; 219) 'a': A<i32> 29[218; 219) 'a': A<i128>
30[218; 221) 'a.x': i32 30[218; 221) 'a.x': i128
31[233; 234) 'b': A<i32> 31[233; 234) 'b': A<i128>
32[237; 247) 'A { x: z }': A<i32> 32[237; 247) 'A { x: z }': A<i128>
33[244; 245) 'z': i32 33[244; 245) 'z': i128
34[254; 255) 'b': A<i32> 34[254; 255) 'b': A<i128>
35[254; 259) 'b.x()': i128 35[254; 259) 'b.x()': i128
36 36
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap
new file mode 100644
index 000000000..44f00a52e
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap
@@ -0,0 +1,39 @@
1---
2created: "2019-02-16T21:58:14.029368845Z"
3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result"
6---
7[74; 78) 'self': A<X, Y>
8[85; 107) '{ ... }': X
9[95; 99) 'self': A<X, Y>
10[95; 101) 'self.x': X
11[117; 121) 'self': A<X, Y>
12[128; 150) '{ ... }': Y
13[138; 142) 'self': A<X, Y>
14[138; 144) 'self.y': Y
15[163; 167) 'self': A<X, Y>
16[169; 170) 't': T
17[188; 223) '{ ... }': (X, Y, T)
18[198; 217) '(self.....y, t)': (X, Y, T)
19[199; 203) 'self': A<X, Y>
20[199; 205) 'self.x': X
21[207; 211) 'self': A<X, Y>
22[207; 213) 'self.y': Y
23[215; 216) 't': T
24[245; 342) '{ ...(1); }': ()
25[255; 256) 'a': A<u64, i64>
26[259; 281) 'A { x:...1i64 }': A<u64, i64>
27[266; 270) '1u64': u64
28[275; 279) '1i64': i64
29[287; 288) 'a': A<u64, i64>
30[287; 292) 'a.x()': u64
31[298; 299) 'a': A<u64, i64>
32[298; 303) 'a.y()': i64
33[309; 310) 'a': A<u64, i64>
34[309; 319) 'a.z(1i128)': (u64, i64, i128)
35[313; 318) '1i128': i128
36[325; 326) 'a': A<u64, i64>
37[325; 339) 'a.z::<u128>(1)': (u64, i64, u128)
38[337; 338) '1': u128
39
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap
new file mode 100644
index 000000000..f609eaf7c
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap
@@ -0,0 +1,16 @@
1---
2created: "2019-02-17T13:35:06.385679926Z"
3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result"
6---
7[78; 82) 'self': &Option<T>
8[98; 100) '{}': ()
9[111; 112) 'o': Option<u32>
10[127; 165) '{ ...f(); }': ()
11[133; 146) '(&o).as_ref()': Option<&u32>
12[134; 136) '&o': &Option<u32>
13[135; 136) 'o': Option<u32>
14[152; 153) 'o': Option<u32>
15[152; 162) 'o.as_ref()': Option<&u32>
16
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 203f1fe4d..5eb9c4f5b 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -507,6 +507,58 @@ fn test() {
507} 507}
508 508
509#[test] 509#[test]
510fn infer_impl_generics() {
511 check_inference(
512 "infer_impl_generics",
513 r#"
514struct A<T1, T2> {
515 x: T1,
516 y: T2,
517}
518impl<Y, X> A<X, Y> {
519 fn x(self) -> X {
520 self.x
521 }
522 fn y(self) -> Y {
523 self.y
524 }
525 fn z<T>(self, t: T) -> (X, Y, T) {
526 (self.x, self.y, t)
527 }
528}
529
530fn test() -> i128 {
531 let a = A { x: 1u64, y: 1i64 };
532 a.x();
533 a.y();
534 a.z(1i128);
535 a.z::<u128>(1);
536}
537"#,
538 );
539}
540
541#[test]
542fn infer_impl_generics_with_autoderef() {
543 check_inference(
544 "infer_impl_generics_with_autoderef",
545 r#"
546enum Option<T> {
547 Some(T),
548 None,
549}
550impl<T> Option<T> {
551 fn as_ref(&self) -> Option<&T> {}
552}
553fn test(o: Option<u32>) {
554 (&o).as_ref();
555 o.as_ref();
556}
557"#,
558 );
559}
560
561#[test]
510fn infer_generic_chain() { 562fn infer_generic_chain() {
511 check_inference( 563 check_inference(
512 "infer_generic_chain", 564 "infer_generic_chain",
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index be839345f..20fa323ce 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -63,7 +63,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
63} 63}
64 64
65fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { 65fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
66 receiver.iterate_methods(ctx.db, |func| { 66 receiver.iterate_methods(ctx.db, |_ty, func| {
67 let sig = func.signature(ctx.db); 67 let sig = func.signature(ctx.db);
68 if sig.has_self_param() { 68 if sig.has_self_param() {
69 CompletionItem::new( 69 CompletionItem::new(
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 7c5e8ce5e..dd91b5063 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1352,6 +1352,7 @@ impl ToOwned for ImplBlock {
1352} 1352}
1353 1353
1354 1354
1355impl ast::TypeParamsOwner for ImplBlock {}
1355impl ImplBlock { 1356impl ImplBlock {
1356 pub fn item_list(&self) -> Option<&ItemList> { 1357 pub fn item_list(&self) -> Option<&ItemList> {
1357 super::child_opt(self) 1358 super::child_opt(self)
@@ -2094,6 +2095,10 @@ impl MethodCallExpr {
2094 pub fn name_ref(&self) -> Option<&NameRef> { 2095 pub fn name_ref(&self) -> Option<&NameRef> {
2095 super::child_opt(self) 2096 super::child_opt(self)
2096 } 2097 }
2098
2099 pub fn type_arg_list(&self) -> Option<&TypeArgList> {
2100 super::child_opt(self)
2101 }
2097} 2102}
2098 2103
2099// Module 2104// Module
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 304bc5909..27a123681 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -322,7 +322,7 @@ Grammar(
322 ], 322 ],
323 options: ["TypeRef"] 323 options: ["TypeRef"]
324 ), 324 ),
325 "ImplBlock": (options: ["ItemList"]), 325 "ImplBlock": (options: ["ItemList"], traits: ["TypeParamsOwner"]),
326 326
327 "ParenType": (options: ["TypeRef"]), 327 "ParenType": (options: ["TypeRef"]),
328 "TupleType": ( collections: [["fields", "TypeRef"]] ), 328 "TupleType": ( collections: [["fields", "TypeRef"]] ),
@@ -431,7 +431,7 @@ Grammar(
431 ), 431 ),
432 "MethodCallExpr": ( 432 "MethodCallExpr": (
433 traits: ["ArgListOwner"], 433 traits: ["ArgListOwner"],
434 options: [ "Expr", "NameRef" ], 434 options: [ "Expr", "NameRef", "TypeArgList" ],
435 ), 435 ),
436 "IndexExpr": (), 436 "IndexExpr": (),
437 "FieldExpr": (options: ["Expr", "NameRef"]), 437 "FieldExpr": (options: ["Expr", "NameRef"]),