aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2018-12-25 20:14:13 +0000
committerFlorian Diebold <[email protected]>2018-12-25 20:14:13 +0000
commitcdca39706121b2d1734a94938a2372da881e10c6 (patch)
treed3f9687371eb1a7004c4694c59445af388eb1876 /crates
parent2870effd5c69941bbf32a44c0ee6d9d42e0b038d (diff)
Add a hir::TypeRef as an intermediate between ast::TypeRef and ty::Ty
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_analysis/src/completion/complete_path.rs2
-rw-r--r--crates/ra_hir/src/adt.rs4
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/module.rs4
-rw-r--r--crates/ra_hir/src/module/nameres.rs2
-rw-r--r--crates/ra_hir/src/path.rs4
-rw-r--r--crates/ra_hir/src/ty.rs139
-rw-r--r--crates/ra_hir/src/type_ref.rs110
-rw-r--r--crates/ra_syntax/src/ast/generated.rs38
-rw-r--r--crates/ra_syntax/src/grammar.ron10
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;
26mod module; 26mod module;
27mod function; 27mod function;
28mod adt; 28mod adt;
29mod type_ref;
29mod ty; 30mod ty;
30 31
31use std::ops::Index; 32use 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 @@
1use ra_syntax::{SmolStr, ast, AstNode, TextRange}; 1use ra_syntax::{SmolStr, ast, AstNode, TextRange};
2 2
3#[derive(Debug, Clone, PartialEq, Eq)] 3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4pub struct Path { 4pub 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)]
10pub enum PathKind { 10pub 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)]
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
54#[derive(Clone, PartialEq, Eq, Hash, Debug)] 25#[derive(Clone, PartialEq, Eq, Hash, Debug)]
55pub enum Ty { 26pub 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
158impl Ty { 129impl 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
4use ra_syntax::ast;
5
6use crate::Path;
7
8#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
9pub enum Mutability {
10 Shared,
11 Mut,
12}
13
14impl 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)]
40pub 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
57impl 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
134impl<'a> ArrayType<'a> {} 134impl<'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
1261impl<'a> FnPointerType<'a> {} 1269impl<'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
1344impl<'a> ForType<'a> {} 1360impl<'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
3493impl<'a> SliceType<'a> {} 3513impl<'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
4028impl<'a> TupleType<'a> {} 4052impl<'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