diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 72 |
1 files changed, 46 insertions, 26 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index c759d4c8b..f86b749ec 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -17,7 +17,7 @@ use ra_syntax::{ | |||
17 | 17 | ||
18 | use crate::{Def, DefId, FnScopes, Module, Function, Path, db::HirDatabase}; | 18 | use crate::{Def, DefId, FnScopes, Module, Function, Path, db::HirDatabase}; |
19 | 19 | ||
20 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | 20 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
21 | pub enum Ty { | 21 | pub enum Ty { |
22 | /// The primitive boolean type. Written as `bool`. | 22 | /// The primitive boolean type. Written as `bool`. |
23 | Bool, | 23 | Bool, |
@@ -35,8 +35,15 @@ pub enum Ty { | |||
35 | /// A primitive floating-point type. For example, `f64`. | 35 | /// A primitive floating-point type. For example, `f64`. |
36 | Float(primitive::FloatTy), | 36 | Float(primitive::FloatTy), |
37 | 37 | ||
38 | // Structures, enumerations and unions. | 38 | /// Structures, enumerations and unions. |
39 | // Adt(AdtDef, Substs), | 39 | Adt { |
40 | /// The DefId of the struct/enum. | ||
41 | def_id: DefId, | ||
42 | /// The name, for displaying. | ||
43 | name: SmolStr, | ||
44 | // later we'll need generic substitutions here | ||
45 | }, | ||
46 | |||
40 | /// The pointee of a string slice. Written as `str`. | 47 | /// The pointee of a string slice. Written as `str`. |
41 | Str, | 48 | Str, |
42 | 49 | ||
@@ -107,45 +114,48 @@ pub enum Ty { | |||
107 | 114 | ||
108 | type TyRef = Arc<Ty>; | 115 | type TyRef = Arc<Ty>; |
109 | 116 | ||
110 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | 117 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
111 | pub struct FnSig { | 118 | pub struct FnSig { |
112 | input: Vec<Ty>, | 119 | input: Vec<Ty>, |
113 | output: Ty, | 120 | output: Ty, |
114 | } | 121 | } |
115 | 122 | ||
116 | impl Ty { | 123 | impl Ty { |
117 | pub fn new(_db: &impl HirDatabase, node: ast::TypeRef) -> Cancelable<Self> { | 124 | pub(crate) fn new( |
125 | db: &impl HirDatabase, | ||
126 | module: &Module, | ||
127 | node: ast::TypeRef, | ||
128 | ) -> Cancelable<Self> { | ||
118 | use ra_syntax::ast::TypeRef::*; | 129 | use ra_syntax::ast::TypeRef::*; |
119 | Ok(match node { | 130 | Ok(match node { |
120 | ParenType(_inner) => Ty::Unknown, // TODO | 131 | ParenType(_inner) => Ty::Unknown, // TODO |
121 | TupleType(_inner) => Ty::Unknown, // TODO | 132 | TupleType(_inner) => Ty::Unknown, // TODO |
122 | NeverType(..) => Ty::Never, | 133 | NeverType(..) => Ty::Never, |
123 | PathType(inner) => { | 134 | PathType(inner) => { |
124 | let path = if let Some(p) = inner.path() { | 135 | let path = if let Some(p) = inner.path().and_then(Path::from_ast) { |
125 | p | 136 | p |
126 | } else { | 137 | } else { |
127 | return Ok(Ty::Unknown); | 138 | return Ok(Ty::Unknown); |
128 | }; | 139 | }; |
129 | if path.qualifier().is_none() { | 140 | if path.is_ident() { |
130 | let name = path | 141 | let name = &path.segments[0]; |
131 | .segment() | ||
132 | .and_then(|s| s.name_ref()) | ||
133 | .map(|n| n.text()) | ||
134 | .unwrap_or(SmolStr::new("")); | ||
135 | if let Some(int_ty) = primitive::IntTy::from_string(&name) { | 142 | if let Some(int_ty) = primitive::IntTy::from_string(&name) { |
136 | Ty::Int(int_ty) | 143 | return Ok(Ty::Int(int_ty)); |
137 | } else if let Some(uint_ty) = primitive::UintTy::from_string(&name) { | 144 | } else if let Some(uint_ty) = primitive::UintTy::from_string(&name) { |
138 | Ty::Uint(uint_ty) | 145 | return Ok(Ty::Uint(uint_ty)); |
139 | } else if let Some(float_ty) = primitive::FloatTy::from_string(&name) { | 146 | } else if let Some(float_ty) = primitive::FloatTy::from_string(&name) { |
140 | Ty::Float(float_ty) | 147 | return Ok(Ty::Float(float_ty)); |
141 | } else { | ||
142 | // TODO | ||
143 | Ty::Unknown | ||
144 | } | 148 | } |
145 | } else { | ||
146 | // TODO | ||
147 | Ty::Unknown | ||
148 | } | 149 | } |
150 | |||
151 | // Resolve in module (in type namespace) | ||
152 | let resolved = if let Some(r) = module.resolve_path(db, path)? { | ||
153 | r | ||
154 | } else { | ||
155 | return Ok(Ty::Unknown); | ||
156 | }; | ||
157 | let ty = db.type_for_def(resolved)?; | ||
158 | ty | ||
149 | } | 159 | } |
150 | PointerType(_inner) => Ty::Unknown, // TODO | 160 | PointerType(_inner) => Ty::Unknown, // TODO |
151 | ArrayType(_inner) => Ty::Unknown, // TODO | 161 | ArrayType(_inner) => Ty::Unknown, // TODO |
@@ -189,6 +199,7 @@ impl fmt::Display for Ty { | |||
189 | } | 199 | } |
190 | write!(f, ") -> {}", sig.output) | 200 | write!(f, ") -> {}", sig.output) |
191 | } | 201 | } |
202 | Ty::Adt { name, .. } => write!(f, "{}", name), | ||
192 | Ty::Unknown => write!(f, "[unknown]"), | 203 | Ty::Unknown => write!(f, "[unknown]"), |
193 | } | 204 | } |
194 | } | 205 | } |
@@ -196,6 +207,7 @@ impl fmt::Display for Ty { | |||
196 | 207 | ||
197 | pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | 208 | pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { |
198 | let syntax = f.syntax(db); | 209 | let syntax = f.syntax(db); |
210 | let module = f.module(db)?; | ||
199 | let node = syntax.borrowed(); | 211 | let node = syntax.borrowed(); |
200 | // TODO we ignore type parameters for now | 212 | // TODO we ignore type parameters for now |
201 | let input = node | 213 | let input = node |
@@ -204,7 +216,7 @@ pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | |||
204 | pl.params() | 216 | pl.params() |
205 | .map(|p| { | 217 | .map(|p| { |
206 | p.type_ref() | 218 | p.type_ref() |
207 | .map(|t| Ty::new(db, t)) | 219 | .map(|t| Ty::new(db, &module, t)) |
208 | .unwrap_or(Ok(Ty::Unknown)) | 220 | .unwrap_or(Ok(Ty::Unknown)) |
209 | }) | 221 | }) |
210 | .collect() | 222 | .collect() |
@@ -213,7 +225,7 @@ pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | |||
213 | let output = node | 225 | let output = node |
214 | .ret_type() | 226 | .ret_type() |
215 | .and_then(|rt| rt.type_ref()) | 227 | .and_then(|rt| rt.type_ref()) |
216 | .map(|t| Ty::new(db, t)) | 228 | .map(|t| Ty::new(db, &module, t)) |
217 | .unwrap_or(Ok(Ty::Unknown))?; | 229 | .unwrap_or(Ok(Ty::Unknown))?; |
218 | let sig = FnSig { input, output }; | 230 | let sig = FnSig { input, output }; |
219 | Ok(Ty::FnPtr(Arc::new(sig))) | 231 | Ok(Ty::FnPtr(Arc::new(sig))) |
@@ -232,6 +244,14 @@ pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { | |||
232 | Ok(Ty::Unknown) | 244 | Ok(Ty::Unknown) |
233 | } | 245 | } |
234 | Def::Function(f) => type_for_fn(db, f), | 246 | Def::Function(f) => type_for_fn(db, f), |
247 | Def::Struct(s) => Ok(Ty::Adt { | ||
248 | def_id, | ||
249 | name: s.name(db)?, | ||
250 | }), | ||
251 | Def::Enum(e) => Ok(Ty::Adt { | ||
252 | def_id, | ||
253 | name: e.name(db)?, | ||
254 | }), | ||
235 | Def::Item => { | 255 | Def::Item => { |
236 | log::debug!("trying to get type for item of unknown type {:?}", def_id); | 256 | log::debug!("trying to get type for item of unknown type {:?}", def_id); |
237 | Ok(Ty::Unknown) | 257 | Ok(Ty::Unknown) |
@@ -492,7 +512,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
492 | }; | 512 | }; |
493 | let cast_ty = e | 513 | let cast_ty = e |
494 | .type_ref() | 514 | .type_ref() |
495 | .map(|t| Ty::new(self.db, t)) | 515 | .map(|t| Ty::new(self.db, &self.module, t)) |
496 | .unwrap_or(Ok(Ty::Unknown))?; | 516 | .unwrap_or(Ok(Ty::Unknown))?; |
497 | // TODO do the coercion... | 517 | // TODO do the coercion... |
498 | cast_ty | 518 | cast_ty |
@@ -526,7 +546,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
526 | match stmt { | 546 | match stmt { |
527 | ast::Stmt::LetStmt(stmt) => { | 547 | ast::Stmt::LetStmt(stmt) => { |
528 | let decl_ty = if let Some(type_ref) = stmt.type_ref() { | 548 | let decl_ty = if let Some(type_ref) = stmt.type_ref() { |
529 | Ty::new(self.db, type_ref)? | 549 | Ty::new(self.db, &self.module, type_ref)? |
530 | } else { | 550 | } else { |
531 | Ty::Unknown | 551 | Ty::Unknown |
532 | }; | 552 | }; |
@@ -576,7 +596,7 @@ pub fn infer(db: &impl HirDatabase, function: Function) -> Cancelable<InferenceR | |||
576 | continue; | 596 | continue; |
577 | }; | 597 | }; |
578 | if let Some(type_ref) = param.type_ref() { | 598 | if let Some(type_ref) = param.type_ref() { |
579 | let ty = Ty::new(db, type_ref)?; | 599 | let ty = Ty::new(db, &ctx.module, type_ref)?; |
580 | ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty); | 600 | ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty); |
581 | } else { | 601 | } else { |
582 | // TODO self param | 602 | // TODO self param |