aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-02-16 21:06:23 +0000
committerFlorian Diebold <[email protected]>2019-02-16 22:06:41 +0000
commit65bd9bc3a800e09f52a315cf98e86c120c366c2c (patch)
tree954a439a7c83898c36a0f2516e4a91c37c03c7dc
parent2af067b391bf37950cf1d3f1af863d931b385af5 (diff)
Handle impl generics in method calls
-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/generics.rs38
-rw-r--r--crates/ra_hir/src/ids.rs3
-rw-r--r--crates/ra_hir/src/ty.rs15
-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.snap40
7 files changed, 122 insertions, 77 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/generics.rs b/crates/ra_hir/src/generics.rs
index 6ae0ead1b..fcc513353 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -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
@@ -40,28 +41,36 @@ impl GenericParams {
40 def: GenericDef, 41 def: GenericDef,
41 ) -> Arc<GenericParams> { 42 ) -> Arc<GenericParams> {
42 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;
43 match def { 52 match def {
44 GenericDef::Function(it) => generics.fill(&*it.source(db).1), 53 GenericDef::Function(it) => generics.fill(&*it.source(db).1, start),
45 GenericDef::Struct(it) => generics.fill(&*it.source(db).1), 54 GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start),
46 GenericDef::Enum(it) => generics.fill(&*it.source(db).1), 55 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start),
47 GenericDef::Trait(it) => generics.fill(&*it.source(db).1), 56 GenericDef::Trait(it) => generics.fill(&*it.source(db).1, start),
48 GenericDef::Type(it) => generics.fill(&*it.source(db).1), 57 GenericDef::Type(it) => generics.fill(&*it.source(db).1, start),
49 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1), 58 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start),
50 } 59 }
51 60
52 Arc::new(generics) 61 Arc::new(generics)
53 } 62 }
54 63
55 fn fill(&mut self, node: &impl TypeParamsOwner) { 64 fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) {
56 if let Some(params) = node.type_param_list() { 65 if let Some(params) = node.type_param_list() {
57 self.fill_params(params) 66 self.fill_params(params, start)
58 } 67 }
59 } 68 }
60 69
61 fn fill_params(&mut self, params: &ast::TypeParamList) { 70 fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) {
62 for (idx, type_param) in params.type_params().enumerate() { 71 for (idx, type_param) in params.type_params().enumerate() {
63 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);
64 let param = GenericParam { idx: idx as u32, name }; 73 let param = GenericParam { idx: idx as u32 + start, name };
65 self.params.push(param); 74 self.params.push(param);
66 } 75 }
67 } 76 }
@@ -69,4 +78,13 @@ impl GenericParams {
69 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { 78 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
70 self.params.iter().find(|p| &p.name == name) 79 self.params.iter().find(|p| &p.name == name)
71 } 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 }
72} 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/ty.rs b/crates/ra_hir/src/ty.rs
index f28a7e731..db0a20514 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -421,7 +421,8 @@ impl Ty {
421 (var.parent_enum(db).generic_params(db), segment) 421 (var.parent_enum(db).generic_params(db), segment)
422 } 422 }
423 }; 423 };
424 // substs_from_path 424 let parent_param_count = def_generics.count_parent_params();
425 substs.extend((0..parent_param_count).map(|_| Ty::Unknown));
425 if let Some(generic_args) = &segment.args_and_bindings { 426 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 427 // 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(); 428 let param_count = def_generics.params.len();
@@ -436,9 +437,8 @@ impl Ty {
436 } 437 }
437 // add placeholders for args that were not provided 438 // add placeholders for args that were not provided
438 // TODO: handle defaults 439 // TODO: handle defaults
439 let supplied_params = 440 let supplied_params = substs.len();
440 segment.args_and_bindings.as_ref().map(|ga| ga.args.len()).unwrap_or(0); 441 for _ in supplied_params..def_generics.count_params_including_parent() {
441 for _ in supplied_params..def_generics.params.len() {
442 substs.push(Ty::Unknown); 442 substs.push(Ty::Unknown);
443 } 443 }
444 assert_eq!(substs.len(), def_generics.params.len()); 444 assert_eq!(substs.len(), def_generics.params.len());
@@ -666,7 +666,12 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
666} 666}
667 667
668fn make_substs(generics: &GenericParams) -> Substs { 668fn make_substs(generics: &GenericParams) -> Substs {
669 Substs(generics.params.iter().map(|_p| Ty::Unknown).collect::<Vec<_>>().into()) 669 Substs(
670 (0..generics.count_params_including_parent())
671 .map(|_p| Ty::Unknown)
672 .collect::<Vec<_>>()
673 .into(),
674 )
670} 675}
671 676
672fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 677fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
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
index 99df39fc2..eabbe52fd 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap
@@ -1,25 +1,25 @@
1--- 1---
2created: "2019-02-16T19:27:11.573533475Z" 2created: "2019-02-16T20:53:59.657979128Z"
3creator: [email protected] 3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs 4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result" 5expression: "&result"
6--- 6---
7[74; 78) 'self': A<[unknown], [unknown]> 7[74; 78) 'self': A<X, Y>
8[85; 107) '{ ... }': [unknown] 8[85; 107) '{ ... }': X
9[95; 99) 'self': A<[unknown], [unknown]> 9[95; 99) 'self': A<X, Y>
10[95; 101) 'self.x': [unknown] 10[95; 101) 'self.x': X
11[117; 121) 'self': A<[unknown], [unknown]> 11[117; 121) 'self': A<X, Y>
12[128; 150) '{ ... }': [unknown] 12[128; 150) '{ ... }': Y
13[138; 142) 'self': A<[unknown], [unknown]> 13[138; 142) 'self': A<X, Y>
14[138; 144) 'self.y': [unknown] 14[138; 144) 'self.y': Y
15[163; 167) 'self': A<[unknown], [unknown]> 15[163; 167) 'self': A<X, Y>
16[169; 170) 't': T 16[169; 170) 't': T
17[188; 223) '{ ... }': ([unknown], [unknown], T) 17[188; 223) '{ ... }': (X, Y, T)
18[198; 217) '(self.....y, t)': ([unknown], [unknown], T) 18[198; 217) '(self.....y, t)': (X, Y, T)
19[199; 203) 'self': A<[unknown], [unknown]> 19[199; 203) 'self': A<X, Y>
20[199; 205) 'self.x': [unknown] 20[199; 205) 'self.x': X
21[207; 211) 'self': A<[unknown], [unknown]> 21[207; 211) 'self': A<X, Y>
22[207; 213) 'self.y': [unknown] 22[207; 213) 'self.y': Y
23[215; 216) 't': T 23[215; 216) 't': T
24[245; 342) '{ ...(1); }': () 24[245; 342) '{ ...(1); }': ()
25[255; 256) 'a': A<u64, i64> 25[255; 256) 'a': A<u64, i64>
@@ -27,13 +27,13 @@ expression: "&result"
27[266; 270) '1u64': u64 27[266; 270) '1u64': u64
28[275; 279) '1i64': i64 28[275; 279) '1i64': i64
29[287; 288) 'a': A<u64, i64> 29[287; 288) 'a': A<u64, i64>
30[287; 292) 'a.x()': [unknown] 30[287; 292) 'a.x()': u64
31[298; 299) 'a': A<u64, i64> 31[298; 299) 'a': A<u64, i64>
32[298; 303) 'a.y()': [unknown] 32[298; 303) 'a.y()': i64
33[309; 310) 'a': A<u64, i64> 33[309; 310) 'a': A<u64, i64>
34[309; 319) 'a.z(1i128)': ([unknown], [unknown], i128) 34[309; 319) 'a.z(1i128)': (u64, i64, i128)
35[313; 318) '1i128': i128 35[313; 318) '1i128': i128
36[325; 326) 'a': A<u64, i64> 36[325; 326) 'a': A<u64, i64>
37[325; 339) 'a.z::<u128>(1)': ([unknown], [unknown], i32) 37[325; 339) 'a.z::<u128>(1)': (u64, i64, i32)
38[337; 338) '1': i32 38[337; 338) '1': i32
39 39