aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2018-12-25 16:17:39 +0000
committerFlorian Diebold <[email protected]>2018-12-25 19:36:06 +0000
commit2870effd5c69941bbf32a44c0ee6d9d42e0b038d (patch)
treebf2c5ff08e6f316c1d9d629ae3595e6f7c069e5d /crates/ra_hir
parentb96d3612390e070936a176571c946ad0cafa69a9 (diff)
Implement reference / pointer types
- parse them - infer types of & and * expressions
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/ty.rs84
-rw-r--r--crates/ra_hir/src/ty/tests.rs22
-rw-r--r--crates/ra_hir/src/ty/tests/data/0001_basics.txt4
-rw-r--r--crates/ra_hir/src/ty/tests/data/0005_refs.txt23
4 files changed, 116 insertions, 17 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 3674688ef..54aa6715c 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -11,7 +11,7 @@ use rustc_hash::{FxHashMap};
11use ra_db::{LocalSyntaxPtr, Cancelable}; 11use ra_db::{LocalSyntaxPtr, Cancelable};
12use ra_syntax::{ 12use ra_syntax::{
13 SmolStr, 13 SmolStr,
14 ast::{self, AstNode, LoopBodyOwner, ArgListOwner}, 14 ast::{self, AstNode, LoopBodyOwner, ArgListOwner, PrefixOp},
15 SyntaxNodeRef 15 SyntaxNodeRef
16}; 16};
17 17
@@ -21,6 +21,36 @@ use crate::{
21 adt::VariantData, 21 adt::VariantData,
22}; 22};
23 23
24#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
25pub enum Mutability {
26 Shared,
27 Mut,
28}
29
30impl Mutability {
31 pub fn from_mutable(mutable: bool) -> Mutability {
32 if mutable {
33 Mutability::Mut
34 } else {
35 Mutability::Shared
36 }
37 }
38
39 pub fn as_keyword_for_ref(self) -> &'static str {
40 match self {
41 Mutability::Shared => "",
42 Mutability::Mut => "mut ",
43 }
44 }
45
46 pub fn as_keyword_for_ptr(self) -> &'static str {
47 match self {
48 Mutability::Shared => "const ",
49 Mutability::Mut => "mut ",
50 }
51 }
52}
53
24#[derive(Clone, PartialEq, Eq, Hash, Debug)] 54#[derive(Clone, PartialEq, Eq, Hash, Debug)]
25pub enum Ty { 55pub enum Ty {
26 /// The primitive boolean type. Written as `bool`. 56 /// The primitive boolean type. Written as `bool`.
@@ -56,12 +86,13 @@ pub enum Ty {
56 /// The pointee of an array slice. Written as `[T]`. 86 /// The pointee of an array slice. Written as `[T]`.
57 Slice(TyRef), 87 Slice(TyRef),
58 88
59 // A raw pointer. Written as `*mut T` or `*const T` 89 /// A raw pointer. Written as `*mut T` or `*const T`
60 // RawPtr(TypeAndMut<'tcx>), 90 RawPtr(TyRef, Mutability),
91
92 /// A reference; a pointer with an associated lifetime. Written as
93 /// `&'a mut T` or `&'a T`.
94 Ref(TyRef, Mutability),
61 95
62 // A reference; a pointer with an associated lifetime. Written as
63 // `&'a mut T` or `&'a T`.
64 // Ref(Ty<'tcx>, hir::Mutability),
65 /// A pointer to a function. Written as `fn() -> i32`. 96 /// A pointer to a function. Written as `fn() -> i32`.
66 /// 97 ///
67 /// For example the type of `bar` here: 98 /// For example the type of `bar` here:
@@ -172,7 +203,7 @@ impl Ty {
172 ) -> Cancelable<Self> { 203 ) -> Cancelable<Self> {
173 use ra_syntax::ast::TypeRef::*; 204 use ra_syntax::ast::TypeRef::*;
174 Ok(match node { 205 Ok(match node {
175 ParenType(_inner) => Ty::Unknown, // TODO 206 ParenType(inner) => Ty::new_opt(db, module, inner.type_ref())?,
176 TupleType(_inner) => Ty::Unknown, // TODO 207 TupleType(_inner) => Ty::Unknown, // TODO
177 NeverType(..) => Ty::Never, 208 NeverType(..) => Ty::Never,
178 PathType(inner) => { 209 PathType(inner) => {
@@ -182,10 +213,18 @@ impl Ty {
182 Ty::Unknown 213 Ty::Unknown
183 } 214 }
184 } 215 }
185 PointerType(_inner) => Ty::Unknown, // TODO 216 PointerType(inner) => {
186 ArrayType(_inner) => Ty::Unknown, // TODO 217 let inner_ty = Ty::new_opt(db, module, inner.type_ref())?;
187 SliceType(_inner) => Ty::Unknown, // TODO 218 let mutability = Mutability::from_mutable(inner.is_mut());
188 ReferenceType(_inner) => Ty::Unknown, // TODO 219 Ty::RawPtr(Arc::new(inner_ty), mutability)
220 }
221 ArrayType(_inner) => Ty::Unknown, // TODO
222 SliceType(_inner) => Ty::Unknown, // TODO
223 ReferenceType(inner) => {
224 let inner_ty = Ty::new_opt(db, module, inner.type_ref())?;
225 let mutability = Mutability::from_mutable(inner.is_mut());
226 Ty::Ref(Arc::new(inner_ty), mutability)
227 }
189 PlaceholderType(_inner) => Ty::Unknown, // TODO 228 PlaceholderType(_inner) => Ty::Unknown, // TODO
190 FnPointerType(_inner) => Ty::Unknown, // TODO 229 FnPointerType(_inner) => Ty::Unknown, // TODO
191 ForType(_inner) => Ty::Unknown, // TODO 230 ForType(_inner) => Ty::Unknown, // TODO
@@ -209,6 +248,8 @@ impl fmt::Display for Ty {
209 Ty::Float(t) => write!(f, "{}", t.ty_to_string()), 248 Ty::Float(t) => write!(f, "{}", t.ty_to_string()),
210 Ty::Str => write!(f, "str"), 249 Ty::Str => write!(f, "str"),
211 Ty::Slice(t) => write!(f, "[{}]", t), 250 Ty::Slice(t) => write!(f, "[{}]", t),
251 Ty::RawPtr(t, m) => write!(f, "*{}{}", m.as_keyword_for_ptr(), t),
252 Ty::Ref(t, m) => write!(f, "&{}{}", m.as_keyword_for_ref(), t),
212 Ty::Never => write!(f, "!"), 253 Ty::Never => write!(f, "!"),
213 Ty::Tuple(ts) => { 254 Ty::Tuple(ts) => {
214 write!(f, "(")?; 255 write!(f, "(")?;
@@ -539,12 +580,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
539 cast_ty 580 cast_ty
540 } 581 }
541 ast::Expr::RefExpr(e) => { 582 ast::Expr::RefExpr(e) => {
542 let _inner_ty = self.infer_expr_opt(e.expr())?; 583 let inner_ty = self.infer_expr_opt(e.expr())?;
543 Ty::Unknown 584 let m = Mutability::from_mutable(e.is_mut());
585 // TODO reference coercions etc.
586 Ty::Ref(Arc::new(inner_ty), m)
544 } 587 }
545 ast::Expr::PrefixExpr(e) => { 588 ast::Expr::PrefixExpr(e) => {
546 let _inner_ty = self.infer_expr_opt(e.expr())?; 589 let inner_ty = self.infer_expr_opt(e.expr())?;
547 Ty::Unknown 590 match e.op() {
591 Some(PrefixOp::Deref) => {
592 match inner_ty {
593 // builtin deref:
594 Ty::Ref(ref_inner, _) => (*ref_inner).clone(),
595 Ty::RawPtr(ptr_inner, _) => (*ptr_inner).clone(),
596 // TODO Deref::deref
597 _ => Ty::Unknown,
598 }
599 }
600 _ => Ty::Unknown,
601 }
548 } 602 }
549 ast::Expr::RangeExpr(_e) => Ty::Unknown, 603 ast::Expr::RangeExpr(_e) => Ty::Unknown,
550 ast::Expr::BinExpr(_e) => Ty::Unknown, 604 ast::Expr::BinExpr(_e) => Ty::Unknown,
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 9bb58ec85..a76925b58 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -91,6 +91,28 @@ fn test() {
91 ); 91 );
92} 92}
93 93
94#[test]
95fn infer_refs_and_ptrs() {
96 check_inference(
97 r#"
98fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
99 a;
100 *a;
101 &a;
102 &mut a;
103 b;
104 *b;
105 &b;
106 c;
107 *c;
108 d;
109 *d;
110}
111"#,
112 "0005_refs.txt",
113 );
114}
115
94fn infer(content: &str) -> String { 116fn infer(content: &str) -> String {
95 let (db, _, file_id) = MockDatabase::with_single_file(content); 117 let (db, _, file_id) = MockDatabase::with_single_file(content);
96 let source_file = db.source_file(file_id); 118 let source_file = db.source_file(file_id);
diff --git a/crates/ra_hir/src/ty/tests/data/0001_basics.txt b/crates/ra_hir/src/ty/tests/data/0001_basics.txt
index 0c46f243a..212e92e00 100644
--- a/crates/ra_hir/src/ty/tests/data/0001_basics.txt
+++ b/crates/ra_hir/src/ty/tests/data/0001_basics.txt
@@ -1,4 +1,4 @@
1[33; 34) 'd': [unknown] 1[33; 34) 'd': &[unknown]
2[88; 94) '1isize': [unknown] 2[88; 94) '1isize': [unknown]
3[48; 49) 'a': u32 3[48; 49) 'a': u32
4[55; 56) 'b': isize 4[55; 56) 'b': isize
@@ -10,4 +10,4 @@
10[17; 18) 'b': isize 10[17; 18) 'b': isize
11[100; 106) '"test"': [unknown] 11[100; 106) '"test"': [unknown]
12[42; 121) '{ ...f32; }': () 12[42; 121) '{ ...f32; }': ()
13[69; 70) 'd': [unknown] 13[69; 70) 'd': &[unknown]
diff --git a/crates/ra_hir/src/ty/tests/data/0005_refs.txt b/crates/ra_hir/src/ty/tests/data/0005_refs.txt
new file mode 100644
index 000000000..296e955c1
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/0005_refs.txt
@@ -0,0 +1,23 @@
1[115; 117) '&b': &&mut u32
2[88; 94) '&mut a': &mut &u32
3[146; 147) 'd': *mut u32
4[145; 147) '*d': u32
5[65; 66) 'a': &u32
6[46; 47) 'd': *mut u32
7[59; 150) '{ ... *d; }': ()
8[116; 117) 'b': &mut u32
9[131; 132) 'c': *const u32
10[130; 132) '*c': u32
11[72; 74) '*a': u32
12[107; 109) '*b': u32
13[108; 109) 'b': &mut u32
14[9; 10) 'a': &u32
15[18; 19) 'b': &mut u32
16[93; 94) 'a': &u32
17[100; 101) 'b': &mut u32
18[81; 82) 'a': &u32
19[80; 82) '&a': &&u32
20[73; 74) 'a': &u32
21[123; 124) 'c': *const u32
22[31; 32) 'c': *const u32
23[138; 139) 'd': *mut u32