aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/ty.rs162
1 files changed, 37 insertions, 125 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 83da13f1a..7b8dbe6b7 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -239,19 +239,11 @@ pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> {
239 .param_list() 239 .param_list()
240 .map(|pl| { 240 .map(|pl| {
241 pl.params() 241 pl.params()
242 .map(|p| { 242 .map(|p| Ty::new_opt(db, &module, p.type_ref()))
243 p.type_ref()
244 .map(|t| Ty::new(db, &module, t))
245 .unwrap_or(Ok(Ty::Unknown))
246 })
247 .collect() 243 .collect()
248 }) 244 })
249 .unwrap_or_else(|| Ok(Vec::new()))?; 245 .unwrap_or_else(|| Ok(Vec::new()))?;
250 let output = node 246 let output = Ty::new_opt(db, &module, node.ret_type().and_then(|rt| rt.type_ref()))?;
251 .ret_type()
252 .and_then(|rt| rt.type_ref())
253 .map(|t| Ty::new(db, &module, t))
254 .unwrap_or(Ok(Ty::Unknown))?;
255 let sig = FnSig { input, output }; 247 let sig = FnSig { input, output };
256 Ok(Ty::FnPtr(Arc::new(sig))) 248 Ok(Ty::FnPtr(Arc::new(sig)))
257} 249}
@@ -263,11 +255,6 @@ pub fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Cancelable<Ty> {
263 }) 255 })
264} 256}
265 257
266// TODO this should probably be per namespace (i.e. types vs. values), since for
267// a tuple struct `struct Foo(Bar)`, Foo has function type as a value, but
268// defines the struct type Foo when used in the type namespace. rustc has a
269// separate DefId for the constructor, but with the current DefId approach, that
270// seems complicated.
271pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { 258pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> {
272 let def = def_id.resolve(db)?; 259 let def = def_id.resolve(db)?;
273 match def { 260 match def {
@@ -396,22 +383,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
396 let ty = match expr { 383 let ty = match expr {
397 ast::Expr::IfExpr(e) => { 384 ast::Expr::IfExpr(e) => {
398 if let Some(condition) = e.condition() { 385 if let Some(condition) = e.condition() {
399 if let Some(e) = condition.expr() { 386 // TODO if no pat, this should be bool
400 // TODO if no pat, this should be bool 387 self.infer_expr_opt(condition.expr())?;
401 self.infer_expr(e)?;
402 }
403 // TODO write type for pat 388 // TODO write type for pat
404 }; 389 };
405 let if_ty = if let Some(block) = e.then_branch() { 390 let if_ty = self.infer_block_opt(e.then_branch())?;
406 self.infer_block(block)? 391 let else_ty = self.infer_block_opt(e.else_branch())?;
407 } else {
408 Ty::Unknown
409 };
410 let else_ty = if let Some(block) = e.else_branch() {
411 self.infer_block(block)?
412 } else {
413 Ty::Unknown
414 };
415 if let Some(ty) = self.unify(&if_ty, &else_ty) { 392 if let Some(ty) = self.unify(&if_ty, &else_ty) {
416 ty 393 ty
417 } else { 394 } else {
@@ -419,62 +396,37 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
419 Ty::Unknown 396 Ty::Unknown
420 } 397 }
421 } 398 }
422 ast::Expr::BlockExpr(e) => { 399 ast::Expr::BlockExpr(e) => self.infer_block_opt(e.block())?,
423 if let Some(block) = e.block() {
424 self.infer_block(block)?
425 } else {
426 Ty::Unknown
427 }
428 }
429 ast::Expr::LoopExpr(e) => { 400 ast::Expr::LoopExpr(e) => {
430 if let Some(block) = e.loop_body() { 401 self.infer_block_opt(e.loop_body())?;
431 self.infer_block(block)?;
432 };
433 // TODO never, or the type of the break param 402 // TODO never, or the type of the break param
434 Ty::Unknown 403 Ty::Unknown
435 } 404 }
436 ast::Expr::WhileExpr(e) => { 405 ast::Expr::WhileExpr(e) => {
437 if let Some(condition) = e.condition() { 406 if let Some(condition) = e.condition() {
438 if let Some(e) = condition.expr() { 407 // TODO if no pat, this should be bool
439 // TODO if no pat, this should be bool 408 self.infer_expr_opt(condition.expr())?;
440 self.infer_expr(e)?;
441 }
442 // TODO write type for pat 409 // TODO write type for pat
443 }; 410 };
444 if let Some(block) = e.loop_body() { 411 self.infer_block_opt(e.loop_body())?;
445 // TODO
446 self.infer_block(block)?;
447 };
448 // TODO always unit? 412 // TODO always unit?
449 Ty::Unknown 413 Ty::Unknown
450 } 414 }
451 ast::Expr::ForExpr(e) => { 415 ast::Expr::ForExpr(e) => {
452 if let Some(expr) = e.iterable() { 416 let _iterable_ty = self.infer_expr_opt(e.iterable());
453 self.infer_expr(expr)?;
454 }
455 if let Some(_pat) = e.pat() { 417 if let Some(_pat) = e.pat() {
456 // TODO write type for pat 418 // TODO write type for pat
457 } 419 }
458 if let Some(block) = e.loop_body() { 420 self.infer_block_opt(e.loop_body())?;
459 self.infer_block(block)?;
460 }
461 // TODO always unit? 421 // TODO always unit?
462 Ty::Unknown 422 Ty::Unknown
463 } 423 }
464 ast::Expr::LambdaExpr(e) => { 424 ast::Expr::LambdaExpr(e) => {
465 let _body_ty = if let Some(body) = e.body() { 425 let _body_ty = self.infer_expr_opt(e.body())?;
466 self.infer_expr(body)?
467 } else {
468 Ty::Unknown
469 };
470 Ty::Unknown 426 Ty::Unknown
471 } 427 }
472 ast::Expr::CallExpr(e) => { 428 ast::Expr::CallExpr(e) => {
473 let callee_ty = if let Some(e) = e.expr() { 429 let callee_ty = self.infer_expr_opt(e.expr())?;
474 self.infer_expr(e)?
475 } else {
476 Ty::Unknown
477 };
478 if let Some(arg_list) = e.arg_list() { 430 if let Some(arg_list) = e.arg_list() {
479 for arg in arg_list.args() { 431 for arg in arg_list.args() {
480 // TODO unify / expect argument type 432 // TODO unify / expect argument type
@@ -491,11 +443,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
491 } 443 }
492 } 444 }
493 ast::Expr::MethodCallExpr(e) => { 445 ast::Expr::MethodCallExpr(e) => {
494 let _receiver_ty = if let Some(e) = e.expr() { 446 let _receiver_ty = self.infer_expr_opt(e.expr())?;
495 self.infer_expr(e)?
496 } else {
497 Ty::Unknown
498 };
499 if let Some(arg_list) = e.arg_list() { 447 if let Some(arg_list) = e.arg_list() {
500 for arg in arg_list.args() { 448 for arg in arg_list.args() {
501 // TODO unify / expect argument type 449 // TODO unify / expect argument type
@@ -505,20 +453,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
505 Ty::Unknown 453 Ty::Unknown
506 } 454 }
507 ast::Expr::MatchExpr(e) => { 455 ast::Expr::MatchExpr(e) => {
508 let _ty = if let Some(match_expr) = e.expr() { 456 let _ty = self.infer_expr_opt(e.expr())?;
509 self.infer_expr(match_expr)?
510 } else {
511 Ty::Unknown
512 };
513 if let Some(match_arm_list) = e.match_arm_list() { 457 if let Some(match_arm_list) = e.match_arm_list() {
514 for arm in match_arm_list.arms() { 458 for arm in match_arm_list.arms() {
515 // TODO type the bindings in pat 459 // TODO type the bindings in pat
516 // TODO type the guard 460 // TODO type the guard
517 let _ty = if let Some(e) = arm.expr() { 461 let _ty = self.infer_expr_opt(arm.expr())?;
518 self.infer_expr(e)?
519 } else {
520 Ty::Unknown
521 };
522 } 462 }
523 // TODO unify all the match arm types 463 // TODO unify all the match arm types
524 Ty::Unknown 464 Ty::Unknown
@@ -531,19 +471,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
531 ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown), 471 ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown),
532 ast::Expr::ContinueExpr(_e) => Ty::Never, 472 ast::Expr::ContinueExpr(_e) => Ty::Never,
533 ast::Expr::BreakExpr(_e) => Ty::Never, 473 ast::Expr::BreakExpr(_e) => Ty::Never,
534 ast::Expr::ParenExpr(e) => { 474 ast::Expr::ParenExpr(e) => self.infer_expr_opt(e.expr())?,
535 if let Some(e) = e.expr() {
536 self.infer_expr(e)?
537 } else {
538 Ty::Unknown
539 }
540 }
541 ast::Expr::Label(_e) => Ty::Unknown, 475 ast::Expr::Label(_e) => Ty::Unknown,
542 ast::Expr::ReturnExpr(e) => { 476 ast::Expr::ReturnExpr(e) => {
543 if let Some(e) = e.expr() { 477 self.infer_expr_opt(e.expr())?;
544 // TODO unify with / expect return type
545 self.infer_expr(e)?;
546 };
547 Ty::Never 478 Ty::Never
548 } 479 }
549 ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => { 480 ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => {
@@ -554,10 +485,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
554 let (ty, _variant_data) = self.resolve_variant(e.path())?; 485 let (ty, _variant_data) = self.resolve_variant(e.path())?;
555 if let Some(nfl) = e.named_field_list() { 486 if let Some(nfl) = e.named_field_list() {
556 for field in nfl.fields() { 487 for field in nfl.fields() {
557 if let Some(e) = field.expr() { 488 // TODO unify with / expect field type
558 // TODO unify with / expect field type 489 self.infer_expr_opt(field.expr())?;
559 self.infer_expr(e)?;
560 }
561 } 490 }
562 } 491 }
563 ty 492 ty
@@ -592,40 +521,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
592 } 521 }
593 } 522 }
594 ast::Expr::TryExpr(e) => { 523 ast::Expr::TryExpr(e) => {
595 let _inner_ty = if let Some(e) = e.expr() { 524 let _inner_ty = self.infer_expr_opt(e.expr())?;
596 self.infer_expr(e)?
597 } else {
598 Ty::Unknown
599 };
600 Ty::Unknown 525 Ty::Unknown
601 } 526 }
602 ast::Expr::CastExpr(e) => { 527 ast::Expr::CastExpr(e) => {
603 let _inner_ty = if let Some(e) = e.expr() { 528 let _inner_ty = self.infer_expr_opt(e.expr())?;
604 self.infer_expr(e)? 529 let cast_ty = Ty::new_opt(self.db, &self.module, e.type_ref())?;
605 } else {
606 Ty::Unknown
607 };
608 let cast_ty = e
609 .type_ref()
610 .map(|t| Ty::new(self.db, &self.module, t))
611 .unwrap_or(Ok(Ty::Unknown))?;
612 // TODO do the coercion... 530 // TODO do the coercion...
613 cast_ty 531 cast_ty
614 } 532 }
615 ast::Expr::RefExpr(e) => { 533 ast::Expr::RefExpr(e) => {
616 let _inner_ty = if let Some(e) = e.expr() { 534 let _inner_ty = self.infer_expr_opt(e.expr())?;
617 self.infer_expr(e)?
618 } else {
619 Ty::Unknown
620 };
621 Ty::Unknown 535 Ty::Unknown
622 } 536 }
623 ast::Expr::PrefixExpr(e) => { 537 ast::Expr::PrefixExpr(e) => {
624 let _inner_ty = if let Some(e) = e.expr() { 538 let _inner_ty = self.infer_expr_opt(e.expr())?;
625 self.infer_expr(e)?
626 } else {
627 Ty::Unknown
628 };
629 Ty::Unknown 539 Ty::Unknown
630 } 540 }
631 ast::Expr::RangeExpr(_e) => Ty::Unknown, 541 ast::Expr::RangeExpr(_e) => Ty::Unknown,
@@ -636,15 +546,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
636 Ok(ty) 546 Ok(ty)
637 } 547 }
638 548
549 fn infer_block_opt(&mut self, node: Option<ast::Block>) -> Cancelable<Ty> {
550 if let Some(b) = node {
551 self.infer_block(b)
552 } else {
553 Ok(Ty::Unknown)
554 }
555 }
556
639 fn infer_block(&mut self, node: ast::Block) -> Cancelable<Ty> { 557 fn infer_block(&mut self, node: ast::Block) -> Cancelable<Ty> {
640 for stmt in node.statements() { 558 for stmt in node.statements() {
641 match stmt { 559 match stmt {
642 ast::Stmt::LetStmt(stmt) => { 560 ast::Stmt::LetStmt(stmt) => {
643 let decl_ty = if let Some(type_ref) = stmt.type_ref() { 561 let decl_ty = Ty::new_opt(self.db, &self.module, stmt.type_ref())?;
644 Ty::new(self.db, &self.module, type_ref)?
645 } else {
646 Ty::Unknown
647 };
648 let ty = if let Some(expr) = stmt.initializer() { 562 let ty = if let Some(expr) = stmt.initializer() {
649 // TODO pass expectation 563 // TODO pass expectation
650 let expr_ty = self.infer_expr(expr)?; 564 let expr_ty = self.infer_expr(expr)?;
@@ -659,9 +573,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
659 }; 573 };
660 } 574 }
661 ast::Stmt::ExprStmt(expr_stmt) => { 575 ast::Stmt::ExprStmt(expr_stmt) => {
662 if let Some(expr) = expr_stmt.expr() { 576 self.infer_expr_opt(expr_stmt.expr())?;
663 self.infer_expr(expr)?;
664 }
665 } 577 }
666 } 578 }
667 } 579 }