aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-17 12:08:18 +0000
committerAleksey Kladov <[email protected]>2019-01-19 12:37:26 +0000
commitd48d5b8b6ca59b462b3a84dad9868daff2eddb6d (patch)
tree20f1936ccf07abea463ae81b36132efd76ad4f71
parent9433a108cfcf3a9c7de9299d6641a5abf9031a17 (diff)
Add initial (flawed) implementation of binding annotations
-rw-r--r--crates/ra_hir/src/code_model_impl/function/scope.rs2
-rw-r--r--crates/ra_hir/src/expr.rs49
-rw-r--r--crates/ra_hir/src/ty.rs26
-rw-r--r--crates/ra_hir/src/ty/tests.rs4
-rw-r--r--crates/ra_syntax/src/ast.rs10
-rw-r--r--crates/ra_syntax/src/ast/generated.rs6
-rw-r--r--crates/ra_syntax/src/grammar.ron5
7 files changed, 97 insertions, 5 deletions
diff --git a/crates/ra_hir/src/code_model_impl/function/scope.rs b/crates/ra_hir/src/code_model_impl/function/scope.rs
index c551e445a..7e8eb7704 100644
--- a/crates/ra_hir/src/code_model_impl/function/scope.rs
+++ b/crates/ra_hir/src/code_model_impl/function/scope.rs
@@ -88,7 +88,7 @@ impl FnScopes {
88 88
89 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { 89 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
90 match &body[pat] { 90 match &body[pat] {
91 Pat::Bind { name } => self.scopes[scope].entries.push(ScopeEntry { 91 Pat::Bind { name, .. } => self.scopes[scope].entries.push(ScopeEntry {
92 name: name.clone(), 92 name: name.clone(),
93 pat, 93 pat,
94 }), 94 }),
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index e7235c1a1..4d372c97b 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -329,6 +329,43 @@ impl Expr {
329pub struct PatId(RawId); 329pub struct PatId(RawId);
330impl_arena_id!(PatId); 330impl_arena_id!(PatId);
331 331
332// copied verbatim from librustc::hir
333
334/// Explicit binding annotations given in the HIR for a binding. Note
335/// that this is not the final binding *mode* that we infer after type
336/// inference.
337#[derive(Clone, PartialEq, Eq, Debug, Copy)]
338pub enum BindingAnnotation {
339 /// No binding annotation given: this means that the final binding mode
340 /// will depend on whether we have skipped through a `&` reference
341 /// when matching. For example, the `x` in `Some(x)` will have binding
342 /// mode `None`; if you do `let Some(x) = &Some(22)`, it will
343 /// ultimately be inferred to be by-reference.
344 ///
345 /// Note that implicit reference skipping is not implemented yet (#42640).
346 Unannotated,
347
348 /// Annotated with `mut x` -- could be either ref or not, similar to `None`.
349 Mutable,
350
351 /// Annotated as `ref`, like `ref x`
352 Ref,
353
354 /// Annotated as `ref mut x`.
355 RefMut,
356}
357
358impl BindingAnnotation {
359 fn new(is_mutable: bool, is_ref: bool) -> Self {
360 match (is_mutable, is_ref) {
361 (true, true) => BindingAnnotation::RefMut,
362 (false, true) => BindingAnnotation::Ref,
363 (true, false) => BindingAnnotation::Mutable,
364 (false, false) => BindingAnnotation::Unannotated,
365 }
366 }
367}
368
332#[derive(Debug, Clone, Eq, PartialEq)] 369#[derive(Debug, Clone, Eq, PartialEq)]
333pub struct FieldPat { 370pub struct FieldPat {
334 pub(crate) name: Name, 371 pub(crate) name: Name,
@@ -359,7 +396,9 @@ pub enum Pat {
359 Path(Path), 396 Path(Path),
360 Lit(ExprId), 397 Lit(ExprId),
361 Bind { 398 Bind {
399 mode: BindingAnnotation,
362 name: Name, 400 name: Name,
401 sub_pat: Option<PatId>,
363 }, 402 },
364 TupleStruct { 403 TupleStruct {
365 path: Option<Path>, 404 path: Option<Path>,
@@ -793,7 +832,13 @@ impl ExprCollector {
793 .name() 832 .name()
794 .map(|nr| nr.as_name()) 833 .map(|nr| nr.as_name())
795 .unwrap_or_else(Name::missing); 834 .unwrap_or_else(Name::missing);
796 Pat::Bind { name } 835 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref());
836 let sub_pat = bp.pat().map(|subpat| self.collect_pat(subpat));
837 Pat::Bind {
838 name,
839 mode: annotation,
840 sub_pat,
841 }
797 } 842 }
798 ast::PatKind::TupleStructPat(p) => { 843 ast::PatKind::TupleStructPat(p) => {
799 let path = p.path().and_then(Path::from_ast); 844 let path = p.path().and_then(Path::from_ast);
@@ -882,6 +927,8 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping {
882 let param = collector.alloc_pat( 927 let param = collector.alloc_pat(
883 Pat::Bind { 928 Pat::Bind {
884 name: Name::self_param(), 929 name: Name::self_param(),
930 mode: BindingAnnotation::Unannotated,
931 sub_pat: None,
885 }, 932 },
886 self_param, 933 self_param,
887 ); 934 );
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 8ad80990e..bc842dd26 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -37,7 +37,7 @@ use crate::{
37 db::HirDatabase, 37 db::HirDatabase,
38 type_ref::{TypeRef, Mutability}, 38 type_ref::{TypeRef, Mutability},
39 name::KnownName, 39 name::KnownName,
40 expr::{Body, Expr, MatchArm, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, 40 expr::{Body, Expr, BindingAnnotation, MatchArm, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat},
41}; 41};
42 42
43/// The ID of a type variable. 43/// The ID of a type variable.
@@ -985,6 +985,30 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
985 path: ref p, 985 path: ref p,
986 args: ref fields, 986 args: ref fields,
987 } => self.infer_struct(p.as_ref(), fields), 987 } => self.infer_struct(p.as_ref(), fields),
988 Pat::Path(path) => {
989 // is this right?
990 self.module
991 .resolve_path(self.db, &path)
992 .take_values()
993 .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved))
994 }
995 Pat::Bind {
996 mode,
997 name: _name,
998 sub_pat,
999 } => {
1000 let subty = if let Some(subpat) = sub_pat {
1001 self.infer_pat(*subpat, expected)
1002 } else {
1003 Ty::Unknown
1004 };
1005
1006 match mode {
1007 BindingAnnotation::Ref => Ty::Ref(subty.into(), Mutability::Shared),
1008 BindingAnnotation::RefMut => Ty::Ref(subty.into(), Mutability::Mut),
1009 BindingAnnotation::Mutable | BindingAnnotation::Unannotated => subty,
1010 }
1011 }
988 _ => Ty::Unknown, 1012 _ => Ty::Unknown,
989 }; 1013 };
990 // use a new type variable if we got Ty::Unknown here 1014 // use a new type variable if we got Ty::Unknown here
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index dfc83bb17..e817a8da9 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -377,6 +377,10 @@ fn test(x: &i32) {
377 } 377 }
378 378
379 let lambda = |a: u64, b, c: i32| { a + b; c }; 379 let lambda = |a: u64, b, c: i32| { a + b; c };
380
381 let ref ref_to_x = x;
382 let mut mut_x = x;
383 let ref mut mut_ref_to_x = x;
380} 384}
381"#, 385"#,
382 "pattern.txt", 386 "pattern.txt",
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 4b7edbbe7..0ee9ef199 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -713,6 +713,16 @@ impl FieldPatList {
713 } 713 }
714} 714}
715 715
716impl BindPat {
717 pub fn is_mutable(&self) -> bool {
718 self.syntax().children().any(|n| n.kind() == MUT_KW)
719 }
720
721 pub fn is_ref(&self) -> bool {
722 self.syntax().children().any(|n| n.kind() == REF_KW)
723 }
724}
725
716#[test] 726#[test]
717fn test_doc_comment_of_items() { 727fn test_doc_comment_of_items() {
718 let file = SourceFile::parse( 728 let file = SourceFile::parse(
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 251d53bdf..ead0f1293 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -180,7 +180,11 @@ impl AstNode for BindPat {
180 180
181 181
182impl ast::NameOwner for BindPat {} 182impl ast::NameOwner for BindPat {}
183impl BindPat {} 183impl BindPat {
184 pub fn pat(&self) -> Option<&Pat> {
185 super::child_opt(self)
186 }
187}
184 188
185// Block 189// Block
186#[derive(Debug, PartialEq, Eq, Hash)] 190#[derive(Debug, PartialEq, Eq, Hash)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 33080f664..d58e0dd35 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -488,7 +488,10 @@ Grammar(
488 ), 488 ),
489 489
490 "RefPat": ( options: [ "Pat" ]), 490 "RefPat": ( options: [ "Pat" ]),
491 "BindPat": ( traits: ["NameOwner"] ), 491 "BindPat": (
492 options: [ "Pat" ],
493 traits: ["NameOwner"]
494 ),
492 "PlaceholderPat": (), 495 "PlaceholderPat": (),
493 "PathPat": ( options: [ "Path" ] ), 496 "PathPat": ( options: [ "Path" ] ),
494 "StructPat": ( options: ["FieldPatList", "Path"] ), 497 "StructPat": ( options: ["FieldPatList", "Path"] ),