aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--crates/ra_syntax/src/ast.rs39
-rw-r--r--crates/ra_syntax/src/ast/generated.rs18
-rw-r--r--crates/ra_syntax/src/grammar.ron6
7 files changed, 173 insertions, 23 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
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 5dbf9b221..8fb6b6408 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -394,3 +394,42 @@ impl<'a> EnumVariant<'a> {
394 StructFlavor::from_node(self) 394 StructFlavor::from_node(self)
395 } 395 }
396} 396}
397
398impl<'a> PointerType<'a> {
399 pub fn is_mut(&self) -> bool {
400 self.syntax().children().any(|n| n.kind() == MUT_KW)
401 }
402}
403
404impl<'a> ReferenceType<'a> {
405 pub fn is_mut(&self) -> bool {
406 self.syntax().children().any(|n| n.kind() == MUT_KW)
407 }
408}
409
410impl<'a> RefExpr<'a> {
411 pub fn is_mut(&self) -> bool {
412 self.syntax().children().any(|n| n.kind() == MUT_KW)
413 }
414}
415
416#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
417pub enum PrefixOp {
418 /// The `*` operator for dereferencing
419 Deref,
420 /// The `!` operator for logical inversion
421 Not,
422 /// The `-` operator for negation
423 Neg,
424}
425
426impl<'a> PrefixExpr<'a> {
427 pub fn op(&self) -> Option<PrefixOp> {
428 match self.syntax().first_child()?.kind() {
429 STAR => Some(PrefixOp::Deref),
430 EXCL => Some(PrefixOp::Not),
431 MINUS => Some(PrefixOp::Neg),
432 _ => None,
433 }
434 }
435}
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 6b2800a0e..535dcc975 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -2607,7 +2607,11 @@ impl<R: TreeRoot<RaTypes>> ParenTypeNode<R> {
2607} 2607}
2608 2608
2609 2609
2610impl<'a> ParenType<'a> {} 2610impl<'a> ParenType<'a> {
2611 pub fn type_ref(self) -> Option<TypeRef<'a>> {
2612 super::child_opt(self)
2613 }
2614}
2611 2615
2612// Pat 2616// Pat
2613#[derive(Debug, Clone, Copy, PartialEq, Eq)] 2617#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -2972,7 +2976,11 @@ impl<R: TreeRoot<RaTypes>> PointerTypeNode<R> {
2972} 2976}
2973 2977
2974 2978
2975impl<'a> PointerType<'a> {} 2979impl<'a> PointerType<'a> {
2980 pub fn type_ref(self) -> Option<TypeRef<'a>> {
2981 super::child_opt(self)
2982 }
2983}
2976 2984
2977// PosField 2985// PosField
2978#[derive(Debug, Clone, Copy,)] 2986#[derive(Debug, Clone, Copy,)]
@@ -3285,7 +3293,11 @@ impl<R: TreeRoot<RaTypes>> ReferenceTypeNode<R> {
3285} 3293}
3286 3294
3287 3295
3288impl<'a> ReferenceType<'a> {} 3296impl<'a> ReferenceType<'a> {
3297 pub fn type_ref(self) -> Option<TypeRef<'a>> {
3298 super::child_opt(self)
3299 }
3300}
3289 3301
3290// RetType 3302// RetType
3291#[derive(Debug, Clone, Copy,)] 3303#[derive(Debug, Clone, Copy,)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index dcde32923..8b1bd6d1c 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -303,14 +303,14 @@ Grammar(
303 ] ), 303 ] ),
304 "ImplItem": (), 304 "ImplItem": (),
305 305
306 "ParenType": (), 306 "ParenType": (options: ["TypeRef"]),
307 "TupleType": (), 307 "TupleType": (),
308 "NeverType": (), 308 "NeverType": (),
309 "PathType": (options: ["Path"]), 309 "PathType": (options: ["Path"]),
310 "PointerType": (), 310 "PointerType": (options: ["TypeRef"]),
311 "ArrayType": (), 311 "ArrayType": (),
312 "SliceType": (), 312 "SliceType": (),
313 "ReferenceType": (), 313 "ReferenceType": (options: ["TypeRef"]),
314 "PlaceholderType": (), 314 "PlaceholderType": (),
315 "FnPointerType": (), 315 "FnPointerType": (),
316 "ForType": (), 316 "ForType": (),