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 /crates/ra_hir/src/ty.rs | |
parent | 2870effd5c69941bbf32a44c0ee6d9d42e0b038d (diff) |
Add a hir::TypeRef as an intermediate between ast::TypeRef and ty::Ty
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 139 |
1 files changed, 62 insertions, 77 deletions
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 |