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.rs195
1 files changed, 127 insertions, 68 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 615a1caed..13ee6cb27 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -5,21 +5,17 @@ mod tests;
5use std::sync::Arc; 5use std::sync::Arc;
6use std::fmt; 6use std::fmt;
7 7
8use log;
8use rustc_hash::{FxHashMap}; 9use rustc_hash::{FxHashMap};
9 10
10use ra_db::LocalSyntaxPtr; 11use ra_db::{LocalSyntaxPtr, Cancelable};
11use ra_syntax::{ 12use ra_syntax::{
12 SmolStr, 13 SmolStr,
13 ast::{self, AstNode, LoopBodyOwner, ArgListOwner}, 14 ast::{self, AstNode, LoopBodyOwner, ArgListOwner},
14 SyntaxNodeRef 15 SyntaxNodeRef
15}; 16};
16 17
17use crate::{ 18use crate::{Def, DefId, FnScopes, Module, Function, Path, db::HirDatabase};
18 FnScopes,
19 db::HirDatabase,
20};
21
22// pub(crate) type TypeId = Id<Ty>;
23 19
24#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 20#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
25pub enum Ty { 21pub enum Ty {
@@ -65,18 +61,6 @@ pub enum Ty {
65 /// `&'a mut T` or `&'a T`. 61 /// `&'a mut T` or `&'a T`.
66 // Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability), 62 // Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability),
67 63
68 /// The anonymous type of a function declaration/definition. Each
69 /// function has a unique type, which is output (for a function
70 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
71 ///
72 /// For example the type of `bar` here:
73 ///
74 /// ```rust
75 /// fn foo() -> i32 { 1 }
76 /// let bar = foo; // bar: fn() -> i32 {foo}
77 /// ```
78 // FnDef(DefId, &'tcx Substs<'tcx>),
79
80 /// A pointer to a function. Written as `fn() -> i32`. 64 /// A pointer to a function. Written as `fn() -> i32`.
81 /// 65 ///
82 /// For example the type of `bar` here: 66 /// For example the type of `bar` here:
@@ -85,7 +69,7 @@ pub enum Ty {
85 /// fn foo() -> i32 { 1 } 69 /// fn foo() -> i32 { 1 }
86 /// let bar: fn() -> i32 = foo; 70 /// let bar: fn() -> i32 = foo;
87 /// ``` 71 /// ```
88 // FnPtr(PolyFnSig<'tcx>), 72 FnPtr(Arc<FnSig>),
89 73
90 /// A trait, defined with `trait`. 74 /// A trait, defined with `trait`.
91 // Dynamic(Binder<&'tcx List<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>), 75 // Dynamic(Binder<&'tcx List<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
@@ -139,6 +123,12 @@ pub enum Ty {
139 123
140type TyRef = Arc<Ty>; 124type TyRef = Arc<Ty>;
141 125
126#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
127pub struct FnSig {
128 input: Vec<Ty>,
129 output: Ty,
130}
131
142impl Ty { 132impl Ty {
143 pub fn new(node: ast::TypeRef) -> Self { 133 pub fn new(node: ast::TypeRef) -> Self {
144 use ra_syntax::ast::TypeRef::*; 134 use ra_syntax::ast::TypeRef::*;
@@ -208,11 +198,55 @@ impl fmt::Display for Ty {
208 } 198 }
209 write!(f, ")") 199 write!(f, ")")
210 } 200 }
201 Ty::FnPtr(sig) => {
202 write!(f, "fn(")?;
203 for t in &sig.input {
204 write!(f, "{},", t)?;
205 }
206 write!(f, ") -> {}", sig.output)
207 }
211 Ty::Unknown => write!(f, "[unknown]"), 208 Ty::Unknown => write!(f, "[unknown]"),
212 } 209 }
213 } 210 }
214} 211}
215 212
213pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> {
214 eprintln!("type_for_fn {:?}", f.fn_id);
215 let syntax = f.syntax(db);
216 let node = syntax.borrowed();
217 // TODO we ignore type parameters for now
218 let input = node
219 .param_list()
220 .map(|pl| {
221 pl.params()
222 .map(|p| p.type_ref().map(|t| Ty::new(t)).unwrap_or(Ty::Unknown))
223 .collect()
224 })
225 .unwrap_or_else(Vec::new);
226 let output = node
227 .ret_type()
228 .and_then(|rt| rt.type_ref())
229 .map(|t| Ty::new(t))
230 .unwrap_or(Ty::Unknown);
231 let sig = FnSig { input, output };
232 Ok(Ty::FnPtr(Arc::new(sig)))
233}
234
235pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> {
236 let def = def_id.resolve(db)?;
237 match def {
238 Def::Module(..) => {
239 log::debug!("trying to get type for module {:?}", def_id);
240 Ok(Ty::Unknown)
241 }
242 Def::Function(f) => type_for_fn(db, f),
243 Def::Item => {
244 log::debug!("trying to get type for item of unknown type {:?}", def_id);
245 Ok(Ty::Unknown)
246 }
247 }
248}
249
216#[derive(Clone, PartialEq, Eq, Debug)] 250#[derive(Clone, PartialEq, Eq, Debug)]
217pub struct InferenceResult { 251pub struct InferenceResult {
218 type_for: FxHashMap<LocalSyntaxPtr, Ty>, 252 type_for: FxHashMap<LocalSyntaxPtr, Ty>,
@@ -224,18 +258,22 @@ impl InferenceResult {
224 } 258 }
225} 259}
226 260
227#[derive(Clone, PartialEq, Eq, Debug)] 261#[derive(Clone, Debug)]
228pub struct InferenceContext { 262pub struct InferenceContext<'a, D: HirDatabase> {
263 db: &'a D,
229 scopes: Arc<FnScopes>, 264 scopes: Arc<FnScopes>,
265 module: Module,
230 // TODO unification tables... 266 // TODO unification tables...
231 type_for: FxHashMap<LocalSyntaxPtr, Ty>, 267 type_for: FxHashMap<LocalSyntaxPtr, Ty>,
232} 268}
233 269
234impl InferenceContext { 270impl<'a, D: HirDatabase> InferenceContext<'a, D> {
235 fn new(scopes: Arc<FnScopes>) -> Self { 271 fn new(db: &'a D, scopes: Arc<FnScopes>, module: Module) -> Self {
236 InferenceContext { 272 InferenceContext {
237 type_for: FxHashMap::default(), 273 type_for: FxHashMap::default(),
274 db,
238 scopes, 275 scopes,
276 module,
239 } 277 }
240 } 278 }
241 279
@@ -262,36 +300,42 @@ impl InferenceContext {
262 self.unify(ty1, ty2) 300 self.unify(ty1, ty2)
263 } 301 }
264 302
265 fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Option<Ty> { 303 fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Cancelable<Option<Ty>> {
266 let p = expr.path()?; 304 let ast_path = ctry!(expr.path());
267 if p.qualifier().is_none() { 305 let path = ctry!(Path::from_ast(ast_path));
268 let name = p.segment().and_then(|s| s.name_ref())?; 306 if path.is_ident() {
269 let scope_entry = self.scopes.resolve_local_name(name)?; 307 // resolve locally
270 let ty = self.type_for.get(&scope_entry.ptr())?; 308 let name = ctry!(ast_path.segment().and_then(|s| s.name_ref()));
271 Some(ty.clone()) 309 if let Some(scope_entry) = self.scopes.resolve_local_name(name) {
272 } else { 310 let ty = ctry!(self.type_for.get(&scope_entry.ptr()));
273 // TODO resolve path 311 return Ok(Some(ty.clone()));
274 Some(Ty::Unknown) 312 };
275 } 313 };
314
315 // resolve in module
316 let resolved = ctry!(self.module.resolve_path(self.db, path)?);
317 let ty = self.db.type_for_def(resolved)?;
318 // TODO we will need to add type variables for type parameters etc. here
319 Ok(Some(ty))
276 } 320 }
277 321
278 fn infer_expr(&mut self, expr: ast::Expr) -> Ty { 322 fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> {
279 let ty = match expr { 323 let ty = match expr {
280 ast::Expr::IfExpr(e) => { 324 ast::Expr::IfExpr(e) => {
281 if let Some(condition) = e.condition() { 325 if let Some(condition) = e.condition() {
282 if let Some(e) = condition.expr() { 326 if let Some(e) = condition.expr() {
283 // TODO if no pat, this should be bool 327 // TODO if no pat, this should be bool
284 self.infer_expr(e); 328 self.infer_expr(e)?;
285 } 329 }
286 // TODO write type for pat 330 // TODO write type for pat
287 }; 331 };
288 let if_ty = if let Some(block) = e.then_branch() { 332 let if_ty = if let Some(block) = e.then_branch() {
289 self.infer_block(block) 333 self.infer_block(block)?
290 } else { 334 } else {
291 Ty::Unknown 335 Ty::Unknown
292 }; 336 };
293 let else_ty = if let Some(block) = e.else_branch() { 337 let else_ty = if let Some(block) = e.else_branch() {
294 self.infer_block(block) 338 self.infer_block(block)?
295 } else { 339 } else {
296 Ty::Unknown 340 Ty::Unknown
297 }; 341 };
@@ -304,14 +348,14 @@ impl InferenceContext {
304 } 348 }
305 ast::Expr::BlockExpr(e) => { 349 ast::Expr::BlockExpr(e) => {
306 if let Some(block) = e.block() { 350 if let Some(block) = e.block() {
307 self.infer_block(block) 351 self.infer_block(block)?
308 } else { 352 } else {
309 Ty::Unknown 353 Ty::Unknown
310 } 354 }
311 } 355 }
312 ast::Expr::LoopExpr(e) => { 356 ast::Expr::LoopExpr(e) => {
313 if let Some(block) = e.loop_body() { 357 if let Some(block) = e.loop_body() {
314 self.infer_block(block); 358 self.infer_block(block)?;
315 }; 359 };
316 // TODO never, or the type of the break param 360 // TODO never, or the type of the break param
317 Ty::Unknown 361 Ty::Unknown
@@ -320,59 +364,69 @@ impl InferenceContext {
320 if let Some(condition) = e.condition() { 364 if let Some(condition) = e.condition() {
321 if let Some(e) = condition.expr() { 365 if let Some(e) = condition.expr() {
322 // TODO if no pat, this should be bool 366 // TODO if no pat, this should be bool
323 self.infer_expr(e); 367 self.infer_expr(e)?;
324 } 368 }
325 // TODO write type for pat 369 // TODO write type for pat
326 }; 370 };
327 if let Some(block) = e.loop_body() { 371 if let Some(block) = e.loop_body() {
328 // TODO 372 // TODO
329 self.infer_block(block); 373 self.infer_block(block)?;
330 }; 374 };
331 // TODO always unit? 375 // TODO always unit?
332 Ty::Unknown 376 Ty::Unknown
333 } 377 }
334 ast::Expr::ForExpr(e) => { 378 ast::Expr::ForExpr(e) => {
335 if let Some(expr) = e.iterable() { 379 if let Some(expr) = e.iterable() {
336 self.infer_expr(expr); 380 self.infer_expr(expr)?;
337 } 381 }
338 if let Some(_pat) = e.pat() { 382 if let Some(_pat) = e.pat() {
339 // TODO write type for pat 383 // TODO write type for pat
340 } 384 }
341 if let Some(block) = e.loop_body() { 385 if let Some(block) = e.loop_body() {
342 self.infer_block(block); 386 self.infer_block(block)?;
343 } 387 }
344 // TODO always unit? 388 // TODO always unit?
345 Ty::Unknown 389 Ty::Unknown
346 } 390 }
347 ast::Expr::LambdaExpr(e) => { 391 ast::Expr::LambdaExpr(e) => {
348 let _body_ty = if let Some(body) = e.body() { 392 let _body_ty = if let Some(body) = e.body() {
349 self.infer_expr(body) 393 self.infer_expr(body)?
350 } else { 394 } else {
351 Ty::Unknown 395 Ty::Unknown
352 }; 396 };
353 Ty::Unknown 397 Ty::Unknown
354 } 398 }
355 ast::Expr::CallExpr(e) => { 399 ast::Expr::CallExpr(e) => {
400 let _callee_ty = if let Some(e) = e.expr() {
401 self.infer_expr(e)?
402 } else {
403 Ty::Unknown
404 };
356 if let Some(arg_list) = e.arg_list() { 405 if let Some(arg_list) = e.arg_list() {
357 for arg in arg_list.args() { 406 for arg in arg_list.args() {
358 // TODO unify / expect argument type 407 // TODO unify / expect argument type
359 self.infer_expr(arg); 408 self.infer_expr(arg)?;
360 } 409 }
361 } 410 }
362 Ty::Unknown 411 Ty::Unknown
363 } 412 }
364 ast::Expr::MethodCallExpr(e) => { 413 ast::Expr::MethodCallExpr(e) => {
414 let _receiver_ty = if let Some(e) = e.expr() {
415 self.infer_expr(e)?
416 } else {
417 Ty::Unknown
418 };
365 if let Some(arg_list) = e.arg_list() { 419 if let Some(arg_list) = e.arg_list() {
366 for arg in arg_list.args() { 420 for arg in arg_list.args() {
367 // TODO unify / expect argument type 421 // TODO unify / expect argument type
368 self.infer_expr(arg); 422 self.infer_expr(arg)?;
369 } 423 }
370 } 424 }
371 Ty::Unknown 425 Ty::Unknown
372 } 426 }
373 ast::Expr::MatchExpr(e) => { 427 ast::Expr::MatchExpr(e) => {
374 let _ty = if let Some(match_expr) = e.expr() { 428 let _ty = if let Some(match_expr) = e.expr() {
375 self.infer_expr(match_expr) 429 self.infer_expr(match_expr)?
376 } else { 430 } else {
377 Ty::Unknown 431 Ty::Unknown
378 }; 432 };
@@ -381,7 +435,7 @@ impl InferenceContext {
381 // TODO type the bindings in pat 435 // TODO type the bindings in pat
382 // TODO type the guard 436 // TODO type the guard
383 let _ty = if let Some(e) = arm.expr() { 437 let _ty = if let Some(e) = arm.expr() {
384 self.infer_expr(e) 438 self.infer_expr(e)?
385 } else { 439 } else {
386 Ty::Unknown 440 Ty::Unknown
387 }; 441 };
@@ -394,12 +448,12 @@ impl InferenceContext {
394 } 448 }
395 ast::Expr::TupleExpr(_e) => Ty::Unknown, 449 ast::Expr::TupleExpr(_e) => Ty::Unknown,
396 ast::Expr::ArrayExpr(_e) => Ty::Unknown, 450 ast::Expr::ArrayExpr(_e) => Ty::Unknown,
397 ast::Expr::PathExpr(e) => self.infer_path_expr(e).unwrap_or(Ty::Unknown), 451 ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown),
398 ast::Expr::ContinueExpr(_e) => Ty::Never, 452 ast::Expr::ContinueExpr(_e) => Ty::Never,
399 ast::Expr::BreakExpr(_e) => Ty::Never, 453 ast::Expr::BreakExpr(_e) => Ty::Never,
400 ast::Expr::ParenExpr(e) => { 454 ast::Expr::ParenExpr(e) => {
401 if let Some(e) = e.expr() { 455 if let Some(e) = e.expr() {
402 self.infer_expr(e) 456 self.infer_expr(e)?
403 } else { 457 } else {
404 Ty::Unknown 458 Ty::Unknown
405 } 459 }
@@ -408,7 +462,7 @@ impl InferenceContext {
408 ast::Expr::ReturnExpr(e) => { 462 ast::Expr::ReturnExpr(e) => {
409 if let Some(e) = e.expr() { 463 if let Some(e) = e.expr() {
410 // TODO unify with return type 464 // TODO unify with return type
411 self.infer_expr(e); 465 self.infer_expr(e)?;
412 }; 466 };
413 Ty::Never 467 Ty::Never
414 } 468 }
@@ -425,7 +479,7 @@ impl InferenceContext {
425 ast::Expr::FieldExpr(_e) => Ty::Unknown, 479 ast::Expr::FieldExpr(_e) => Ty::Unknown,
426 ast::Expr::TryExpr(e) => { 480 ast::Expr::TryExpr(e) => {
427 let _inner_ty = if let Some(e) = e.expr() { 481 let _inner_ty = if let Some(e) = e.expr() {
428 self.infer_expr(e) 482 self.infer_expr(e)?
429 } else { 483 } else {
430 Ty::Unknown 484 Ty::Unknown
431 }; 485 };
@@ -433,7 +487,7 @@ impl InferenceContext {
433 } 487 }
434 ast::Expr::CastExpr(e) => { 488 ast::Expr::CastExpr(e) => {
435 let _inner_ty = if let Some(e) = e.expr() { 489 let _inner_ty = if let Some(e) = e.expr() {
436 self.infer_expr(e) 490 self.infer_expr(e)?
437 } else { 491 } else {
438 Ty::Unknown 492 Ty::Unknown
439 }; 493 };
@@ -443,7 +497,7 @@ impl InferenceContext {
443 } 497 }
444 ast::Expr::RefExpr(e) => { 498 ast::Expr::RefExpr(e) => {
445 let _inner_ty = if let Some(e) = e.expr() { 499 let _inner_ty = if let Some(e) = e.expr() {
446 self.infer_expr(e) 500 self.infer_expr(e)?
447 } else { 501 } else {
448 Ty::Unknown 502 Ty::Unknown
449 }; 503 };
@@ -451,7 +505,7 @@ impl InferenceContext {
451 } 505 }
452 ast::Expr::PrefixExpr(e) => { 506 ast::Expr::PrefixExpr(e) => {
453 let _inner_ty = if let Some(e) = e.expr() { 507 let _inner_ty = if let Some(e) = e.expr() {
454 self.infer_expr(e) 508 self.infer_expr(e)?
455 } else { 509 } else {
456 Ty::Unknown 510 Ty::Unknown
457 }; 511 };
@@ -462,10 +516,10 @@ impl InferenceContext {
462 ast::Expr::Literal(_e) => Ty::Unknown, 516 ast::Expr::Literal(_e) => Ty::Unknown,
463 }; 517 };
464 self.write_ty(expr.syntax(), ty.clone()); 518 self.write_ty(expr.syntax(), ty.clone());
465 ty 519 Ok(ty)
466 } 520 }
467 521
468 fn infer_block(&mut self, node: ast::Block) -> Ty { 522 fn infer_block(&mut self, node: ast::Block) -> Cancelable<Ty> {
469 for stmt in node.statements() { 523 for stmt in node.statements() {
470 match stmt { 524 match stmt {
471 ast::Stmt::LetStmt(stmt) => { 525 ast::Stmt::LetStmt(stmt) => {
@@ -476,7 +530,7 @@ impl InferenceContext {
476 }; 530 };
477 let ty = if let Some(expr) = stmt.initializer() { 531 let ty = if let Some(expr) = stmt.initializer() {
478 // TODO pass expectation 532 // TODO pass expectation
479 let expr_ty = self.infer_expr(expr); 533 let expr_ty = self.infer_expr(expr)?;
480 self.unify_with_coercion(&expr_ty, &decl_ty) 534 self.unify_with_coercion(&expr_ty, &decl_ty)
481 .unwrap_or(decl_ty) 535 .unwrap_or(decl_ty)
482 } else { 536 } else {
@@ -489,23 +543,28 @@ impl InferenceContext {
489 } 543 }
490 ast::Stmt::ExprStmt(expr_stmt) => { 544 ast::Stmt::ExprStmt(expr_stmt) => {
491 if let Some(expr) = expr_stmt.expr() { 545 if let Some(expr) = expr_stmt.expr() {
492 self.infer_expr(expr); 546 self.infer_expr(expr)?;
493 } 547 }
494 } 548 }
495 } 549 }
496 } 550 }
497 let ty = if let Some(expr) = node.expr() { 551 let ty = if let Some(expr) = node.expr() {
498 self.infer_expr(expr) 552 self.infer_expr(expr)?
499 } else { 553 } else {
500 Ty::unit() 554 Ty::unit()
501 }; 555 };
502 self.write_ty(node.syntax(), ty.clone()); 556 self.write_ty(node.syntax(), ty.clone());
503 ty 557 Ok(ty)
504 } 558 }
505} 559}
506 560
507pub fn infer(_db: &impl HirDatabase, node: ast::FnDef, scopes: Arc<FnScopes>) -> InferenceResult { 561pub fn infer(db: &impl HirDatabase, function: Function) -> Cancelable<InferenceResult> {
508 let mut ctx = InferenceContext::new(scopes); 562 let scopes = function.scopes(db);
563 let module = function.module(db)?;
564 let mut ctx = InferenceContext::new(db, scopes, module);
565
566 let syntax = function.syntax(db);
567 let node = syntax.borrowed();
509 568
510 if let Some(param_list) = node.param_list() { 569 if let Some(param_list) = node.param_list() {
511 for param in param_list.params() { 570 for param in param_list.params() {
@@ -529,12 +588,12 @@ pub fn infer(_db: &impl HirDatabase, node: ast::FnDef, scopes: Arc<FnScopes>) ->
529 // (see Expectation in rustc_typeck) 588 // (see Expectation in rustc_typeck)
530 589
531 if let Some(block) = node.body() { 590 if let Some(block) = node.body() {
532 ctx.infer_block(block); 591 ctx.infer_block(block)?;
533 } 592 }
534 593
535 // TODO 'resolve' the types: replace inference variables by their inferred results 594 // TODO 'resolve' the types: replace inference variables by their inferred results
536 595
537 InferenceResult { 596 Ok(InferenceResult {
538 type_for: ctx.type_for, 597 type_for: ctx.type_for,
539 } 598 })
540} 599}