aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs139
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)]
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