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.rs72
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
18use crate::{Def, DefId, FnScopes, Module, Function, Path, db::HirDatabase}; 18use 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)]
21pub enum Ty { 21pub 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
108type TyRef = Arc<Ty>; 115type TyRef = Arc<Ty>;
109 116
110#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 117#[derive(Clone, PartialEq, Eq, Hash, Debug)]
111pub struct FnSig { 118pub struct FnSig {
112 input: Vec<Ty>, 119 input: Vec<Ty>,
113 output: Ty, 120 output: Ty,
114} 121}
115 122
116impl Ty { 123impl 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
197pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { 208pub 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