aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2018-12-29 20:32:07 +0000
committerFlorian Diebold <[email protected]>2019-01-04 18:10:50 +0000
commit111126ed3c4f6358e0c833f80226e5192778f749 (patch)
tree83ddf3395d8f8eb97323bb8581bef80fd9eda846 /crates
parentae9530addc4c5e9bbfd5c0287d3c3adb2de95e40 (diff)
Type the self parameter
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/mock.rs4
-rw-r--r--crates/ra_hir/src/ty.rs38
-rw-r--r--crates/ra_hir/src/ty/tests/data/0007_self.txt2
-rw-r--r--crates/ra_syntax/src/ast.rs31
-rw-r--r--crates/ra_syntax/src/ast/generated.rs47
-rw-r--r--crates/ra_syntax/src/grammar.ron3
6 files changed, 116 insertions, 9 deletions
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index ef245ec7a..2419d256a 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -30,6 +30,10 @@ impl MockDatabase {
30 let file_id = db.add_file(&mut source_root, "/main.rs", text); 30 let file_id = db.add_file(&mut source_root, "/main.rs", text);
31 db.query_mut(ra_db::SourceRootQuery) 31 db.query_mut(ra_db::SourceRootQuery)
32 .set(WORKSPACE, Arc::new(source_root.clone())); 32 .set(WORKSPACE, Arc::new(source_root.clone()));
33
34 let mut crate_graph = CrateGraph::default();
35 crate_graph.add_crate_root(file_id);
36 db.set_crate_graph(crate_graph);
33 (db, source_root, file_id) 37 (db, source_root, file_id)
34 } 38 }
35 39
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 719b3f7cd..c762ec606 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -918,22 +918,46 @@ pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceRe
918 let node = syntax.borrowed(); 918 let node = syntax.borrowed();
919 919
920 if let Some(param_list) = node.param_list() { 920 if let Some(param_list) = node.param_list() {
921 if let Some(self_param) = param_list.self_param() {
922 let self_type = if let Some(impl_block) = function.impl_block(db)? {
923 if let Some(type_ref) = self_param.type_ref() {
924 let ty = Ty::from_ast(db, &ctx.module, type_ref)?;
925 ctx.insert_type_vars(ty)
926 } else {
927 let ty = Ty::from_hir(db, &ctx.module, impl_block.target())?;
928 let ty = match self_param.flavor() {
929 ast::SelfParamFlavor::Owned => ty,
930 ast::SelfParamFlavor::Ref => Ty::Ref(Arc::new(ty), Mutability::Shared),
931 ast::SelfParamFlavor::MutRef => Ty::Ref(Arc::new(ty), Mutability::Mut),
932 };
933 ctx.insert_type_vars(ty)
934 }
935 } else {
936 log::debug!(
937 "No impl block found, but self param for function {:?}",
938 def_id
939 );
940 ctx.new_type_var()
941 };
942 if let Some(self_kw) = self_param.self_kw() {
943 ctx.type_of
944 .insert(LocalSyntaxPtr::new(self_kw.syntax()), self_type);
945 }
946 }
921 for param in param_list.params() { 947 for param in param_list.params() {
922 let pat = if let Some(pat) = param.pat() { 948 let pat = if let Some(pat) = param.pat() {
923 pat 949 pat
924 } else { 950 } else {
925 continue; 951 continue;
926 }; 952 };
927 if let Some(type_ref) = param.type_ref() { 953 let ty = if let Some(type_ref) = param.type_ref() {
928 let ty = Ty::from_ast(db, &ctx.module, type_ref)?; 954 let ty = Ty::from_ast(db, &ctx.module, type_ref)?;
929 let ty = ctx.insert_type_vars(ty); 955 ctx.insert_type_vars(ty)
930 ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty);
931 } else { 956 } else {
932 // TODO self param 957 // missing type annotation
933 let type_var = ctx.new_type_var(); 958 ctx.new_type_var()
934 ctx.type_of
935 .insert(LocalSyntaxPtr::new(pat.syntax()), type_var);
936 }; 959 };
960 ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty);
937 } 961 }
938 } 962 }
939 963
diff --git a/crates/ra_hir/src/ty/tests/data/0007_self.txt b/crates/ra_hir/src/ty/tests/data/0007_self.txt
index 18cd796c2..3d3c8b260 100644
--- a/crates/ra_hir/src/ty/tests/data/0007_self.txt
+++ b/crates/ra_hir/src/ty/tests/data/0007_self.txt
@@ -1,4 +1,6 @@
1[50; 54) 'self': [unknown] 1[50; 54) 'self': [unknown]
2[34; 38) 'self': &S
2[40; 61) '{ ... }': () 3[40; 61) '{ ... }': ()
3[88; 109) '{ ... }': () 4[88; 109) '{ ... }': ()
4[98; 102) 'self': [unknown] 5[98; 102) 'self': [unknown]
6[75; 79) 'self': &[unknown]
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 7f986d322..2a3bd27e2 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -482,6 +482,37 @@ impl<'a> PrefixExpr<'a> {
482 } 482 }
483} 483}
484 484
485#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
486pub enum SelfParamFlavor {
487 /// self
488 Owned,
489 /// &self
490 Ref,
491 /// &mut self
492 MutRef,
493}
494
495impl<'a> SelfParam<'a> {
496 pub fn flavor(&self) -> SelfParamFlavor {
497 let borrowed = self.syntax().children().any(|n| n.kind() == AMP);
498 if borrowed {
499 // check for a `mut` coming after the & -- `mut &self` != `&mut self`
500 if self
501 .syntax()
502 .children()
503 .skip_while(|n| n.kind() != AMP)
504 .any(|n| n.kind() == MUT_KW)
505 {
506 SelfParamFlavor::MutRef
507 } else {
508 SelfParamFlavor::Ref
509 }
510 } else {
511 SelfParamFlavor::Owned
512 }
513 }
514}
515
485#[test] 516#[test]
486fn test_doc_comment_of_items() { 517fn test_doc_comment_of_items() {
487 let file = SourceFileNode::parse( 518 let file = SourceFileNode::parse(
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 91de17ddf..7df6a9c46 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -3488,6 +3488,43 @@ impl<'a> ReturnExpr<'a> {
3488 } 3488 }
3489} 3489}
3490 3490
3491// SelfKw
3492#[derive(Debug, Clone, Copy,)]
3493pub struct SelfKwNode<R: TreeRoot<RaTypes> = OwnedRoot> {
3494 pub(crate) syntax: SyntaxNode<R>,
3495}
3496pub type SelfKw<'a> = SelfKwNode<RefRoot<'a>>;
3497
3498impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<SelfKwNode<R1>> for SelfKwNode<R2> {
3499 fn eq(&self, other: &SelfKwNode<R1>) -> bool { self.syntax == other.syntax }
3500}
3501impl<R: TreeRoot<RaTypes>> Eq for SelfKwNode<R> {}
3502impl<R: TreeRoot<RaTypes>> Hash for SelfKwNode<R> {
3503 fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) }
3504}
3505
3506impl<'a> AstNode<'a> for SelfKw<'a> {
3507 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
3508 match syntax.kind() {
3509 SELF_KW => Some(SelfKw { syntax }),
3510 _ => None,
3511 }
3512 }
3513 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
3514}
3515
3516impl<R: TreeRoot<RaTypes>> SelfKwNode<R> {
3517 pub fn borrowed(&self) -> SelfKw {
3518 SelfKwNode { syntax: self.syntax.borrowed() }
3519 }
3520 pub fn owned(&self) -> SelfKwNode {
3521 SelfKwNode { syntax: self.syntax.owned() }
3522 }
3523}
3524
3525
3526impl<'a> SelfKw<'a> {}
3527
3491// SelfParam 3528// SelfParam
3492#[derive(Debug, Clone, Copy,)] 3529#[derive(Debug, Clone, Copy,)]
3493pub struct SelfParamNode<R: TreeRoot<RaTypes> = OwnedRoot> { 3530pub struct SelfParamNode<R: TreeRoot<RaTypes> = OwnedRoot> {
@@ -3523,7 +3560,15 @@ impl<R: TreeRoot<RaTypes>> SelfParamNode<R> {
3523} 3560}
3524 3561
3525 3562
3526impl<'a> SelfParam<'a> {} 3563impl<'a> SelfParam<'a> {
3564 pub fn type_ref(self) -> Option<TypeRef<'a>> {
3565 super::child_opt(self)
3566 }
3567
3568 pub fn self_kw(self) -> Option<SelfKw<'a>> {
3569 super::child_opt(self)
3570 }
3571}
3527 3572
3528// SlicePat 3573// SlicePat
3529#[derive(Debug, Clone, Copy,)] 3574#[derive(Debug, Clone, Copy,)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 688a4af1e..c55e9e07a 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -534,7 +534,8 @@ Grammar(
534 ["params", "Param"] 534 ["params", "Param"]
535 ] 535 ]
536 ), 536 ),
537 "SelfParam": (), 537 "SelfParam": (options: ["TypeRef", "SelfKw"]),
538 "SelfKw": (),
538 "Param": ( 539 "Param": (
539 options: [ "Pat", "TypeRef" ], 540 options: [ "Pat", "TypeRef" ],
540 ), 541 ),