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.rs448
1 files changed, 271 insertions, 177 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index c759d4c8b..67b523c2c 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -11,13 +11,18 @@ use rustc_hash::{FxHashMap};
11use ra_db::{LocalSyntaxPtr, Cancelable}; 11use ra_db::{LocalSyntaxPtr, Cancelable};
12use ra_syntax::{ 12use ra_syntax::{
13 SmolStr, 13 SmolStr,
14 ast::{self, AstNode, LoopBodyOwner, ArgListOwner}, 14 ast::{self, AstNode, LoopBodyOwner, ArgListOwner, PrefixOp},
15 SyntaxNodeRef 15 SyntaxNodeRef
16}; 16};
17 17
18use crate::{Def, DefId, FnScopes, Module, Function, Path, db::HirDatabase}; 18use crate::{
19 Def, DefId, FnScopes, Module, Function, Struct, Enum, Path,
20 db::HirDatabase,
21 adt::VariantData,
22 type_ref::{TypeRef, Mutability},
23};
19 24
20#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 25#[derive(Clone, PartialEq, Eq, Hash, Debug)]
21pub enum Ty { 26pub enum Ty {
22 /// The primitive boolean type. Written as `bool`. 27 /// The primitive boolean type. Written as `bool`.
23 Bool, 28 Bool,
@@ -35,8 +40,15 @@ pub enum Ty {
35 /// A primitive floating-point type. For example, `f64`. 40 /// A primitive floating-point type. For example, `f64`.
36 Float(primitive::FloatTy), 41 Float(primitive::FloatTy),
37 42
38 // Structures, enumerations and unions. 43 /// Structures, enumerations and unions.
39 // Adt(AdtDef, Substs), 44 Adt {
45 /// The DefId of the struct/enum.
46 def_id: DefId,
47 /// The name, for displaying.
48 name: SmolStr,
49 // later we'll need generic substitutions here
50 },
51
40 /// The pointee of a string slice. Written as `str`. 52 /// The pointee of a string slice. Written as `str`.
41 Str, 53 Str,
42 54
@@ -45,12 +57,13 @@ pub enum Ty {
45 /// The pointee of an array slice. Written as `[T]`. 57 /// The pointee of an array slice. Written as `[T]`.
46 Slice(TyRef), 58 Slice(TyRef),
47 59
48 // A raw pointer. Written as `*mut T` or `*const T` 60 /// A raw pointer. Written as `*mut T` or `*const T`
49 // RawPtr(TypeAndMut<'tcx>), 61 RawPtr(TyRef, Mutability),
62
63 /// A reference; a pointer with an associated lifetime. Written as
64 /// `&'a mut T` or `&'a T`.
65 Ref(TyRef, Mutability),
50 66
51 // A reference; a pointer with an associated lifetime. Written as
52 // `&'a mut T` or `&'a T`.
53 // Ref(Ty<'tcx>, hir::Mutability),
54 /// A pointer to a function. Written as `fn() -> i32`. 67 /// A pointer to a function. Written as `fn() -> i32`.
55 /// 68 ///
56 /// For example the type of `bar` here: 69 /// For example the type of `bar` here:
@@ -107,58 +120,104 @@ pub enum Ty {
107 120
108type TyRef = Arc<Ty>; 121type TyRef = Arc<Ty>;
109 122
110#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 123#[derive(Clone, PartialEq, Eq, Hash, Debug)]
111pub struct FnSig { 124pub struct FnSig {
112 input: Vec<Ty>, 125 input: Vec<Ty>,
113 output: Ty, 126 output: Ty,
114} 127}
115 128
116impl Ty { 129impl Ty {
117 pub fn new(_db: &impl HirDatabase, node: ast::TypeRef) -> Cancelable<Self> { 130 pub(crate) fn from_hir(
118 use ra_syntax::ast::TypeRef::*; 131 db: &impl HirDatabase,
119 Ok(match node { 132 module: &Module,
120 ParenType(_inner) => Ty::Unknown, // TODO 133 type_ref: &TypeRef,
121 TupleType(_inner) => Ty::Unknown, // TODO 134 ) -> Cancelable<Self> {
122 NeverType(..) => Ty::Never, 135 Ok(match type_ref {
123 PathType(inner) => { 136 TypeRef::Never => Ty::Never,
124 let path = if let Some(p) = inner.path() { 137 TypeRef::Tuple(inner) => {
125 p 138 let inner_tys = inner
126 } else { 139 .iter()
127 return Ok(Ty::Unknown); 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,
128 }; 170 };
129 if path.qualifier().is_none() { 171 Ty::FnPtr(Arc::new(sig))
130 let name = path
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) {
136 Ty::Int(int_ty)
137 } else if let Some(uint_ty) = primitive::UintTy::from_string(&name) {
138 Ty::Uint(uint_ty)
139 } else if let Some(float_ty) = primitive::FloatTy::from_string(&name) {
140 Ty::Float(float_ty)
141 } else {
142 // TODO
143 Ty::Unknown
144 }
145 } else {
146 // TODO
147 Ty::Unknown
148 }
149 } 172 }
150 PointerType(_inner) => Ty::Unknown, // TODO 173 TypeRef::Error => Ty::Unknown,
151 ArrayType(_inner) => Ty::Unknown, // TODO
152 SliceType(_inner) => Ty::Unknown, // TODO
153 ReferenceType(_inner) => Ty::Unknown, // TODO
154 PlaceholderType(_inner) => Ty::Unknown, // TODO
155 FnPointerType(_inner) => Ty::Unknown, // TODO
156 ForType(_inner) => Ty::Unknown, // TODO
157 ImplTraitType(_inner) => Ty::Unknown, // TODO
158 DynTraitType(_inner) => Ty::Unknown, // TODO
159 }) 174 })
160 } 175 }
161 176
177 pub(crate) fn from_hir_path(
178 db: &impl HirDatabase,
179 module: &Module,
180 path: &Path,
181 ) -> Cancelable<Self> {
182 if path.is_ident() {
183 let name = &path.segments[0];
184 if let Some(int_ty) = primitive::IntTy::from_string(&name) {
185 return Ok(Ty::Int(int_ty));
186 } else if let Some(uint_ty) = primitive::UintTy::from_string(&name) {
187 return Ok(Ty::Uint(uint_ty));
188 } else if let Some(float_ty) = primitive::FloatTy::from_string(&name) {
189 return Ok(Ty::Float(float_ty));
190 }
191 }
192
193 // Resolve in module (in type namespace)
194 let resolved = if let Some(r) = module.resolve_path(db, path)?.take_types() {
195 r
196 } else {
197 return Ok(Ty::Unknown);
198 };
199 let ty = db.type_for_def(resolved)?;
200 Ok(ty)
201 }
202
203 // TODO: These should not be necessary long-term, since everything will work on HIR
204 pub(crate) fn from_ast_opt(
205 db: &impl HirDatabase,
206 module: &Module,
207 node: Option<ast::TypeRef>,
208 ) -> Cancelable<Self> {
209 node.map(|n| Ty::from_ast(db, module, n))
210 .unwrap_or(Ok(Ty::Unknown))
211 }
212
213 pub(crate) fn from_ast(
214 db: &impl HirDatabase,
215 module: &Module,
216 node: ast::TypeRef,
217 ) -> Cancelable<Self> {
218 Ty::from_hir(db, module, &TypeRef::from_ast(node))
219 }
220
162 pub fn unit() -> Self { 221 pub fn unit() -> Self {
163 Ty::Tuple(Vec::new()) 222 Ty::Tuple(Vec::new())
164 } 223 }
@@ -174,6 +233,8 @@ impl fmt::Display for Ty {
174 Ty::Float(t) => write!(f, "{}", t.ty_to_string()), 233 Ty::Float(t) => write!(f, "{}", t.ty_to_string()),
175 Ty::Str => write!(f, "str"), 234 Ty::Str => write!(f, "str"),
176 Ty::Slice(t) => write!(f, "[{}]", t), 235 Ty::Slice(t) => write!(f, "[{}]", t),
236 Ty::RawPtr(t, m) => write!(f, "*{}{}", m.as_keyword_for_ptr(), t),
237 Ty::Ref(t, m) => write!(f, "&{}{}", m.as_keyword_for_ref(), t),
177 Ty::Never => write!(f, "!"), 238 Ty::Never => write!(f, "!"),
178 Ty::Tuple(ts) => { 239 Ty::Tuple(ts) => {
179 write!(f, "(")?; 240 write!(f, "(")?;
@@ -189,6 +250,7 @@ impl fmt::Display for Ty {
189 } 250 }
190 write!(f, ") -> {}", sig.output) 251 write!(f, ") -> {}", sig.output)
191 } 252 }
253 Ty::Adt { name, .. } => write!(f, "{}", name),
192 Ty::Unknown => write!(f, "[unknown]"), 254 Ty::Unknown => write!(f, "[unknown]"),
193 } 255 }
194 } 256 }
@@ -196,34 +258,40 @@ impl fmt::Display for Ty {
196 258
197pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { 259pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> {
198 let syntax = f.syntax(db); 260 let syntax = f.syntax(db);
261 let module = f.module(db)?;
199 let node = syntax.borrowed(); 262 let node = syntax.borrowed();
200 // TODO we ignore type parameters for now 263 // TODO we ignore type parameters for now
201 let input = node 264 let input = node
202 .param_list() 265 .param_list()
203 .map(|pl| { 266 .map(|pl| {
204 pl.params() 267 pl.params()
205 .map(|p| { 268 .map(|p| Ty::from_ast_opt(db, &module, p.type_ref()))
206 p.type_ref()
207 .map(|t| Ty::new(db, t))
208 .unwrap_or(Ok(Ty::Unknown))
209 })
210 .collect() 269 .collect()
211 }) 270 })
212 .unwrap_or_else(|| Ok(Vec::new()))?; 271 .unwrap_or_else(|| Ok(Vec::new()))?;
213 let output = node 272 let output = Ty::from_ast_opt(db, &module, node.ret_type().and_then(|rt| rt.type_ref()))?;
214 .ret_type()
215 .and_then(|rt| rt.type_ref())
216 .map(|t| Ty::new(db, t))
217 .unwrap_or(Ok(Ty::Unknown))?;
218 let sig = FnSig { input, output }; 273 let sig = FnSig { input, output };
219 Ok(Ty::FnPtr(Arc::new(sig))) 274 Ok(Ty::FnPtr(Arc::new(sig)))
220} 275}
221 276
222// TODO this should probably be per namespace (i.e. types vs. values), since for 277pub fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Cancelable<Ty> {
223// a tuple struct `struct Foo(Bar)`, Foo has function type as a value, but 278 Ok(Ty::Adt {
224// defines the struct type Foo when used in the type namespace. rustc has a 279 def_id: s.def_id(),
225// separate DefId for the constructor, but with the current DefId approach, that 280 name: s
226// seems complicated. 281 .name(db)?
282 .unwrap_or_else(|| SmolStr::new("[unnamed struct]")),
283 })
284}
285
286pub fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Cancelable<Ty> {
287 Ok(Ty::Adt {
288 def_id: s.def_id(),
289 name: s
290 .name(db)?
291 .unwrap_or_else(|| SmolStr::new("[unnamed enum]")),
292 })
293}
294
227pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { 295pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> {
228 let def = def_id.resolve(db)?; 296 let def = def_id.resolve(db)?;
229 match def { 297 match def {
@@ -232,6 +300,8 @@ pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> {
232 Ok(Ty::Unknown) 300 Ok(Ty::Unknown)
233 } 301 }
234 Def::Function(f) => type_for_fn(db, f), 302 Def::Function(f) => type_for_fn(db, f),
303 Def::Struct(s) => type_for_struct(db, s),
304 Def::Enum(e) => type_for_enum(db, e),
235 Def::Item => { 305 Def::Item => {
236 log::debug!("trying to get type for item of unknown type {:?}", def_id); 306 log::debug!("trying to get type for item of unknown type {:?}", def_id);
237 Ok(Ty::Unknown) 307 Ok(Ty::Unknown)
@@ -239,6 +309,33 @@ pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> {
239 } 309 }
240} 310}
241 311
312pub(super) fn type_for_field(
313 db: &impl HirDatabase,
314 def_id: DefId,
315 field: SmolStr,
316) -> Cancelable<Ty> {
317 let def = def_id.resolve(db)?;
318 let variant_data = match def {
319 Def::Struct(s) => {
320 let variant_data = s.variant_data(db)?;
321 variant_data
322 }
323 // TODO: unions
324 // TODO: enum variants
325 _ => panic!(
326 "trying to get type for field in non-struct/variant {:?}",
327 def_id
328 ),
329 };
330 let module = def_id.module(db)?;
331 let type_ref = if let Some(tr) = variant_data.get_field_type_ref(&field) {
332 tr
333 } else {
334 return Ok(Ty::Unknown);
335 };
336 Ty::from_hir(db, &module, &type_ref)
337}
338
242#[derive(Clone, PartialEq, Eq, Debug)] 339#[derive(Clone, PartialEq, Eq, Debug)]
243pub struct InferenceResult { 340pub struct InferenceResult {
244 type_of: FxHashMap<LocalSyntaxPtr, Ty>, 341 type_of: FxHashMap<LocalSyntaxPtr, Ty>,
@@ -305,32 +402,54 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
305 }; 402 };
306 403
307 // resolve in module 404 // resolve in module
308 let resolved = ctry!(self.module.resolve_path(self.db, path)?); 405 let resolved = ctry!(self.module.resolve_path(self.db, &path)?.take_values());
309 let ty = self.db.type_for_def(resolved)?; 406 let ty = self.db.type_for_def(resolved)?;
310 // TODO we will need to add type variables for type parameters etc. here 407 // TODO we will need to add type variables for type parameters etc. here
311 Ok(Some(ty)) 408 Ok(Some(ty))
312 } 409 }
313 410
411 fn resolve_variant(
412 &self,
413 path: Option<ast::Path>,
414 ) -> Cancelable<(Ty, Option<Arc<VariantData>>)> {
415 let path = if let Some(path) = path.and_then(Path::from_ast) {
416 path
417 } else {
418 return Ok((Ty::Unknown, None));
419 };
420 let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path)?.take_types() {
421 def_id
422 } else {
423 return Ok((Ty::Unknown, None));
424 };
425 Ok(match def_id.resolve(self.db)? {
426 Def::Struct(s) => {
427 let struct_data = self.db.struct_data(def_id)?;
428 let ty = type_for_struct(self.db, s)?;
429 (ty, Some(struct_data.variant_data().clone()))
430 }
431 _ => (Ty::Unknown, None),
432 })
433 }
434
435 fn infer_expr_opt(&mut self, expr: Option<ast::Expr>) -> Cancelable<Ty> {
436 if let Some(e) = expr {
437 self.infer_expr(e)
438 } else {
439 Ok(Ty::Unknown)
440 }
441 }
442
314 fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> { 443 fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> {
315 let ty = match expr { 444 let ty = match expr {
316 ast::Expr::IfExpr(e) => { 445 ast::Expr::IfExpr(e) => {
317 if let Some(condition) = e.condition() { 446 if let Some(condition) = e.condition() {
318 if let Some(e) = condition.expr() { 447 // TODO if no pat, this should be bool
319 // TODO if no pat, this should be bool 448 self.infer_expr_opt(condition.expr())?;
320 self.infer_expr(e)?;
321 }
322 // TODO write type for pat 449 // TODO write type for pat
323 }; 450 };
324 let if_ty = if let Some(block) = e.then_branch() { 451 let if_ty = self.infer_block_opt(e.then_branch())?;
325 self.infer_block(block)? 452 let else_ty = self.infer_block_opt(e.else_branch())?;
326 } else {
327 Ty::Unknown
328 };
329 let else_ty = if let Some(block) = e.else_branch() {
330 self.infer_block(block)?
331 } else {
332 Ty::Unknown
333 };
334 if let Some(ty) = self.unify(&if_ty, &else_ty) { 453 if let Some(ty) = self.unify(&if_ty, &else_ty) {
335 ty 454 ty
336 } else { 455 } else {
@@ -338,62 +457,37 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
338 Ty::Unknown 457 Ty::Unknown
339 } 458 }
340 } 459 }
341 ast::Expr::BlockExpr(e) => { 460 ast::Expr::BlockExpr(e) => self.infer_block_opt(e.block())?,
342 if let Some(block) = e.block() {
343 self.infer_block(block)?
344 } else {
345 Ty::Unknown
346 }
347 }
348 ast::Expr::LoopExpr(e) => { 461 ast::Expr::LoopExpr(e) => {
349 if let Some(block) = e.loop_body() { 462 self.infer_block_opt(e.loop_body())?;
350 self.infer_block(block)?;
351 };
352 // TODO never, or the type of the break param 463 // TODO never, or the type of the break param
353 Ty::Unknown 464 Ty::Unknown
354 } 465 }
355 ast::Expr::WhileExpr(e) => { 466 ast::Expr::WhileExpr(e) => {
356 if let Some(condition) = e.condition() { 467 if let Some(condition) = e.condition() {
357 if let Some(e) = condition.expr() { 468 // TODO if no pat, this should be bool
358 // TODO if no pat, this should be bool 469 self.infer_expr_opt(condition.expr())?;
359 self.infer_expr(e)?;
360 }
361 // TODO write type for pat 470 // TODO write type for pat
362 }; 471 };
363 if let Some(block) = e.loop_body() { 472 self.infer_block_opt(e.loop_body())?;
364 // TODO
365 self.infer_block(block)?;
366 };
367 // TODO always unit? 473 // TODO always unit?
368 Ty::Unknown 474 Ty::Unknown
369 } 475 }
370 ast::Expr::ForExpr(e) => { 476 ast::Expr::ForExpr(e) => {
371 if let Some(expr) = e.iterable() { 477 let _iterable_ty = self.infer_expr_opt(e.iterable());
372 self.infer_expr(expr)?;
373 }
374 if let Some(_pat) = e.pat() { 478 if let Some(_pat) = e.pat() {
375 // TODO write type for pat 479 // TODO write type for pat
376 } 480 }
377 if let Some(block) = e.loop_body() { 481 self.infer_block_opt(e.loop_body())?;
378 self.infer_block(block)?;
379 }
380 // TODO always unit? 482 // TODO always unit?
381 Ty::Unknown 483 Ty::Unknown
382 } 484 }
383 ast::Expr::LambdaExpr(e) => { 485 ast::Expr::LambdaExpr(e) => {
384 let _body_ty = if let Some(body) = e.body() { 486 let _body_ty = self.infer_expr_opt(e.body())?;
385 self.infer_expr(body)?
386 } else {
387 Ty::Unknown
388 };
389 Ty::Unknown 487 Ty::Unknown
390 } 488 }
391 ast::Expr::CallExpr(e) => { 489 ast::Expr::CallExpr(e) => {
392 let callee_ty = if let Some(e) = e.expr() { 490 let callee_ty = self.infer_expr_opt(e.expr())?;
393 self.infer_expr(e)?
394 } else {
395 Ty::Unknown
396 };
397 if let Some(arg_list) = e.arg_list() { 491 if let Some(arg_list) = e.arg_list() {
398 for arg in arg_list.args() { 492 for arg in arg_list.args() {
399 // TODO unify / expect argument type 493 // TODO unify / expect argument type
@@ -410,11 +504,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
410 } 504 }
411 } 505 }
412 ast::Expr::MethodCallExpr(e) => { 506 ast::Expr::MethodCallExpr(e) => {
413 let _receiver_ty = if let Some(e) = e.expr() { 507 let _receiver_ty = self.infer_expr_opt(e.expr())?;
414 self.infer_expr(e)?
415 } else {
416 Ty::Unknown
417 };
418 if let Some(arg_list) = e.arg_list() { 508 if let Some(arg_list) = e.arg_list() {
419 for arg in arg_list.args() { 509 for arg in arg_list.args() {
420 // TODO unify / expect argument type 510 // TODO unify / expect argument type
@@ -424,20 +514,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
424 Ty::Unknown 514 Ty::Unknown
425 } 515 }
426 ast::Expr::MatchExpr(e) => { 516 ast::Expr::MatchExpr(e) => {
427 let _ty = if let Some(match_expr) = e.expr() { 517 let _ty = self.infer_expr_opt(e.expr())?;
428 self.infer_expr(match_expr)?
429 } else {
430 Ty::Unknown
431 };
432 if let Some(match_arm_list) = e.match_arm_list() { 518 if let Some(match_arm_list) = e.match_arm_list() {
433 for arm in match_arm_list.arms() { 519 for arm in match_arm_list.arms() {
434 // TODO type the bindings in pat 520 // TODO type the bindings in pat
435 // TODO type the guard 521 // TODO type the guard
436 let _ty = if let Some(e) = arm.expr() { 522 let _ty = self.infer_expr_opt(arm.expr())?;
437 self.infer_expr(e)?
438 } else {
439 Ty::Unknown
440 };
441 } 523 }
442 // TODO unify all the match arm types 524 // TODO unify all the match arm types
443 Ty::Unknown 525 Ty::Unknown
@@ -450,68 +532,78 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
450 ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown), 532 ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown),
451 ast::Expr::ContinueExpr(_e) => Ty::Never, 533 ast::Expr::ContinueExpr(_e) => Ty::Never,
452 ast::Expr::BreakExpr(_e) => Ty::Never, 534 ast::Expr::BreakExpr(_e) => Ty::Never,
453 ast::Expr::ParenExpr(e) => { 535 ast::Expr::ParenExpr(e) => self.infer_expr_opt(e.expr())?,
454 if let Some(e) = e.expr() {
455 self.infer_expr(e)?
456 } else {
457 Ty::Unknown
458 }
459 }
460 ast::Expr::Label(_e) => Ty::Unknown, 536 ast::Expr::Label(_e) => Ty::Unknown,
461 ast::Expr::ReturnExpr(e) => { 537 ast::Expr::ReturnExpr(e) => {
462 if let Some(e) = e.expr() { 538 self.infer_expr_opt(e.expr())?;
463 // TODO unify with return type
464 self.infer_expr(e)?;
465 };
466 Ty::Never 539 Ty::Never
467 } 540 }
468 ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => { 541 ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => {
469 // Can this even occur outside of a match expression? 542 // Can this even occur outside of a match expression?
470 Ty::Unknown 543 Ty::Unknown
471 } 544 }
472 ast::Expr::StructLit(_e) => Ty::Unknown, 545 ast::Expr::StructLit(e) => {
546 let (ty, _variant_data) = self.resolve_variant(e.path())?;
547 if let Some(nfl) = e.named_field_list() {
548 for field in nfl.fields() {
549 // TODO unify with / expect field type
550 self.infer_expr_opt(field.expr())?;
551 }
552 }
553 ty
554 }
473 ast::Expr::NamedFieldList(_) | ast::Expr::NamedField(_) => { 555 ast::Expr::NamedFieldList(_) | ast::Expr::NamedField(_) => {
474 // Can this even occur outside of a struct literal? 556 // Can this even occur outside of a struct literal?
475 Ty::Unknown 557 Ty::Unknown
476 } 558 }
477 ast::Expr::IndexExpr(_e) => Ty::Unknown, 559 ast::Expr::IndexExpr(_e) => Ty::Unknown,
478 ast::Expr::FieldExpr(_e) => Ty::Unknown, 560 ast::Expr::FieldExpr(e) => {
479 ast::Expr::TryExpr(e) => { 561 let receiver_ty = self.infer_expr_opt(e.expr())?;
480 let _inner_ty = if let Some(e) = e.expr() { 562 if let Some(nr) = e.name_ref() {
481 self.infer_expr(e)? 563 let text = nr.text();
564 match receiver_ty {
565 Ty::Tuple(fields) => {
566 let i = text.parse::<usize>().ok();
567 i.and_then(|i| fields.get(i).cloned())
568 .unwrap_or(Ty::Unknown)
569 }
570 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, text)?,
571 _ => Ty::Unknown,
572 }
482 } else { 573 } else {
483 Ty::Unknown 574 Ty::Unknown
484 }; 575 }
576 }
577 ast::Expr::TryExpr(e) => {
578 let _inner_ty = self.infer_expr_opt(e.expr())?;
485 Ty::Unknown 579 Ty::Unknown
486 } 580 }
487 ast::Expr::CastExpr(e) => { 581 ast::Expr::CastExpr(e) => {
488 let _inner_ty = if let Some(e) = e.expr() { 582 let _inner_ty = self.infer_expr_opt(e.expr())?;
489 self.infer_expr(e)? 583 let cast_ty = Ty::from_ast_opt(self.db, &self.module, e.type_ref())?;
490 } else {
491 Ty::Unknown
492 };
493 let cast_ty = e
494 .type_ref()
495 .map(|t| Ty::new(self.db, t))
496 .unwrap_or(Ok(Ty::Unknown))?;
497 // TODO do the coercion... 584 // TODO do the coercion...
498 cast_ty 585 cast_ty
499 } 586 }
500 ast::Expr::RefExpr(e) => { 587 ast::Expr::RefExpr(e) => {
501 let _inner_ty = if let Some(e) = e.expr() { 588 let inner_ty = self.infer_expr_opt(e.expr())?;
502 self.infer_expr(e)? 589 let m = Mutability::from_mutable(e.is_mut());
503 } else { 590 // TODO reference coercions etc.
504 Ty::Unknown 591 Ty::Ref(Arc::new(inner_ty), m)
505 };
506 Ty::Unknown
507 } 592 }
508 ast::Expr::PrefixExpr(e) => { 593 ast::Expr::PrefixExpr(e) => {
509 let _inner_ty = if let Some(e) = e.expr() { 594 let inner_ty = self.infer_expr_opt(e.expr())?;
510 self.infer_expr(e)? 595 match e.op() {
511 } else { 596 Some(PrefixOp::Deref) => {
512 Ty::Unknown 597 match inner_ty {
513 }; 598 // builtin deref:
514 Ty::Unknown 599 Ty::Ref(ref_inner, _) => (*ref_inner).clone(),
600 Ty::RawPtr(ptr_inner, _) => (*ptr_inner).clone(),
601 // TODO Deref::deref
602 _ => Ty::Unknown,
603 }
604 }
605 _ => Ty::Unknown,
606 }
515 } 607 }
516 ast::Expr::RangeExpr(_e) => Ty::Unknown, 608 ast::Expr::RangeExpr(_e) => Ty::Unknown,
517 ast::Expr::BinExpr(_e) => Ty::Unknown, 609 ast::Expr::BinExpr(_e) => Ty::Unknown,
@@ -521,15 +613,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
521 Ok(ty) 613 Ok(ty)
522 } 614 }
523 615
616 fn infer_block_opt(&mut self, node: Option<ast::Block>) -> Cancelable<Ty> {
617 if let Some(b) = node {
618 self.infer_block(b)
619 } else {
620 Ok(Ty::Unknown)
621 }
622 }
623
524 fn infer_block(&mut self, node: ast::Block) -> Cancelable<Ty> { 624 fn infer_block(&mut self, node: ast::Block) -> Cancelable<Ty> {
525 for stmt in node.statements() { 625 for stmt in node.statements() {
526 match stmt { 626 match stmt {
527 ast::Stmt::LetStmt(stmt) => { 627 ast::Stmt::LetStmt(stmt) => {
528 let decl_ty = if let Some(type_ref) = stmt.type_ref() { 628 let decl_ty = Ty::from_ast_opt(self.db, &self.module, stmt.type_ref())?;
529 Ty::new(self.db, type_ref)?
530 } else {
531 Ty::Unknown
532 };
533 let ty = if let Some(expr) = stmt.initializer() { 629 let ty = if let Some(expr) = stmt.initializer() {
534 // TODO pass expectation 630 // TODO pass expectation
535 let expr_ty = self.infer_expr(expr)?; 631 let expr_ty = self.infer_expr(expr)?;
@@ -544,9 +640,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
544 }; 640 };
545 } 641 }
546 ast::Stmt::ExprStmt(expr_stmt) => { 642 ast::Stmt::ExprStmt(expr_stmt) => {
547 if let Some(expr) = expr_stmt.expr() { 643 self.infer_expr_opt(expr_stmt.expr())?;
548 self.infer_expr(expr)?;
549 }
550 } 644 }
551 } 645 }
552 } 646 }
@@ -576,7 +670,7 @@ pub fn infer(db: &impl HirDatabase, function: Function) -> Cancelable<InferenceR
576 continue; 670 continue;
577 }; 671 };
578 if let Some(type_ref) = param.type_ref() { 672 if let Some(type_ref) = param.type_ref() {
579 let ty = Ty::new(db, type_ref)?; 673 let ty = Ty::from_ast(db, &ctx.module, type_ref)?;
580 ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty); 674 ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty);
581 } else { 675 } else {
582 // TODO self param 676 // TODO self param