diff options
author | Florian Diebold <[email protected]> | 2018-12-25 20:14:13 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2018-12-25 20:14:13 +0000 |
commit | cdca39706121b2d1734a94938a2372da881e10c6 (patch) | |
tree | d3f9687371eb1a7004c4694c59445af388eb1876 | |
parent | 2870effd5c69941bbf32a44c0ee6d9d42e0b038d (diff) |
Add a hir::TypeRef as an intermediate between ast::TypeRef and ty::Ty
-rw-r--r-- | crates/ra_analysis/src/completion/complete_path.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/adt.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/module.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/module/nameres.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/path.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 139 | ||||
-rw-r--r-- | crates/ra_hir/src/type_ref.rs | 110 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 38 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 10 |
10 files changed, 219 insertions, 95 deletions
diff --git a/crates/ra_analysis/src/completion/complete_path.rs b/crates/ra_analysis/src/completion/complete_path.rs index 8c00be499..aaa2c7cee 100644 --- a/crates/ra_analysis/src/completion/complete_path.rs +++ b/crates/ra_analysis/src/completion/complete_path.rs | |||
@@ -8,7 +8,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> C | |||
8 | (Some(path), Some(module)) => (path.clone(), module), | 8 | (Some(path), Some(module)) => (path.clone(), module), |
9 | _ => return Ok(()), | 9 | _ => return Ok(()), |
10 | }; | 10 | }; |
11 | let def_id = match module.resolve_path(ctx.db, path)?.take_types() { | 11 | let def_id = match module.resolve_path(ctx.db, &path)?.take_types() { |
12 | Some(it) => it, | 12 | Some(it) => it, |
13 | None => return Ok(()), | 13 | None => return Ok(()), |
14 | }; | 14 | }; |
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 40a45b831..dae04d258 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -145,7 +145,7 @@ impl VariantData { | |||
145 | .map(|(i, fd)| { | 145 | .map(|(i, fd)| { |
146 | Ok(StructField { | 146 | Ok(StructField { |
147 | name: SmolStr::new(i.to_string()), | 147 | name: SmolStr::new(i.to_string()), |
148 | ty: Ty::new_opt(db, &module, fd.type_ref())?, | 148 | ty: Ty::from_ast_opt(db, &module, fd.type_ref())?, |
149 | }) | 149 | }) |
150 | }) | 150 | }) |
151 | .collect::<Cancelable<_>>()?; | 151 | .collect::<Cancelable<_>>()?; |
@@ -160,7 +160,7 @@ impl VariantData { | |||
160 | .name() | 160 | .name() |
161 | .map(|n| n.text()) | 161 | .map(|n| n.text()) |
162 | .unwrap_or_else(|| SmolStr::new("[error]")), | 162 | .unwrap_or_else(|| SmolStr::new("[error]")), |
163 | ty: Ty::new_opt(db, &module, fd.type_ref())?, | 163 | ty: Ty::from_ast_opt(db, &module, fd.type_ref())?, |
164 | }) | 164 | }) |
165 | }) | 165 | }) |
166 | .collect::<Cancelable<_>>()?; | 166 | .collect::<Cancelable<_>>()?; |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 68fdbb7ea..f1cc0ccd0 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -26,6 +26,7 @@ mod krate; | |||
26 | mod module; | 26 | mod module; |
27 | mod function; | 27 | mod function; |
28 | mod adt; | 28 | mod adt; |
29 | mod type_ref; | ||
29 | mod ty; | 30 | mod ty; |
30 | 31 | ||
31 | use std::ops::Index; | 32 | use std::ops::Index; |
diff --git a/crates/ra_hir/src/module.rs b/crates/ra_hir/src/module.rs index e1a0e4b59..b9d36f01f 100644 --- a/crates/ra_hir/src/module.rs +++ b/crates/ra_hir/src/module.rs | |||
@@ -115,7 +115,7 @@ impl Module { | |||
115 | Ok(res) | 115 | Ok(res) |
116 | } | 116 | } |
117 | 117 | ||
118 | pub fn resolve_path(&self, db: &impl HirDatabase, path: Path) -> Cancelable<PerNs<DefId>> { | 118 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> Cancelable<PerNs<DefId>> { |
119 | let mut curr_per_ns = PerNs::types( | 119 | let mut curr_per_ns = PerNs::types( |
120 | match path.kind { | 120 | match path.kind { |
121 | PathKind::Crate => self.crate_root(), | 121 | PathKind::Crate => self.crate_root(), |
@@ -131,7 +131,7 @@ impl Module { | |||
131 | .def_id(db), | 131 | .def_id(db), |
132 | ); | 132 | ); |
133 | 133 | ||
134 | let segments = path.segments; | 134 | let segments = &path.segments; |
135 | for name in segments.iter() { | 135 | for name in segments.iter() { |
136 | let curr = if let Some(r) = curr_per_ns.as_ref().take(Namespace::Types) { | 136 | let curr = if let Some(r) = curr_per_ns.as_ref().take(Namespace::Types) { |
137 | r | 137 | r |
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index 33c9d93c2..98cd225dd 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs | |||
@@ -451,7 +451,7 @@ where | |||
451 | segments: import.path.segments[i + 1..].iter().cloned().collect(), | 451 | segments: import.path.segments[i + 1..].iter().cloned().collect(), |
452 | kind: PathKind::Crate, | 452 | kind: PathKind::Crate, |
453 | }; | 453 | }; |
454 | let def_id = module.resolve_path(self.db, path)?; | 454 | let def_id = module.resolve_path(self.db, &path)?; |
455 | if !def_id.is_none() { | 455 | if !def_id.is_none() { |
456 | self.update(module_id, |items| { | 456 | self.update(module_id, |items| { |
457 | let res = Resolution { | 457 | let res = Resolution { |
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index e04d00900..0b260072c 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs | |||
@@ -1,12 +1,12 @@ | |||
1 | use ra_syntax::{SmolStr, ast, AstNode, TextRange}; | 1 | use ra_syntax::{SmolStr, ast, AstNode, TextRange}; |
2 | 2 | ||
3 | #[derive(Debug, Clone, PartialEq, Eq)] | 3 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
4 | pub struct Path { | 4 | pub struct Path { |
5 | pub kind: PathKind, | 5 | pub kind: PathKind, |
6 | pub segments: Vec<SmolStr>, | 6 | pub segments: Vec<SmolStr>, |
7 | } | 7 | } |
8 | 8 | ||
9 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 9 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
10 | pub enum PathKind { | 10 | pub enum PathKind { |
11 | Plain, | 11 | Plain, |
12 | Self_, | 12 | Self_, |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 54aa6715c..11b4caa23 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -19,38 +19,9 @@ use crate::{ | |||
19 | Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, | 19 | Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, |
20 | db::HirDatabase, | 20 | db::HirDatabase, |
21 | adt::VariantData, | 21 | adt::VariantData, |
22 | type_ref::{TypeRef, Mutability}, | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||
25 | pub enum Mutability { | ||
26 | Shared, | ||
27 | Mut, | ||
28 | } | ||
29 | |||
30 | impl 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 | |||
54 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 25 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
55 | pub enum Ty { | 26 | pub enum Ty { |
56 | /// The primitive boolean type. Written as `bool`. | 27 | /// The primitive boolean type. Written as `bool`. |
@@ -156,16 +127,58 @@ pub struct FnSig { | |||
156 | } | 127 | } |
157 | 128 | ||
158 | impl Ty { | 129 | impl Ty { |
159 | pub(crate) fn new_from_ast_path( | 130 | pub(crate) fn from_hir( |
160 | db: &impl HirDatabase, | 131 | db: &impl HirDatabase, |
161 | module: &Module, | 132 | module: &Module, |
162 | path: ast::Path, | 133 | type_ref: &TypeRef, |
134 | ) -> Cancelable<Self> { | ||
135 | Ok(match type_ref { | ||
136 | TypeRef::Never => Ty::Never, | ||
137 | TypeRef::Tuple(inner) => { | ||
138 | let inner_tys = inner | ||
139 | .iter() | ||
140 | .map(|tr| Ty::from_hir(db, module, tr)) | ||
141 | .collect::<Cancelable<_>>()?; | ||
142 | Ty::Tuple(inner_tys) | ||
143 | } | ||
144 | TypeRef::Path(path) => Ty::from_hir_path(db, module, path)?, | ||
145 | TypeRef::RawPtr(inner, mutability) => { | ||
146 | let inner_ty = Ty::from_hir(db, module, inner)?; | ||
147 | Ty::RawPtr(Arc::new(inner_ty), *mutability) | ||
148 | } | ||
149 | TypeRef::Array(_inner) => Ty::Unknown, // TODO | ||
150 | TypeRef::Slice(inner) => { | ||
151 | let inner_ty = Ty::from_hir(db, module, inner)?; | ||
152 | Ty::Slice(Arc::new(inner_ty)) | ||
153 | } | ||
154 | TypeRef::Reference(inner, mutability) => { | ||
155 | let inner_ty = Ty::from_hir(db, module, inner)?; | ||
156 | Ty::Ref(Arc::new(inner_ty), *mutability) | ||
157 | } | ||
158 | TypeRef::Placeholder => Ty::Unknown, // TODO | ||
159 | TypeRef::Fn(params) => { | ||
160 | let mut inner_tys = params | ||
161 | .iter() | ||
162 | .map(|tr| Ty::from_hir(db, module, tr)) | ||
163 | .collect::<Cancelable<Vec<_>>>()?; | ||
164 | let return_ty = inner_tys | ||
165 | .pop() | ||
166 | .expect("TypeRef::Fn should always have at least return type"); | ||
167 | let sig = FnSig { | ||
168 | input: inner_tys, | ||
169 | output: return_ty, | ||
170 | }; | ||
171 | Ty::FnPtr(Arc::new(sig)) | ||
172 | } | ||
173 | TypeRef::Error => Ty::Unknown, | ||
174 | }) | ||
175 | } | ||
176 | |||
177 | pub(crate) fn from_hir_path( | ||
178 | db: &impl HirDatabase, | ||
179 | module: &Module, | ||
180 | path: &Path, | ||
163 | ) -> Cancelable<Self> { | 181 | ) -> Cancelable<Self> { |
164 | let path = if let Some(p) = Path::from_ast(path) { | ||
165 | p | ||
166 | } else { | ||
167 | return Ok(Ty::Unknown); | ||
168 | }; | ||
169 | if path.is_ident() { | 182 | if path.is_ident() { |
170 | let name = &path.segments[0]; | 183 | let name = &path.segments[0]; |
171 | if let Some(int_ty) = primitive::IntTy::from_string(&name) { | 184 | if let Some(int_ty) = primitive::IntTy::from_string(&name) { |
@@ -187,50 +200,22 @@ impl Ty { | |||
187 | Ok(ty) | 200 | Ok(ty) |
188 | } | 201 | } |
189 | 202 | ||
190 | pub(crate) fn new_opt( | 203 | // TODO: These should not be necessary long-term, since everything will work on HIR |
204 | pub(crate) fn from_ast_opt( | ||
191 | db: &impl HirDatabase, | 205 | db: &impl HirDatabase, |
192 | module: &Module, | 206 | module: &Module, |
193 | node: Option<ast::TypeRef>, | 207 | node: Option<ast::TypeRef>, |
194 | ) -> Cancelable<Self> { | 208 | ) -> Cancelable<Self> { |
195 | node.map(|n| Ty::new(db, module, n)) | 209 | node.map(|n| Ty::from_ast(db, module, n)) |
196 | .unwrap_or(Ok(Ty::Unknown)) | 210 | .unwrap_or(Ok(Ty::Unknown)) |
197 | } | 211 | } |
198 | 212 | ||
199 | pub(crate) fn new( | 213 | pub(crate) fn from_ast( |
200 | db: &impl HirDatabase, | 214 | db: &impl HirDatabase, |
201 | module: &Module, | 215 | module: &Module, |
202 | node: ast::TypeRef, | 216 | node: ast::TypeRef, |
203 | ) -> Cancelable<Self> { | 217 | ) -> Cancelable<Self> { |
204 | use ra_syntax::ast::TypeRef::*; | 218 | Ty::from_hir(db, module, &TypeRef::from_ast(node)) |
205 | Ok(match node { | ||
206 | ParenType(inner) => Ty::new_opt(db, module, inner.type_ref())?, | ||
207 | TupleType(_inner) => Ty::Unknown, // TODO | ||
208 | NeverType(..) => Ty::Never, | ||
209 | PathType(inner) => { | ||
210 | if let Some(path) = inner.path() { | ||
211 | Ty::new_from_ast_path(db, module, path)? | ||
212 | } else { | ||
213 | Ty::Unknown | ||
214 | } | ||
215 | } | ||
216 | PointerType(inner) => { | ||
217 | let inner_ty = Ty::new_opt(db, module, inner.type_ref())?; | ||
218 | let mutability = Mutability::from_mutable(inner.is_mut()); | ||
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 | } | ||
228 | PlaceholderType(_inner) => Ty::Unknown, // TODO | ||
229 | FnPointerType(_inner) => Ty::Unknown, // TODO | ||
230 | ForType(_inner) => Ty::Unknown, // TODO | ||
231 | ImplTraitType(_inner) => Ty::Unknown, // TODO | ||
232 | DynTraitType(_inner) => Ty::Unknown, // TODO | ||
233 | }) | ||
234 | } | 219 | } |
235 | 220 | ||
236 | pub fn unit() -> Self { | 221 | pub fn unit() -> Self { |
@@ -280,11 +265,11 @@ pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | |||
280 | .param_list() | 265 | .param_list() |
281 | .map(|pl| { | 266 | .map(|pl| { |
282 | pl.params() | 267 | pl.params() |
283 | .map(|p| Ty::new_opt(db, &module, p.type_ref())) | 268 | .map(|p| Ty::from_ast_opt(db, &module, p.type_ref())) |
284 | .collect() | 269 | .collect() |
285 | }) | 270 | }) |
286 | .unwrap_or_else(|| Ok(Vec::new()))?; | 271 | .unwrap_or_else(|| Ok(Vec::new()))?; |
287 | let output = Ty::new_opt(db, &module, node.ret_type().and_then(|rt| rt.type_ref()))?; | 272 | let output = Ty::from_ast_opt(db, &module, node.ret_type().and_then(|rt| rt.type_ref()))?; |
288 | let sig = FnSig { input, output }; | 273 | let sig = FnSig { input, output }; |
289 | Ok(Ty::FnPtr(Arc::new(sig))) | 274 | Ok(Ty::FnPtr(Arc::new(sig))) |
290 | } | 275 | } |
@@ -390,7 +375,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
390 | }; | 375 | }; |
391 | 376 | ||
392 | // resolve in module | 377 | // resolve in module |
393 | let resolved = ctry!(self.module.resolve_path(self.db, path)?.take_values()); | 378 | let resolved = ctry!(self.module.resolve_path(self.db, &path)?.take_values()); |
394 | let ty = self.db.type_for_def(resolved)?; | 379 | let ty = self.db.type_for_def(resolved)?; |
395 | // TODO we will need to add type variables for type parameters etc. here | 380 | // TODO we will need to add type variables for type parameters etc. here |
396 | Ok(Some(ty)) | 381 | Ok(Some(ty)) |
@@ -405,7 +390,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
405 | } else { | 390 | } else { |
406 | return Ok((Ty::Unknown, None)); | 391 | return Ok((Ty::Unknown, None)); |
407 | }; | 392 | }; |
408 | let def_id = if let Some(def_id) = self.module.resolve_path(self.db, path)?.take_types() { | 393 | let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path)?.take_types() { |
409 | def_id | 394 | def_id |
410 | } else { | 395 | } else { |
411 | return Ok((Ty::Unknown, None)); | 396 | return Ok((Ty::Unknown, None)); |
@@ -575,7 +560,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
575 | } | 560 | } |
576 | ast::Expr::CastExpr(e) => { | 561 | ast::Expr::CastExpr(e) => { |
577 | let _inner_ty = self.infer_expr_opt(e.expr())?; | 562 | let _inner_ty = self.infer_expr_opt(e.expr())?; |
578 | let cast_ty = Ty::new_opt(self.db, &self.module, e.type_ref())?; | 563 | let cast_ty = Ty::from_ast_opt(self.db, &self.module, e.type_ref())?; |
579 | // TODO do the coercion... | 564 | // TODO do the coercion... |
580 | cast_ty | 565 | cast_ty |
581 | } | 566 | } |
@@ -620,7 +605,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
620 | for stmt in node.statements() { | 605 | for stmt in node.statements() { |
621 | match stmt { | 606 | match stmt { |
622 | ast::Stmt::LetStmt(stmt) => { | 607 | ast::Stmt::LetStmt(stmt) => { |
623 | let decl_ty = Ty::new_opt(self.db, &self.module, stmt.type_ref())?; | 608 | let decl_ty = Ty::from_ast_opt(self.db, &self.module, stmt.type_ref())?; |
624 | let ty = if let Some(expr) = stmt.initializer() { | 609 | let ty = if let Some(expr) = stmt.initializer() { |
625 | // TODO pass expectation | 610 | // TODO pass expectation |
626 | let expr_ty = self.infer_expr(expr)?; | 611 | let expr_ty = self.infer_expr(expr)?; |
@@ -665,7 +650,7 @@ pub fn infer(db: &impl HirDatabase, function: Function) -> Cancelable<InferenceR | |||
665 | continue; | 650 | continue; |
666 | }; | 651 | }; |
667 | if let Some(type_ref) = param.type_ref() { | 652 | if let Some(type_ref) = param.type_ref() { |
668 | let ty = Ty::new(db, &ctx.module, type_ref)?; | 653 | let ty = Ty::from_ast(db, &ctx.module, type_ref)?; |
669 | ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty); | 654 | ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty); |
670 | } else { | 655 | } else { |
671 | // TODO self param | 656 | // TODO self param |
diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs new file mode 100644 index 000000000..ae163313f --- /dev/null +++ b/crates/ra_hir/src/type_ref.rs | |||
@@ -0,0 +1,110 @@ | |||
1 | //! HIR for references to types. Paths in these are not yet resolved. They can | ||
2 | //! be directly created from an ast::TypeRef, without further queries. | ||
3 | |||
4 | use ra_syntax::ast; | ||
5 | |||
6 | use crate::Path; | ||
7 | |||
8 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||
9 | pub enum Mutability { | ||
10 | Shared, | ||
11 | Mut, | ||
12 | } | ||
13 | |||
14 | impl Mutability { | ||
15 | pub fn from_mutable(mutable: bool) -> Mutability { | ||
16 | if mutable { | ||
17 | Mutability::Mut | ||
18 | } else { | ||
19 | Mutability::Shared | ||
20 | } | ||
21 | } | ||
22 | |||
23 | pub fn as_keyword_for_ref(self) -> &'static str { | ||
24 | match self { | ||
25 | Mutability::Shared => "", | ||
26 | Mutability::Mut => "mut ", | ||
27 | } | ||
28 | } | ||
29 | |||
30 | pub fn as_keyword_for_ptr(self) -> &'static str { | ||
31 | match self { | ||
32 | Mutability::Shared => "const ", | ||
33 | Mutability::Mut => "mut ", | ||
34 | } | ||
35 | } | ||
36 | } | ||
37 | |||
38 | /// Compare ty::Ty | ||
39 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | ||
40 | pub enum TypeRef { | ||
41 | Never, | ||
42 | Placeholder, | ||
43 | Tuple(Vec<TypeRef>), | ||
44 | Path(Path), | ||
45 | RawPtr(Box<TypeRef>, Mutability), | ||
46 | Reference(Box<TypeRef>, Mutability), | ||
47 | Array(Box<TypeRef> /*, Expr*/), | ||
48 | Slice(Box<TypeRef>), | ||
49 | /// A fn pointer. Last element of the vector is the return type. | ||
50 | Fn(Vec<TypeRef>), | ||
51 | // For | ||
52 | // ImplTrait, | ||
53 | // DynTrait, | ||
54 | Error, | ||
55 | } | ||
56 | |||
57 | impl TypeRef { | ||
58 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. | ||
59 | pub(crate) fn from_ast(node: ast::TypeRef) -> Self { | ||
60 | use ra_syntax::ast::TypeRef::*; | ||
61 | match node { | ||
62 | ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()), | ||
63 | TupleType(inner) => TypeRef::Tuple(inner.fields().map(TypeRef::from_ast).collect()), | ||
64 | NeverType(..) => TypeRef::Never, | ||
65 | PathType(inner) => inner | ||
66 | .path() | ||
67 | .and_then(Path::from_ast) | ||
68 | .map(TypeRef::Path) | ||
69 | .unwrap_or(TypeRef::Error), | ||
70 | PointerType(inner) => { | ||
71 | let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); | ||
72 | let mutability = Mutability::from_mutable(inner.is_mut()); | ||
73 | TypeRef::RawPtr(Box::new(inner_ty), mutability) | ||
74 | } | ||
75 | ArrayType(inner) => TypeRef::Array(Box::new(TypeRef::from_ast_opt(inner.type_ref()))), | ||
76 | SliceType(inner) => TypeRef::Slice(Box::new(TypeRef::from_ast_opt(inner.type_ref()))), | ||
77 | ReferenceType(inner) => { | ||
78 | let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); | ||
79 | let mutability = Mutability::from_mutable(inner.is_mut()); | ||
80 | TypeRef::Reference(Box::new(inner_ty), mutability) | ||
81 | } | ||
82 | PlaceholderType(_inner) => TypeRef::Placeholder, | ||
83 | FnPointerType(inner) => { | ||
84 | let ret_ty = TypeRef::from_ast_opt(inner.ret_type().and_then(|rt| rt.type_ref())); | ||
85 | let mut params = if let Some(pl) = inner.param_list() { | ||
86 | pl.params() | ||
87 | .map(|p| p.type_ref()) | ||
88 | .map(TypeRef::from_ast_opt) | ||
89 | .collect() | ||
90 | } else { | ||
91 | Vec::new() | ||
92 | }; | ||
93 | params.push(ret_ty); | ||
94 | TypeRef::Fn(params) | ||
95 | } | ||
96 | // for types are close enough for our purposes to the inner type for now... | ||
97 | ForType(inner) => TypeRef::from_ast_opt(inner.type_ref()), | ||
98 | ImplTraitType(_inner) => TypeRef::Error, | ||
99 | DynTraitType(_inner) => TypeRef::Error, | ||
100 | } | ||
101 | } | ||
102 | |||
103 | fn from_ast_opt(node: Option<ast::TypeRef>) -> Self { | ||
104 | if let Some(node) = node { | ||
105 | TypeRef::from_ast(node) | ||
106 | } else { | ||
107 | TypeRef::Error | ||
108 | } | ||
109 | } | ||
110 | } | ||
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 535dcc975..c22e026cf 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -131,7 +131,15 @@ impl<R: TreeRoot<RaTypes>> ArrayTypeNode<R> { | |||
131 | } | 131 | } |
132 | 132 | ||
133 | 133 | ||
134 | impl<'a> ArrayType<'a> {} | 134 | impl<'a> ArrayType<'a> { |
135 | pub fn type_ref(self) -> Option<TypeRef<'a>> { | ||
136 | super::child_opt(self) | ||
137 | } | ||
138 | |||
139 | pub fn expr(self) -> Option<Expr<'a>> { | ||
140 | super::child_opt(self) | ||
141 | } | ||
142 | } | ||
135 | 143 | ||
136 | // Attr | 144 | // Attr |
137 | #[derive(Debug, Clone, Copy,)] | 145 | #[derive(Debug, Clone, Copy,)] |
@@ -1258,7 +1266,15 @@ impl<R: TreeRoot<RaTypes>> FnPointerTypeNode<R> { | |||
1258 | } | 1266 | } |
1259 | 1267 | ||
1260 | 1268 | ||
1261 | impl<'a> FnPointerType<'a> {} | 1269 | impl<'a> FnPointerType<'a> { |
1270 | pub fn param_list(self) -> Option<ParamList<'a>> { | ||
1271 | super::child_opt(self) | ||
1272 | } | ||
1273 | |||
1274 | pub fn ret_type(self) -> Option<RetType<'a>> { | ||
1275 | super::child_opt(self) | ||
1276 | } | ||
1277 | } | ||
1262 | 1278 | ||
1263 | // ForExpr | 1279 | // ForExpr |
1264 | #[derive(Debug, Clone, Copy,)] | 1280 | #[derive(Debug, Clone, Copy,)] |
@@ -1341,7 +1357,11 @@ impl<R: TreeRoot<RaTypes>> ForTypeNode<R> { | |||
1341 | } | 1357 | } |
1342 | 1358 | ||
1343 | 1359 | ||
1344 | impl<'a> ForType<'a> {} | 1360 | impl<'a> ForType<'a> { |
1361 | pub fn type_ref(self) -> Option<TypeRef<'a>> { | ||
1362 | super::child_opt(self) | ||
1363 | } | ||
1364 | } | ||
1345 | 1365 | ||
1346 | // IfExpr | 1366 | // IfExpr |
1347 | #[derive(Debug, Clone, Copy,)] | 1367 | #[derive(Debug, Clone, Copy,)] |
@@ -3490,7 +3510,11 @@ impl<R: TreeRoot<RaTypes>> SliceTypeNode<R> { | |||
3490 | } | 3510 | } |
3491 | 3511 | ||
3492 | 3512 | ||
3493 | impl<'a> SliceType<'a> {} | 3513 | impl<'a> SliceType<'a> { |
3514 | pub fn type_ref(self) -> Option<TypeRef<'a>> { | ||
3515 | super::child_opt(self) | ||
3516 | } | ||
3517 | } | ||
3494 | 3518 | ||
3495 | // SourceFile | 3519 | // SourceFile |
3496 | #[derive(Debug, Clone, Copy,)] | 3520 | #[derive(Debug, Clone, Copy,)] |
@@ -4025,7 +4049,11 @@ impl<R: TreeRoot<RaTypes>> TupleTypeNode<R> { | |||
4025 | } | 4049 | } |
4026 | 4050 | ||
4027 | 4051 | ||
4028 | impl<'a> TupleType<'a> {} | 4052 | impl<'a> TupleType<'a> { |
4053 | pub fn fields(self) -> impl Iterator<Item = TypeRef<'a>> + 'a { | ||
4054 | super::children(self) | ||
4055 | } | ||
4056 | } | ||
4029 | 4057 | ||
4030 | // TypeDef | 4058 | // TypeDef |
4031 | #[derive(Debug, Clone, Copy,)] | 4059 | #[derive(Debug, Clone, Copy,)] |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 8b1bd6d1c..4bcff4e14 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -304,16 +304,16 @@ Grammar( | |||
304 | "ImplItem": (), | 304 | "ImplItem": (), |
305 | 305 | ||
306 | "ParenType": (options: ["TypeRef"]), | 306 | "ParenType": (options: ["TypeRef"]), |
307 | "TupleType": (), | 307 | "TupleType": ( collections: [["fields", "TypeRef"]] ), |
308 | "NeverType": (), | 308 | "NeverType": (), |
309 | "PathType": (options: ["Path"]), | 309 | "PathType": (options: ["Path"]), |
310 | "PointerType": (options: ["TypeRef"]), | 310 | "PointerType": (options: ["TypeRef"]), |
311 | "ArrayType": (), | 311 | "ArrayType": ( options: ["TypeRef", "Expr"] ), |
312 | "SliceType": (), | 312 | "SliceType": ( options: ["TypeRef"] ), |
313 | "ReferenceType": (options: ["TypeRef"]), | 313 | "ReferenceType": (options: ["TypeRef"]), |
314 | "PlaceholderType": (), | 314 | "PlaceholderType": (), |
315 | "FnPointerType": (), | 315 | "FnPointerType": (options: ["ParamList", "RetType"]), |
316 | "ForType": (), | 316 | "ForType": (options: ["TypeRef"]), |
317 | "ImplTraitType": (), | 317 | "ImplTraitType": (), |
318 | "DynTraitType": (), | 318 | "DynTraitType": (), |
319 | 319 | ||